diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index 5005954691..eb3249161e 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -216,17 +216,13 @@ wxPoint& BOARD::GetPosition() void BOARD::UnLink() { - /* Modification du chainage arriere */ + /* Update back link */ if( Back() ) { if( Back()->Type() == TYPEPCB ) { Back()->SetNext( Next() ); } - else /* Le chainage arriere pointe sur la structure "Pere" */ - { -// Pback-> = Pnext; - } } /* Modification du chainage avant */ @@ -1082,6 +1078,39 @@ void BOARD::RedrawFilledAreas(WinEDA_DrawPanel* panel, wxDC * aDC, int aDrawMode } +/** + * Function HitTestForAnyFilledArea + * tests if the given wxPoint is within the bounds of a filled area of this zone. + * the test is made on zones on layer from aStartLayer to aEndLayer + * Note: if a zone has its flag BUSY (in .m_State) is set, it is ignored. + * @param refPos A wxPoint to test + * @param aStartLayer the first layer to test + * @param aEndLayer the last layer (-1 to ignore it) to test + * @return ZONE_CONTAINER* return a pointer to the ZONE_CONTAINER found, else NULL + */ +ZONE_CONTAINER* BOARD::HitTestForAnyFilledArea( const wxPoint& aRefPos, int aStartLayer, int aEndLayer ) +{ + if( aEndLayer < 0 ) + aEndLayer = aStartLayer; + if( aEndLayer < aStartLayer) + EXCHG (aEndLayer, aStartLayer); + + for( unsigned ia = 0; ia < m_ZoneDescriptorList.size(); ia++ ) + { + ZONE_CONTAINER* area = m_ZoneDescriptorList[ia]; + int layer = area->GetLayer(); + if ( (layer < aStartLayer) || (layer > aEndLayer) ) + continue; + if ( area->GetState( BUSY ) ) // In locate functions we must skip tagged items with BUSY flag set. + continue; + if( area->HitTestFilledArea( aRefPos ) ) + return area; + } + + return NULL; +} + + #if defined(DEBUG) diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index 81d95da8ea..9c38cdd6bd 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -355,6 +355,17 @@ public: /*************************/ /* Copper Areas handling */ /*************************/ + /** + * Function HitTestForAnyFilledArea + * tests if the given wxPoint is within the bounds of a filled area of this zone. + * the test is made on zones on layer from aStartLayer to aEndLayer + * Note: if a zone has its flag BUSY (in .m_State) is set, it is ignored. + * @param refPos A wxPoint to test + * @param aStartLayer the first layer to test + * @param aEndLayer the last layer (-1 to ignore it) to test + * @return ZONE_CONTAINER* return a pointer to the ZONE_CONTAINER found, else NULL + */ + ZONE_CONTAINER* HitTestForAnyFilledArea( const wxPoint& aRefPos, int aStartLayer, int aEndLayer = -1 ); /** * Function RedrawAreasOutlines diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index f6ebe80697..6f2f90ddff 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -797,6 +797,31 @@ bool ZONE_CONTAINER::HitTest( EDA_Rect& refArea ) return is_out_of_box ? false : true; } +/** + * Function HitTestFilledArea + * tests if the given wxPoint is within the bounds of a filled area of this zone. + * @param aRefPos A wxPoint to test + * @return bool - true if a hit, else false + */ +bool ZONE_CONTAINER::HitTestFilledArea( const wxPoint& aRefPos ) +{ + unsigned indexstart = 0, indexend; + bool inside = false; + for( indexend = 0; indexend < m_FilledPolysList.size(); indexend++ ) + { + if( m_FilledPolysList[indexend].end_contour ) // end of a filled sub-area found + { + if( TestPointInsidePolygon( m_FilledPolysList, indexstart, indexend, aRefPos.x, aRefPos.y ) ) + { + inside = true; + break; + } + } + } + return inside; +} + + /************************************************************/ void ZONE_CONTAINER::Display_Infos( WinEDA_DrawFrame* frame ) diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h index a08bd6af80..843cd1964d 100644 --- a/pcbnew/class_zone.h +++ b/pcbnew/class_zone.h @@ -166,11 +166,20 @@ public: /** * Function HitTest * tests if the given wxPoint is within the bounds of this object. + * For zones, this means near an ouline segment * @param refPos A wxPoint to test * @return bool - true if a hit, else false */ bool HitTest( const wxPoint& refPos ); + /** + * Function HitTestFilledArea + * tests if the given wxPoint is within the bounds of a filled area of this zone. + * @param aRefPos A wxPoint to test + * @return bool - true if a hit, else false + */ + bool HitTestFilledArea( const wxPoint& aRefPos ); + /** function BuildFilledPolysListData * Build m_FilledPolysList data from real outlines (m_Poly) * in order to have drawable (and plottable) filled polygons diff --git a/pcbnew/clean.cpp b/pcbnew/clean.cpp index 508c43e4b2..a3419e3825 100644 --- a/pcbnew/clean.cpp +++ b/pcbnew/clean.cpp @@ -169,6 +169,7 @@ static void DeleteUnconnectedTracks( WinEDA_PcbFrame* frame, wxDC* DC ) TRACK* other; TRACK* startNetcode; TRACK* next; + ZONE_CONTAINER* zone; int nbpoints_supprimes = 0; int masklayer, oldnetcode; @@ -234,7 +235,7 @@ static void DeleteUnconnectedTracks( WinEDA_PcbFrame* frame, wxDC* DC ) oldnetcode = segment->GetNet(); } - flag_erase = 0; + flag_erase = 0; //Not connected indicator type_end = 0; /* Is a pad found on a track end ? */ @@ -258,27 +259,51 @@ static void DeleteUnconnectedTracks( WinEDA_PcbFrame* frame, wxDC* DC ) } // if not connected to a pad, test if segment's START is connected to another track + // For via tests, an enhancement could to test if connected to 2 items on different layers. + // Currently a via must be connected to 2 items, taht can be on the same layer + int top_layer, bottom_layer; if( (type_end & START_ON_PAD ) == 0 ) { - other = Locate_Piste_Connectee( segment, frame->m_Pcb->m_Track, - NULL, START ); - if( other == NULL ) + other = Locate_Piste_Connectee( segment, frame->m_Pcb->m_Track, NULL, START ); + + if( other == NULL ) // Test a connection to zones + { + if( segment->Type() != TYPEVIA ) + { + zone = frame->m_Pcb->HitTestForAnyFilledArea(segment->m_Start, segment->GetLayer() ); + } + + else + { + ((SEGVIA*)segment)->ReturnLayerPair( &top_layer, &bottom_layer ); + zone = frame->m_Pcb->HitTestForAnyFilledArea(segment->m_Start, top_layer, bottom_layer ); + } + } + + if( (other == NULL) && (zone == NULL) ) flag_erase |= 1; - else // segment or via connected to this end + else // segment, via or zone connected to this end { segment->start = other; - - if( other->Type() == TYPEVIA ) + // If a via is connected to this end, test if this via has a second item connected + // if no, remove it with the current segment + if( other && other->Type() == TYPEVIA ) { // search for another segment following the via segment->SetState( BUSY, ON ); - TRACK* via = other; + SEGVIA* via = (SEGVIA*) other; other = Locate_Piste_Connectee( via, frame->m_Pcb->m_Track, NULL, START ); if( other == NULL ) + { + via->ReturnLayerPair( &top_layer, &bottom_layer ); + zone = frame->m_Pcb->HitTestForAnyFilledArea(via->m_Start, bottom_layer, top_layer ); + } + + if( (other == NULL) && (zone == NULL) ) flag_erase |= 2; segment->SetState( BUSY, OFF ); @@ -291,22 +316,42 @@ static void DeleteUnconnectedTracks( WinEDA_PcbFrame* frame, wxDC* DC ) { other = Locate_Piste_Connectee( segment, frame->m_Pcb->m_Track, NULL, END ); - if( other == NULL ) + if( other == NULL ) // Test a connection to zones + { + if( segment->Type() != TYPEVIA ) + zone = frame->m_Pcb->HitTestForAnyFilledArea(segment->m_End, segment->GetLayer() ); + + else + { + ((SEGVIA*)segment)->ReturnLayerPair( &top_layer, &bottom_layer ); + zone = frame->m_Pcb->HitTestForAnyFilledArea(segment->m_End,top_layer, bottom_layer ); + } + } + + if ( (other == NULL) && (zone == NULL) ) flag_erase |= 0x10; - else // segment or via connected to this end + else // segment, via or zone connected to this end { segment->end = other; - if( other->Type() == TYPEVIA ) + // If a via is connected to this end, test if this via has a second item connected + // if no, remove it with the current segment + if( other && other->Type() == TYPEVIA ) { // search for another segment following the via segment->SetState( BUSY, ON ); - TRACK* via = other; + SEGVIA* via = (SEGVIA*) other; other = Locate_Piste_Connectee( via, frame->m_Pcb->m_Track, NULL, END ); if( other == NULL ) + { + via->ReturnLayerPair( &top_layer, &bottom_layer ); + zone = frame->m_Pcb->HitTestForAnyFilledArea(via->m_End, bottom_layer, top_layer ); + } + + if( (other == NULL) && (zone == NULL) ) flag_erase |= 0x20; segment->SetState( BUSY, OFF ); diff --git a/pcbnew/editrack.cpp b/pcbnew/editrack.cpp index 389c912899..07f94b26e0 100644 --- a/pcbnew/editrack.cpp +++ b/pcbnew/editrack.cpp @@ -99,7 +99,7 @@ TRACK* WinEDA_PcbFrame::Begin_Route( TRACK* track, wxDC* DC ) if( track == NULL ) /* Starting a new track */ { - /* undrw old hightlight */ + /* erase old highlight */ OldNetCodeSurbrillance = g_HightLigth_NetCode; OldEtatSurbrillance = g_HightLigt_Status; @@ -133,6 +133,13 @@ TRACK* WinEDA_PcbFrame::Begin_Route( TRACK* track, wxDC* DC ) } } + else // no starting point, but a filled zone area can exist. This is also a good starting point. + { + ZONE_CONTAINER* zone = m_Pcb->HitTestForAnyFilledArea(pos, GetScreen()->m_Active_Layer ); + if ( zone ) + g_HightLigth_NetCode = zone->GetNet(); + } + build_ratsnest_pad( LockPoint, wxPoint( 0, 0 ), TRUE ); Hight_Light( DC ); diff --git a/pcbnew/makefile.g95 b/pcbnew/makefile.g95 index 97fd0e3b3a..b3c7ccd60e 100644 --- a/pcbnew/makefile.g95 +++ b/pcbnew/makefile.g95 @@ -6,7 +6,7 @@ TARGET=pcbnew include ../libs.win -EXTRACPPFLAGS += -I /f/kicad-sourceforge/trunk/kicad +EXTRACPPFLAGS += -I /f/kicad-sourceforge/trunk/kicad -I $(BOOST_PATH) all: $(TARGET).exe include makefile.include