cleanup.cpp 8.59 KB
Newer Older
1 2 3
/*********************************/
/* Module de nettoyage du schema */
/*********************************/
4 5

#include "fctsys.h"
6
#include "appl_wxstruct.h"
7
#include "common.h"
8
#include "confirm.h"
9 10 11 12 13 14 15 16 17
#include "program.h"
#include "libcmp.h"
#include "general.h"
#include "netlist.h"
#include "macros.h"
#include "protos.h"


/* Routines locales */
18 19
static int TstAlignSegment( EDA_DrawLineStruct* RefSegm,
                            EDA_DrawLineStruct* TstSegm );
20 21 22 23 24

/* Variable locales */


/*******************************************/
25
bool SCH_SCREEN::SchematicCleanUp( wxDC* DC )
26
/*******************************************/
27

28
/* Routine de nettoyage:
29 30 31
 *  - regroupe les segments de fils (ou de bus) alignes en 1 seul segment
 *  - Detecte les objets identiques superposes
 */
32
{
33
    SCH_ITEM* DrawList, * TstDrawList;
34 35 36 37 38 39
    int       flag;
    bool      Modify = FALSE;

    WinEDA_SchematicFrame* frame;

    frame = (WinEDA_SchematicFrame*)wxGetApp().GetTopWindow();
40 41

    DrawList = EEDrawList;
42
    for( ; DrawList != NULL; DrawList = DrawList->Next() )
43 44 45
    {
        if( DrawList->Type() == DRAW_SEGMENT_STRUCT_TYPE )
        {
46
            TstDrawList = DrawList->Next();
47 48 49 50 51
            while( TstDrawList )
            {
                if( TstDrawList->Type() == DRAW_SEGMENT_STRUCT_TYPE )
                {
                    flag = TstAlignSegment( (EDA_DrawLineStruct*) DrawList,
52
                                            (EDA_DrawLineStruct*) TstDrawList );
53 54 55 56 57 58 59 60 61 62
                    if( flag )  /* Suppression de TstSegm */
                    {
                        /* keep the bits set in .m_Flags, because the deleted segment can be flagged */
                        DrawList->m_Flags |= TstDrawList->m_Flags;
                        EraseStruct( TstDrawList, this );
                        SetRefreshReq();
                        TstDrawList = EEDrawList;
                        Modify = TRUE;
                    }
                    else
63
                        TstDrawList = TstDrawList->Next();
64 65
                }
                else
66
                    TstDrawList = TstDrawList->Next();
67 68 69 70
            }
        }
    }

71
    frame->TestDanglingEnds( EEDrawList, DC );
72
    return Modify;
73 74 75 76
}


/***********************************************/
77
void BreakSegmentOnJunction( SCH_SCREEN* Screen )
78
/************************************************/
79

80
/* Routine creant des debuts / fin de segment (BUS ou WIRES) sur les jonctions
81 82
 *  et les raccords
 */
83
{
84
    SCH_ITEM* DrawList;
85 86 87

    if( Screen == NULL )
    {
88 89
        DisplayError( NULL,
                      wxT( "BreakSegmentOnJunction() error: NULL screen" ) );
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
        return;
    }

    DrawList = Screen->EEDrawList;
    while( DrawList )
    {
        switch( DrawList->Type() )
        {
        case DRAW_JUNCTION_STRUCT_TYPE:
            #undef STRUCT
            #define STRUCT ( (DrawJunctionStruct*) DrawList )
            BreakSegment( Screen, STRUCT->m_Pos );
            break;

        case DRAW_BUSENTRY_STRUCT_TYPE:
            #undef STRUCT
            #define STRUCT ( (DrawBusEntryStruct*) DrawList )
            BreakSegment( Screen, STRUCT->m_Pos );
            BreakSegment( Screen, STRUCT->m_End() );
            break;

        case DRAW_SEGMENT_STRUCT_TYPE:
        case DRAW_NOCONNECT_STRUCT_TYPE:
113 114 115 116
        case TYPE_SCH_LABEL:
        case TYPE_SCH_GLOBALLABEL:
        case TYPE_SCH_HIERLABEL:
        case TYPE_SCH_COMPONENT:
117 118 119
        case DRAW_PICK_ITEM_STRUCT_TYPE:
        case DRAW_POLYLINE_STRUCT_TYPE:
        case DRAW_MARKER_STRUCT_TYPE:
120
        case TYPE_SCH_TEXT:
121
        case DRAW_SHEET_STRUCT_TYPE:
charras's avatar
charras committed
122
        case DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE:
123 124 125 126 127
            break;

        default:
            break;
        }
128
        DrawList = DrawList->Next();
129
    }
130 131 132 133
}


/*********************************************************/
134 135
DrawPickedStruct* BreakSegment( SCH_SCREEN* screen,
                                wxPoint breakpoint, bool PutInUndoList )
136
/*********************************************************/
137

138
/* Coupe un segment ( BUS, WIRE ) en 2 au point breakpoint,
139 140 141 142
 *  - si ce point est sur le segment
 *  - extremites non comprises
 *  If PutInUndoList == TRUE, create a list of modifictions, for undo command
 */
143
{
144 145 146 147 148 149 150 151 152 153 154 155 156 157
    EDA_BaseStruct* DrawList;
    EDA_DrawLineStruct* segment, * NewSegment;
    int ox, oy, fx, fy;
    DrawPickedStruct* List = NULL;

    DrawList = screen->EEDrawList;
    while( DrawList )
    {
        switch( DrawList->Type() )
        {
        case DRAW_SEGMENT_STRUCT_TYPE:
            segment = (EDA_DrawLineStruct*) DrawList;
            ox = segment->m_Start.x; oy = segment->m_Start.y;
            fx = segment->m_End.x; fy = segment->m_End.y;
158 159
            if( distance( fx - ox, fy - oy, breakpoint.x - ox, breakpoint.y -
                          oy, 0 ) == 0 )
160
                break;
161

162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
            /* Segment connecte: doit etre coupe en 2 si px,py n'est
             *  pas une extremite */
            if( (ox == breakpoint.x) && (oy == breakpoint.y ) )
                break;
            if( (fx == breakpoint.x) && (fy == breakpoint.y ) )
                break;
            /* Ici il faut couper le segment en 2 */
            if( PutInUndoList )         // First: put copy of the old segment in undo list
            {
                DrawPickedStruct* wrapper = new DrawPickedStruct();

                wrapper->m_Flags = IS_CHANGED;
                wrapper->m_PickedStruct = segment->GenCopy();
                wrapper->m_Image = segment;
                wrapper->m_PickedStruct->m_Image = segment;
177
                wrapper->SetNext( List );
178 179 180 181
                List = wrapper;
            }
            NewSegment = segment->GenCopy();
            NewSegment->m_Start = breakpoint;
182
            segment->m_End = NewSegment->m_Start;
183 184
            NewSegment->SetNext( segment->Next() );
            segment->SetNext( NewSegment );
185 186 187 188 189 190 191
            DrawList = NewSegment;
            if( PutInUndoList )
            {
                DrawPickedStruct* wrapper = new DrawPickedStruct();

                wrapper->m_Flags = IS_NEW;
                wrapper->m_Image = NewSegment;
192
                wrapper->SetNext( List );
193 194 195 196 197 198 199 200 201 202 203 204 205
                List = wrapper;
            }
            break;

        case DRAW_JUNCTION_STRUCT_TYPE:
        case DRAW_BUSENTRY_STRUCT_TYPE:
        case DRAW_POLYLINE_STRUCT_TYPE:
            break;

        default:
            break;
        }

206
        DrawList = DrawList->Next();
207 208 209 210
    }

    return List;
}
211 212 213


/***********************************************************/
214 215
static int TstAlignSegment( EDA_DrawLineStruct* RefSegm,
                            EDA_DrawLineStruct* TstSegm )
216 217 218
/***********************************************************/

/* Search if the 2 segments RefSegm and TstSegm are on a line.
219 220 221
 *  Retourn 0 if no
 *      1 if yes, and RefSegm is modified to be the equivalent segment
 */
222
{
223 224
    if( RefSegm == TstSegm )
        return 0;
225
    if( RefSegm->GetLayer() != TstSegm->GetLayer() )
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
        return 0;

    // search for a common end, and modify coordinates to ensure RefSegm->m_End == TstSegm->m_Start
    if( RefSegm->m_Start == TstSegm->m_Start )
    {
        if( RefSegm->m_End == TstSegm->m_End )          // trivial case: RefSegm and TstSegm are identical
            return 1;
        EXCHG( RefSegm->m_Start, RefSegm->m_End );      // at this point, RefSegm->m_End == TstSegm->m_Start
    }
    else if( RefSegm->m_Start == TstSegm->m_End )
    {
        EXCHG( RefSegm->m_Start, RefSegm->m_End );
        EXCHG( TstSegm->m_Start, TstSegm->m_End );    // at this point, RefSegm->m_End == TstSegm->m_Start
    }
    else if( RefSegm->m_End == TstSegm->m_End )
    {
        EXCHG( TstSegm->m_Start, TstSegm->m_End );      // at this point, RefSegm->m_End == TstSegm->m_Start
    }
    else if( RefSegm->m_End != TstSegm->m_Start )       // No common end point, segments cannot be merged
        return 0;
246

247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
    /* Test alignment: */
    if( RefSegm->m_Start.y == RefSegm->m_End.y )       // Horizontal segment
    {
        if( TstSegm->m_Start.y == TstSegm->m_End.y )
        {
            RefSegm->m_End = TstSegm->m_End;
            return 1;
        }
    }
    else if( RefSegm->m_Start.x == RefSegm->m_End.x )  // Vertical segment
    {
        if( TstSegm->m_Start.x == TstSegm->m_End.x )
        {
            RefSegm->m_End = TstSegm->m_End;
            return 1;
        }
    }
    else
    {
266 267 268 269
        if( atan2( (double) ( RefSegm->m_Start.x - RefSegm->m_End.x ),
                  (double) ( RefSegm->m_Start.y - RefSegm->m_End.y ) ) ==
           atan2( (double) ( TstSegm->m_Start.x - TstSegm->m_End.x ),
                 (double) ( TstSegm->m_Start.y - TstSegm->m_End.y ) ) )
270 271 272 273 274 275 276 277
        {
            RefSegm->m_End = TstSegm->m_End;
            return 1;
        }
    }

    return 0;
}