First version of pcbnew using polygonal filled areas in zones in rats nets calculations.

This commit is contained in:
charras 2008-11-18 18:13:55 +00:00
parent f43a7acc6a
commit 178bc946e3
27 changed files with 1744 additions and 1256 deletions

View File

@ -4,6 +4,11 @@ Started 2007-June-11
Please add newer entries at the top, list the date and your name with
email address.
2008-Nov-18 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================
++pcbnew
First version of pcbnew using polygonal filled areas in zones in rats nets calculations.
Needs more tests.
2008-Nov-14 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
@ -19,7 +24,7 @@ kbool:
2008-Nov-14 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================
+gerview
+gerbiew
+ Added support for displaying most aperture macros embedded in a RS274X compatible file.
Cleanup of rs274d.cpp and added the beginning of the isDark support, which we
need to discuss. GERBER::m_ImageNegative can toggle during the course of reading

View File

@ -33,6 +33,7 @@ set(CVPCB_EXTRA_SRCS
../pcbnew/basepcbframe.cpp
../pcbnew/class_board.cpp
../pcbnew/class_board_item.cpp
../pcbnew/class_board_connected_item.cpp
../pcbnew/class_cotation.cpp
../pcbnew/class_drawsegment.cpp
../pcbnew/class_edge_mod.cpp

View File

@ -12,12 +12,11 @@ EXTRALIBS = ../common/common.a ../bitmaps/libbitmaps.a\
LIBVIEWER3D = ../3d-viewer/3d-viewer.a
# DEPEND = cvpcb.h ../include/pcbstruct.h
OBJECTS = $(TARGET).o \
class_cvpcb.o\
class_zone.o\
class_zone_setting.o\
class_board_connected_item.o\
memoire.o \
cvframe.o\
listboxes.o\
@ -55,30 +54,33 @@ OBJECTS = $(TARGET).o \
basepcbframe.o\
collectors.o
cvpcb.o: cvpcb.cpp cvpcb.h $(DEPEND)
cvpcb.o: cvpcb.cpp cvpcb.h
displayframe.o: displayframe.cpp $(DEPEND)
displayframe.o: displayframe.cpp
listboxes.o: listboxes.cpp $(DEPEND)
listboxes.o: listboxes.cpp
drawpanel.o: ../share/drawpanel.cpp $(DEPEND)
drawpanel.o: ../share/drawpanel.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../share/$*.cpp
drawframe.o: ../share/drawframe.cpp $(DEPEND)
drawframe.o: ../share/drawframe.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../share/$*.cpp
init.o: init.cpp $(DEPEND)
init.o: init.cpp
memoire.o: memoire.cpp $(DEPEND)
memoire.o: memoire.cpp
rdpcad.o: rdpcad.cpp $(DEPEND)
rdpcad.o: rdpcad.cpp
classpcb.o: ../pcbnew/classpcb.cpp $(DEPEND)
classpcb.o: ../pcbnew/classpcb.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_mire.o: ../pcbnew/class_mire.cpp ../pcbnew/class_mire.h $(COMMON)
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_board_connected_item.o: ../pcbnew/class_board_connected_item.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_zone.o: ../pcbnew/class_zone.cpp ../pcbnew/class_zone.h $(COMMON)
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
@ -91,68 +93,68 @@ class_cotation.o: ../pcbnew/class_cotation.cpp ../pcbnew/class_cotation.h $(COMM
class_pcb_text.o: ../pcbnew/class_pcb_text.cpp ../pcbnew/class_pcb_text.h $(COMMON)
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_board.o: ../pcbnew/class_board.cpp $(DEPEND)
class_board.o: ../pcbnew/class_board.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_drawsegment.o: ../pcbnew/class_drawsegment.cpp ../pcbnew/class_drawsegment.h $(DEPEND)
class_drawsegment.o: ../pcbnew/class_drawsegment.cpp ../pcbnew/class_drawsegment.h
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_track.o: ../pcbnew/class_track.cpp $(DEPEND)
class_track.o: ../pcbnew/class_track.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_pad.o: ../pcbnew/class_pad.cpp $(DEPEND)
class_pad.o: ../pcbnew/class_pad.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_module.o: ../pcbnew/class_module.cpp $(DEPEND)
class_module.o: ../pcbnew/class_module.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_text_mod.o: ../pcbnew/class_text_mod.cpp $(DEPEND)
class_text_mod.o: ../pcbnew/class_text_mod.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_edge_mod.o: ../pcbnew/class_edge_mod.cpp $(DEPEND)
class_edge_mod.o: ../pcbnew/class_edge_mod.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_equipot.o: ../pcbnew/class_equipot.cpp $(DEPEND)
class_equipot.o: ../pcbnew/class_equipot.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
basepcbframe.o: ../pcbnew/basepcbframe.cpp $(DEPEND)
basepcbframe.o: ../pcbnew/basepcbframe.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
collectors.o: ../pcbnew/collectors.cpp $(COMMON)
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
readschematicnetlist.o: readschematicnetlist.cpp $(DEPEND)
readschematicnetlist.o: readschematicnetlist.cpp
viewlogi.o: viewlogi.cpp $(DEPEND)
viewlogi.o: viewlogi.cpp
viewlnet.o: viewlnet.cpp $(DEPEND)
viewlnet.o: viewlnet.cpp
loadcmp.o: loadcmp.cpp $(DEPEND)
loadcmp.o: loadcmp.cpp
savecmp.o: savecmp.cpp $(DEPEND)
savecmp.o: savecmp.cpp
writenetlistpcbnew.o: writenetlistpcbnew.cpp $(DEPEND)
writenetlistpcbnew.o: writenetlistpcbnew.cpp
genequiv.o: genequiv.cpp $(DEPEND)
genequiv.o: genequiv.cpp
ioascii.o: ../pcbnew/ioascii.cpp $(DEPEND)
ioascii.o: ../pcbnew/ioascii.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
listlib.o: listlib.cpp $(DEPEND)
listlib.o: listlib.cpp
cfg.o: cfg.cpp cfg.h $(DEPEND)
cfg.o: cfg.cpp cfg.h
menucfg.o: menucfg.cpp dialog_cvpcb_config.cpp dialog_cvpcb_config.h $(DEPEND)
menucfg.o: menucfg.cpp dialog_cvpcb_config.cpp dialog_cvpcb_config.h
autosel.o: autosel.cpp $(DEPEND)
autosel.o: autosel.cpp
setvisu.o: setvisu.cpp $(DEPEND)
setvisu.o: setvisu.cpp
zoom.o: ../share/zoom.cpp $(DEPEND)
zoom.o: ../share/zoom.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../share/$*.cpp
tracemod.o: ../pcbnew/tracemod.cpp ../include/gr_basic.h $(DEPEND)
tracemod.o: ../pcbnew/tracemod.cpp ../include/gr_basic.h
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
dialog_display_options.o: dialog_display_options.cpp dialog_display_options.h $(DEPEND)
dialog_display_options.o: dialog_display_options.cpp dialog_display_options.h

View File

@ -43,6 +43,7 @@ set(GERBVIEW_SRCS
set(GERBVIEW_EXTRA_SRCS
../pcbnew/basepcbframe.cpp
../pcbnew/class_board.cpp
../pcbnew/class_board_connected_item.cpp
../pcbnew/class_drawsegment.cpp
../pcbnew/class_drc_item.cpp
../pcbnew/class_marker.cpp

View File

@ -7,8 +7,6 @@ EXTRACPPFLAGS= -DGERBVIEW -DPCBNEW -fno-strict-aliasing\
-I../polygon
#COMMON = pcbnew.h struct.h
OBJECTS= \
$(TARGET).o\
classpcb.o\
@ -27,6 +25,7 @@ OBJECTS= \
class_drawsegment.o\
class_track.o \
class_drc_item.o \
class_board_connected_item.o\
drawframe.o\
drawpanel.o\
set_color.o \
@ -65,132 +64,135 @@ drawpanel.o: ../share/drawpanel.cpp
drawframe.o: ../share/drawframe.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../share/$*.cpp
controle.o: controle.cpp $(COMMON)
controle.o: controle.cpp
hotkeys.o: hotkeys.cpp hotkeys.h $(COMMON)
hotkeys.o: hotkeys.cpp hotkeys.h
set_color.o: set_color.cpp set_color.h $(COMMON)
set_color.o: set_color.cpp set_color.h
files.o: files.cpp $(COMMON)
files.o: files.cpp
class_marker.o: ../pcbnew/class_marker.cpp ../pcbnew/class_marker.h $(COMMON)
class_board_connected_item.o: ../pcbnew/class_board_connected_item.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_zone.o: ../pcbnew/class_zone.cpp ../pcbnew/class_zone.h $(COMMON)
class_marker.o: ../pcbnew/class_marker.cpp ../pcbnew/class_marker.h
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_zone_setting.o: ../pcbnew/class_zone_setting.cpp ../pcbnew/class_zone_setting.h $(COMMON)
class_zone.o: ../pcbnew/class_zone.cpp ../pcbnew/class_zone.h
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_zone_setting.o: ../pcbnew/class_zone_setting.cpp ../pcbnew/class_zone_setting.h
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_drawsegment.o: ../pcbnew/class_drawsegment.cpp ../pcbnew/class_drawsegment.h $(DEPEND)
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_drc_item.o: ../pcbnew/class_drc_item.cpp $(COMMON)
class_drc_item.o: ../pcbnew/class_drc_item.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
sel_layer.o: ../pcbnew/sel_layer.cpp $(COMMON)
sel_layer.o: ../pcbnew/sel_layer.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
wxprint.o: ../share/wxprint.cpp ../share/dialog_print.cpp ../share/dialog_print.h $(COMMON)
wxprint.o: ../share/wxprint.cpp ../share/dialog_print.cpp ../share/dialog_print.h
$(CXX) -c $(EDACPPFLAGS) -o $@ ../share/$*.cpp
lay2plot.o: lay2plot.cpp $(COMMON)
lay2plot.o: lay2plot.cpp
classpcb.o: ../pcbnew/classpcb.cpp $(COMMON)
classpcb.o: ../pcbnew/classpcb.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_pcb_text.o: ../pcbnew/class_pcb_text.cpp ../pcbnew/class_pcb_text.h $(COMMON)
class_pcb_text.o: ../pcbnew/class_pcb_text.cpp ../pcbnew/class_pcb_text.h
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_board.o: ../pcbnew/class_board.cpp $(DEPEND)
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
basepcbframe.o: ../pcbnew/basepcbframe.cpp $(COMMON)
basepcbframe.o: ../pcbnew/basepcbframe.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
collectors.o: ../pcbnew/collectors.cpp $(COMMON)
collectors.o: ../pcbnew/collectors.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_track.o: ../pcbnew/class_track.cpp $(COMMON)
class_track.o: ../pcbnew/class_track.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
$(TARGET).o: $(TARGET).cpp $(COMMON)
$(TARGET).o: $(TARGET).cpp
gerbview_config.o: gerbview_config.cpp gerbview_config.h $(COMMON)
gerbview_config.o: gerbview_config.cpp gerbview_config.h
tracepcb.o: tracepcb.cpp $(COMMON)
tracepcb.o: tracepcb.cpp
block.o: block.cpp $(COMMON)
block.o: block.cpp
trpiste.o: trpiste.cpp $(COMMON)
trpiste.o: trpiste.cpp
surbrill.o: surbrill.cpp $(COMMON)
surbrill.o: surbrill.cpp
pcbtexte.o: pcbtexte.cpp $(COMMON)
pcbtexte.o: pcbtexte.cpp
zoom.o: ../share/zoom.cpp $(COMMON)
zoom.o: ../share/zoom.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../share/$*.cpp
affiche.o: affiche.cpp $(COMMON)
affiche.o: affiche.cpp
reglage.o: reglage.cpp $(COMMON)
reglage.o: reglage.cpp
editrack.o: editrack.cpp $(COMMON)
editrack.o: editrack.cpp
deltrack.o: deltrack.cpp $(COMMON)
deltrack.o: deltrack.cpp
track.o: track.cpp $(COMMON)
track.o: track.cpp
editrout.o: editrout.cpp autorout.h $(COMMON)
editrout.o: editrout.cpp autorout.h
editmod.o: editmod.cpp autorout.h $(COMMON)
editmod.o: editmod.cpp autorout.h
editpads.o: editpads.cpp $(COMMON)
editpads.o: editpads.cpp
editedge.o: editedge.cpp $(COMMON)
editedge.o: editedge.cpp
cotation.o: cotation.cpp $(COMMON)
cotation.o: cotation.cpp
editexte.o: editexte.cpp $(COMMON)
editexte.o: editexte.cpp
clean.o: clean.cpp autorout.h $(COMMON)
clean.o: clean.cpp autorout.h
pcbplot.o: pcbplot.cpp $(COMMON)
pcbplot.o: pcbplot.cpp
plothpgl.o: plothpgl.cpp $(COMMON)
plothpgl.o: plothpgl.cpp
plotgerb.o: plotgerb.cpp pcbplot.h $(COMMON)
plotgerb.o: plotgerb.cpp pcbplot.h
printps.o: printps.cpp pcbplot.h $(COMMON)
printps.o: printps.cpp pcbplot.h
readgerb.o: readgerb.cpp pcbplot.h $(COMMON)
readgerb.o: readgerb.cpp pcbplot.h
plot_rtn.o: plot_rtn.cpp pcbplot.h $(COMMON)
plot_rtn.o: plot_rtn.cpp pcbplot.h
gendrill.o: gendrill.cpp pcbplot.h $(COMMON)
gendrill.o: gendrill.cpp pcbplot.h
librairi.o: librairi.cpp autorout.h librairi.h $(COMMON)
librairi.o: librairi.cpp autorout.h librairi.h
docedit.o: docedit.cpp $(COMMON)
docedit.o: docedit.cpp
edgemod.o: edgemod.cpp $(COMMON)
edgemod.o: edgemod.cpp
autorout.o: autorout.cpp cell.h autorout.fct autorout.h $(COMMON)
autorout.o: autorout.cpp cell.h autorout.fct autorout.h
setlayer.o: setlayer.cpp $(COMMON)
setlayer.o: setlayer.cpp
dist.o: dist.cpp cell.h autorout.fct $(COMMON)
dist.o: dist.cpp cell.h autorout.fct
zones.o: zones.cpp cell.h autorout.fct $(COMMON)
zones.o: zones.cpp cell.h autorout.fct
undelete.o: undelete.cpp $(COMMON)
undelete.o: undelete.cpp
ioascii.o: ioascii.cpp $(COMMON)
ioascii.o: ioascii.cpp
chrono.o: chrono.cpp pcbnew.h
coordbox.o: coordbox.cpp $(COMMON)
coordbox.o: coordbox.cpp
mirepcb.o: mirepcb.cpp $(COMMON)
mirepcb.o: mirepcb.cpp
dragsegm.o: dragsegm.cpp drag.h $(COMMON)
dragsegm.o: dragsegm.cpp drag.h

View File

@ -1,22 +1,39 @@
/*********************************************************************/
/* board_item_struct.h : Basic classes for BOARD_ITEM descriptions */
/*********************************************************************/
/**********************************************************************************************/
/* board_item_struct.h : Basic classes for BOARD_ITEM and BOARD_CONNECTED_ITEM descriptions */
/**********************************************************************************************/
#ifndef BOARD_ITEM_STRUCT_H
#define BOARD_ITEM_STRUCT_H
/* Forme des segments (pistes, contours ..) ( parametre .shape ) */
/**
* Class BOARD_ITEM
* is a base class for any item which can be embedded within the BOARD
* container class, and therefore instances of derived classes should only be
* found in PCBNEW or other programs that use class BOARD and its contents.
* The corresponding class in EESCHEMA is SCH_ITEM.
*/
/**
* Class BOARD_CONNECTED_ITEM
* This is a base class derived from BOARD_ITEM for items that can be connected
* mainly: tracks and pads
* Handle connection info
*
*/
/* Shapes for segments (graphic segments and tracks) ( .shape member ) */
enum Track_Shapes {
S_SEGMENT = 0, /* segment rectiligne */
S_RECT, /* segment forme rect (i.e. bouts non arrondis) */
S_ARC, /* segment en arc de cercle (bouts arrondis)*/
S_CIRCLE, /* segment en cercle (anneau)*/
S_ARC_RECT, /* segment en arc de cercle (bouts droits) (GERBER)*/
S_SPOT_OVALE, /* spot ovale (for GERBER)*/
S_SPOT_CIRCLE, /* spot rond (for GERBER)*/
S_SPOT_RECT, /* spot rect (for GERBER)*/
S_POLYGON /* polygon shape */
S_SEGMENT = 0, /* usual segment : line with rounded ends */
S_RECT, /* segment with non rounded ends */
S_ARC, /* Arcs (with rounded ends)*/
S_CIRCLE, /* ring*/
S_ARC_RECT, /* Arcs (with non rounded ends) (GERBER)*/
S_SPOT_OVALE, /* Oblong spot (for GERBER)*/
S_SPOT_CIRCLE, /* rounded spot (for GERBER)*/
S_SPOT_RECT, /* Rectangular spott (for GERBER)*/
S_POLYGON /* polygonal shape */
};
@ -165,5 +182,40 @@ public:
virtual bool Save( FILE* aFile ) const = 0;
};
class BOARD_CONNECTED_ITEM: public BOARD_ITEM
{
protected:
int m_NetCode; // Net number
int m_Subnet; /* In rastnest routines : for the current net,
* block number (number common to the current connected items found) */
int m_ZoneSubnet; // variable used in rastnest computations : for the current net,
// handle block number in zone connection
public:
BOARD_CONNECTED_ITEM( BOARD_ITEM* StructFather, KICAD_T idtype );
BOARD_CONNECTED_ITEM( const BOARD_CONNECTED_ITEM& src );
/**
* Function GetNet
* @return int - the net code.
*/
int GetNet() const;
void SetNet( int aNetCode );
/**
* Function GetSubNet
* @return int - the sub net code.
*/
int GetSubNet() const;
void SetSubNet( int aSubNetCode );
/**
* Function GetZoneSubNet
* @return int - the sub net code in zone connections.
*/
int GetZoneSubNet() const;
void SetZoneSubNet( int aSubNetCode );
};
#endif /* BOARD_ITEM_STRUCT_H */

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@ set(PCBNEW_SRCS
board.cpp
class_board.cpp
class_board_item.cpp
class_board_connected_item.cpp
class_cotation.cpp
class_drawsegment.cpp
class_drc_item.cpp
@ -145,6 +146,7 @@ set(PCBNEW_SRCS
zones_convert_brd_items_to_polygons.cpp
zone_filling_algorithm.cpp
zones_polygons_insulated_copper_islands.cpp
zones_polygons_test_connections.cpp
zones_test_and_combine_areas.cpp
)

View File

@ -977,8 +977,8 @@ void Build_PlacedPads_List( BOARD* Pcb )
for( ; PtPad != NULL; PtPad = (D_PAD*) PtPad->Pnext )
{
*pt_liste_pad = PtPad;
PtPad->m_physical_connexion = 0;
PtPad->m_logical_connexion = 0;
PtPad->SetSubNet( 0 );
PtPad->SetSubRatsnest( 0 );
PtPad->m_Parent = Module;
if( PtPad->GetNet() )
Pcb->m_NbNodes++;

View File

@ -544,6 +544,16 @@ public:
* @return errors count
*/
int Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_Examine,bool aCreate_Markers );
/****** function relative to ratsnest calculations: */
/**
* Function Test_Connection_To_Copper_Areas
* init .m_ZoneSubnet parameter in tracks and pads according to the connections to areas found
* @param aNetcode = netcode to analyse. if -1, analyse all nets
*/
void Test_Connections_To_Copper_Areas( int aNetcode = -1 );
};
#endif // #ifndef CLASS_BOARD_H

View File

@ -0,0 +1,76 @@
/*************************************************************************/
/* class_board_connected_item.cpp : BOARD_CONNECTED_ITEM class functions */
/*************************************************************************/
#include "fctsys.h"
#include "wxstruct.h"
#include "common.h"
#include "pcbnew.h"
#ifdef CVPCB
#include "cvpcb.h"
#endif
BOARD_CONNECTED_ITEM::BOARD_CONNECTED_ITEM( BOARD_ITEM* StructFather, KICAD_T idtype ) :
BOARD_ITEM( StructFather, idtype )
{
m_NetCode = 0;
m_Subnet = 0;
m_ZoneSubnet = 0;
}
BOARD_CONNECTED_ITEM::BOARD_CONNECTED_ITEM( const BOARD_CONNECTED_ITEM& src ) :
BOARD_ITEM( src )
{
m_Layer = src.m_Layer;
}
/**
* Function GetNet
* @return int - the net code.
*/
int BOARD_CONNECTED_ITEM::GetNet() const
{
return m_NetCode;
}
void BOARD_CONNECTED_ITEM::SetNet( int aNetCode )
{
m_NetCode = aNetCode;
}
/**
* Function GetSubNet
* @return int - the sub net code.
*/
int BOARD_CONNECTED_ITEM::GetSubNet() const
{
return m_Subnet;
}
void BOARD_CONNECTED_ITEM::SetSubNet( int aSubNetCode )
{
m_Subnet = aSubNetCode;
}
/**
* Function GetZoneSubNet
* @return int - the sub net code in zone connections.
*/
int BOARD_CONNECTED_ITEM::GetZoneSubNet() const
{
return m_ZoneSubnet;
}
void BOARD_CONNECTED_ITEM::SetZoneSubNet( int aSubNetCode )
{
m_ZoneSubnet = aSubNetCode;
}

View File

@ -26,12 +26,10 @@
/* classe D_PAD : constructeur */
/*******************************/
D_PAD::D_PAD( MODULE* parent ) :
BOARD_ITEM( parent, TYPEPAD )
D_PAD::D_PAD( MODULE* parent ) : BOARD_CONNECTED_ITEM( parent, TYPEPAD )
{
m_NumPadName = 0;
m_Masque_Layer = CUIVRE_LAYER;
SetNet( 0 ); /* Numero de net pour comparaisons rapides */
m_DrillShape = PAD_CIRCLE; // Drill shape = circle
m_Size.x = m_Size.y = 500;
@ -45,8 +43,7 @@ D_PAD::D_PAD( MODULE* parent ) :
m_Attribut = PAD_STANDARD; // NORMAL, PAD_SMD, PAD_CONN, Bit 7 = STACK
m_Orient = 0; // en 1/10 degres
m_logical_connexion = 0;
m_physical_connexion = 0; // variables utilisee lors du calcul du chevelu
SetSubRatsnest(0);
ComputeRayon();
}
@ -199,8 +196,8 @@ void D_PAD::Copy( D_PAD* source )
m_Attribut = source->m_Attribut; // NORMAL, PAD_SMD, PAD_CONN, Bit 7 = STACK
m_Orient = source->m_Orient; // en 1/10 degres
m_logical_connexion = 0; // variable utilisee lors du calcul du chevelu
m_physical_connexion = 0; // variable utilisee lors du calcul de la connexit<69>
SetSubRatsnest( 0 );
SetSubNet( 0 );
m_Netname = source->m_Netname;
}
@ -890,7 +887,7 @@ void D_PAD::Display_Infos( WinEDA_DrawFrame* frame )
};
static const wxString Msg_Pad_Attribut[5] =
{ wxT( "norm" ), wxT( "smd " ), wxT( "conn" ), wxT( "hole" ), wxT( "????" ) };
{ wxT( "norm" ), wxT( "smd " ), wxT( "conn" ), wxT( "????" ) };
frame->MsgPanel->EraseMsgBox();
@ -910,9 +907,9 @@ void D_PAD::Display_Infos( WinEDA_DrawFrame* frame )
/* For test and debug only: display m_physical_connexion and m_logical_connexion */
pos += 10;
#if 0
Line.Printf( wxT( "%d.%d " ), m_logical_connexion, m_physical_connexion );
Affiche_1_Parametre( frame, pos, "L.P", Line, WHITE );
#if 1 // Used only to debug connectivity calculations
Line.Printf( wxT( "%d-%d-%d " ), GetSubRatsnest(), GetSubNet(), m_ZoneSubnet );
Affiche_1_Parametre( frame, pos, wxT("L-P-Z"), Line, DARKGREEN );
#endif
wxString LayerInfo;
@ -993,13 +990,9 @@ void D_PAD::Display_Infos( WinEDA_DrawFrame* frame )
Affiche_1_Parametre( frame, pos, _( "Layer" ), LayerInfo, DARKGREEN );
pos += 6;
Affiche_1_Parametre( frame, pos, Msg_Pad_Shape[m_PadShape], wxEmptyString, DARKGREEN );
Affiche_1_Parametre( frame,
-1,
wxEmptyString,
Msg_Pad_Attribut[m_Attribut & 15],
DARKGREEN );
int attribut = m_Attribut & 15;
if ( attribut > 3 ) attribut = 3;
Affiche_1_Parametre( frame, pos, Msg_Pad_Shape[m_PadShape],Msg_Pad_Attribut[attribut], DARKGREEN );
valeur_param( m_Size.x, Line );
pos += 6;

View File

@ -8,7 +8,7 @@ class Pcb3D_GLCanvas;
/* Definition type Structure d'un pad */
class D_PAD : public BOARD_ITEM
class D_PAD : public BOARD_CONNECTED_ITEM
{
private:
int m_NetCode; // Net number for fast comparisons
@ -60,15 +60,10 @@ public:
int m_Attribut; // NORMAL, PAD_SMD, PAD_CONN
int m_Orient; // in 1/10 degrees
int m_logical_connexion; // variable used in rastnest computations
private:
int m_SubRatsnest; // variable used in rats nest computations
// handle subnet (block) number in ratsnet connection
int m_physical_connexion; // variable used in rastnest computations
// handle physical subnet (block)number in track connection
protected:
int m_ZoneSubnet; // variable used in rastnest computations
// handle block number in zone connection
public:
D_PAD( MODULE* parent );
D_PAD( D_PAD* pad );
@ -128,15 +123,9 @@ public:
* Function GetNet
* @return int - the netcode
*/
int GetNet() const { return m_NetCode; }
void SetNet( int aNetCode ) { m_NetCode = aNetCode; }
int GetSubRatsnest() const { return m_SubRatsnest; }
void SetSubRatsnest( int aSubRatsnest ) { m_SubRatsnest = aSubRatsnest; }
/**
* Function GetZoneSubNet
* @return int - the sub net code in zone connections.
*/
int GetZoneSubNet() const { return m_ZoneSubnet; }
void SetZoneSubNet( int aSubNetCode ) { m_ZoneSubnet = aSubNetCode; }
/**
* Function Display_Infos

View File

@ -58,15 +58,12 @@ static bool ShowClearance( const TRACK* aTrack )
/**********************************************************/
TRACK::TRACK( BOARD_ITEM* StructFather, KICAD_T idtype ) :
BOARD_ITEM( StructFather, idtype )
BOARD_CONNECTED_ITEM( StructFather, idtype )
/**********************************************************/
{
m_Width = 0;
m_Shape = S_SEGMENT;
start = end = NULL;
SetNet( 0 );
SetSubNet( 0 );
SetZoneSubNet( 0 );
SetDrillDefault();
m_Param = 0;
}
@ -98,7 +95,7 @@ SEGVIA::SEGVIA( BOARD_ITEM* StructFather ) :
// Copy constructor
TRACK::TRACK( const TRACK& Source ) :
BOARD_ITEM( Source )
BOARD_CONNECTED_ITEM( Source )
{
m_Shape = Source.m_Shape;
SetNet( Source.GetNet() );

View File

@ -16,7 +16,7 @@
/***/
class TRACK : public BOARD_ITEM
class TRACK : public BOARD_CONNECTED_ITEM
{
public:
int m_Width; // 0 = line, > 0 = tracks, bus ...
@ -35,12 +35,6 @@ public:
int m_Param; // Auxiliary variable ( used in some computations )
protected:
int m_NetCode; // Net number
int m_Subnet; /* In rastnest routines : for the current net,
* block number (number common to the current connected items found) */
int m_ZoneSubnet; // variable used in rastnest computations : for the current net,
// handle block number in zone connection
TRACK( const TRACK& track ); // protected so Copy() is used instead.
public:
@ -72,7 +66,7 @@ public:
EDA_Rect GetBoundingBox();
/* supprime du chainage la structure Struct */
/* Remove "this" from the linked list */
void UnLink();
@ -117,28 +111,6 @@ public:
*/
TRACK* GetEndNetCode( int NetCode );
/**
* Function GetNet
* @return int - the net code.
*/
int GetNet() const { return m_NetCode; }
void SetNet( int aNetCode ) { m_NetCode = aNetCode; }
/**
* Function GetSubNet
* @return int - the sub net code.
*/
int GetSubNet() const { return m_Subnet; }
void SetSubNet( int aSubNetCode ) { m_Subnet = aSubNetCode; }
/**
* Function GetZoneSubNet
* @return int - the sub net code in zone connections.
*/
int GetZoneSubNet() const { return m_ZoneSubnet; }
void SetZoneSubNet( int aSubNetCode ) { m_ZoneSubnet = aSubNetCode; }
/**
* Function GetLength
* returns the length of the track using the hypotenuse calculation.

View File

@ -97,15 +97,6 @@ public:
int aDrawMode,
const wxPoint& offset = ZeroOffset );
EDA_Rect GetBoundingBox();
/**
* Function Test_For_Copper_Island_And_Remove__Insulated_Islands
* Remove insulated copper islands found in m_FilledPolysList.
* @param aPcb = the board to analyse
*/
void Test_For_Copper_Island_And_Remove_Insulated_Islands( BOARD* aPcb );
/**
* Function DrawWhileCreateOutline
* Draws the zone outline when ir is created.
@ -118,6 +109,27 @@ public:
void DrawWhileCreateOutline( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode = GR_OR );
/* Function GetBoundingBox
* @return an EDA_Rect that is the bounding box of the zone outline
*/
EDA_Rect GetBoundingBox();
/**
* Function Test_For_Copper_Island_And_Remove__Insulated_Islands
* Remove insulated copper islands found in m_FilledPolysList.
* @param aPcb = the board to analyse
*/
void Test_For_Copper_Island_And_Remove_Insulated_Islands( BOARD* aPcb );
/** function CalculateSubAreaBoundaryBox
* Calculates the bounding box of a a filled area ( list of CPolyPt )
* use m_FilledPolysList as list of CPolyPt (that are the corners of one or more polygons or filled areas )
* @return an EDA_Rect as bounding box
* @param aIndexStart = index of the first corner of a polygon (filled area) in m_FilledPolysList
* @param aIndexEnd = index of the last corner of a polygon in m_FilledPolysList
*/
EDA_Rect CalculateSubAreaBoundaryBox( int aIndexStart, int aIndexEnd );
/**
* Function IsOnCopperLayer
* @return true if this zone is on a copper layer, false if on a technical layer

View File

@ -12,26 +12,28 @@
#include "protos.h"
/* Loca functions */
static void propage_equipot( TRACK* pt_start_conn, TRACK* pt_end_conn );
static void calcule_connexite_1_net( TRACK* pt_start_conn, TRACK* pt_end_conn );
extern void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb );
extern void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb, int aNetcode );
/* Local functions */
static void Propagate_SubNet( TRACK* pt_start_conn, TRACK* pt_end_conn );
static void Build_Pads_Info_Connections_By_Tracks( TRACK* pt_start_conn, TRACK* pt_end_conn );
static void RebuildTrackChain( BOARD* pcb );
static int Sort_By_NetCode( TRACK** pt_ref, TRACK** pt_compare );
/*..*/
/*****************************************************************/
static int change_equipot( TRACK* pt_start_conn, TRACK* pt_end_conn,
int old_val, int new_val )
/*****************************************************************/
/**************************************************************************************************/
static int Merge_Two_SubNets( TRACK* pt_start_conn, TRACK* pt_end_conn, int old_val, int new_val )
/**************************************************************************************************/
/** Function change_equipot()
* Used by propage_equipot()
/** Function Merge_Two_SubNets()
* Used by Propagate_SubNet()
* Change a subnet value to a new value, for tracks ans pads which are connected to corresponding track
* for pads, this is the .m_physical_connexion member which is tested and modified
* for tracks, this is the .m_Subnet member which is tested and modified
* for pads and tracks, this is the .m_Subnet member that is tested and modified
* these members are block numbers (or cluster numbers) for a given net
* The result is merging 2 blocks (or subnets)
* @return modification count
* @param old_val = subnet value to modify
* @param new_val = new subnet value for each item whith have old_val as subnet value
@ -66,15 +68,15 @@ static int change_equipot( TRACK* pt_start_conn, TRACK* pt_end_conn,
if( pt_conn->start && ( pt_conn->start->Type() == TYPEPAD) )
{
pt_pad = (D_PAD*) (pt_conn->start);
if( pt_pad->m_physical_connexion == old_val )
pt_pad->m_physical_connexion = pt_conn->GetSubNet();
if( pt_pad->GetSubNet() == old_val )
pt_pad->SetSubNet(pt_conn->GetSubNet());
}
if( pt_conn->end && (pt_conn->end->Type() == TYPEPAD) )
{
pt_pad = (D_PAD*) (pt_conn->end);
if( pt_pad->m_physical_connexion == old_val )
pt_pad->m_physical_connexion = pt_conn->GetSubNet();
if( pt_pad->GetSubNet() == old_val )
pt_pad->SetSubNet(pt_conn->GetSubNet());
}
if( pt_conn == pt_end_conn )
break;
@ -85,23 +87,23 @@ static int change_equipot( TRACK* pt_start_conn, TRACK* pt_end_conn,
/******************************************************************/
static void propage_equipot( TRACK* pt_start_conn, TRACK* pt_end_conn )
static void Propagate_SubNet( TRACK* pt_start_conn, TRACK* pt_end_conn )
/******************************************************************/
/** Function propage_equipot
/** Function Propagate_SubNet
* Test a list of track segment, to create or propagate a sub netcode to pads and segments connected together
* the track list must be sorted by nets, and all segments from pt_start_conn to pt_end_conn have the save net
* the track list must be sorted by nets, and all segments from pt_start_conn to pt_end_conn have the same net
* When 2 items are connected (a track to a pad, or a track to an other track) they are grouped in a cluster.
* for pads, this is the .m_physical_connexion member which is a cluster identifier
* for tracks, this is the .m_Subnet member which is a cluster identifier
* For a given net, if all tracks are created, there is only one cluster.
* but if not all tracks are created, there are are more than one cluster, and some ratsnets will be shown.
* but if not all tracks are created, there are more than one cluster, and some ratsnets will be shown.
* @param pt_start_conn = first track to test
* @param pt_end_conn = last segment to test
*/
{
TRACK* pt_conn;
int sous_net_code;
int sub_netcode;
D_PAD* pt_pad;
TRACK* pt_autre_piste;
BOARD_ITEM* PtStruct;
@ -113,18 +115,18 @@ static void propage_equipot( TRACK* pt_start_conn, TRACK* pt_end_conn )
pt_conn->SetSubNet( 0 );
PtStruct = pt_conn->start;
if( PtStruct && (PtStruct->Type() == TYPEPAD) )
( (D_PAD*) PtStruct )->m_physical_connexion = 0;
( (D_PAD*) PtStruct )->SetSubNet( 0);
PtStruct = pt_conn->end;
if( PtStruct && (PtStruct->Type() == TYPEPAD) )
( (D_PAD*) PtStruct )->m_physical_connexion = 0;
( (D_PAD*) PtStruct )->SetSubNet( 0);
if( pt_conn == pt_end_conn )
break;
}
sous_net_code = 1;
pt_start_conn->SetSubNet( sous_net_code );
sub_netcode = 1;
pt_start_conn->SetSubNet( sub_netcode );
/* Start of calculation */
pt_conn = pt_start_conn;
@ -139,25 +141,25 @@ static void propage_equipot( TRACK* pt_start_conn, TRACK* pt_end_conn )
pt_pad = (D_PAD*) PtStruct;
if( pt_conn->GetSubNet() ) /* the track segment is already a cluster member */
{
if( pt_pad->m_physical_connexion > 0 ) /* The pad is already a cluster member, so we can merge the 2 clusters */
if( pt_pad->GetSubNet() > 0 ) /* The pad is already a cluster member, so we can merge the 2 clusters */
{
change_equipot( pt_start_conn, pt_end_conn,
pt_pad->m_physical_connexion, pt_conn->GetSubNet() );
Merge_Two_SubNets( pt_start_conn, pt_end_conn,
pt_pad->GetSubNet(), pt_conn->GetSubNet() );
}
else /* The pad is not yet attached to a cluster , so we can add this pad to the cluster */
pt_pad->m_physical_connexion = pt_conn->GetSubNet();
pt_pad->SetSubNet( pt_conn->GetSubNet() );
}
else /* the track segment is not attached to a cluster */
{
if( pt_pad->m_physical_connexion > 0 ) /* it is connected to a pad in a cluster, merge this track */
if( pt_pad->GetSubNet() > 0 ) /* it is connected to a pad in a cluster, merge this track */
{
pt_conn->SetSubNet( pt_pad->m_physical_connexion );
pt_conn->SetSubNet( pt_pad->GetSubNet() );
}
else /* it is connected to a pad not in a cluster, so we must create a new cluster (only with the 2 items: the track and the pad) */
{
sous_net_code++;
pt_conn->SetSubNet( sous_net_code );
pt_pad->m_physical_connexion = pt_conn->GetSubNet();
sub_netcode++;
pt_conn->SetSubNet( sub_netcode );
pt_pad->SetSubNet( pt_conn->GetSubNet() );
}
}
}
@ -169,25 +171,25 @@ static void propage_equipot( TRACK* pt_start_conn, TRACK* pt_end_conn )
pt_pad = (D_PAD*) PtStruct;
if( pt_conn->GetSubNet() )
{
if( pt_pad->m_physical_connexion > 0 )
if( pt_pad->GetSubNet() > 0 )
{
change_equipot( pt_start_conn, pt_end_conn,
pt_pad->m_physical_connexion, pt_conn->GetSubNet() );
Merge_Two_SubNets( pt_start_conn, pt_end_conn,
pt_pad->GetSubNet(), pt_conn->GetSubNet() );
}
else
pt_pad->m_physical_connexion = pt_conn->GetSubNet();
pt_pad->SetSubNet( pt_conn->GetSubNet() );
}
else
{
if( pt_pad->m_physical_connexion > 0 )
if( pt_pad->GetSubNet() > 0 )
{
pt_conn->SetSubNet( pt_pad->m_physical_connexion );
pt_conn->SetSubNet( pt_pad->GetSubNet() );
}
else
{
sous_net_code++;
pt_conn->SetSubNet( sous_net_code );
pt_pad->m_physical_connexion = pt_conn->GetSubNet();
sub_netcode++;
pt_conn->SetSubNet( sub_netcode );
pt_pad->SetSubNet( pt_conn->GetSubNet() );
}
}
}
@ -204,7 +206,7 @@ static void propage_equipot( TRACK* pt_start_conn, TRACK* pt_end_conn )
{
if( pt_autre_piste->GetSubNet() ) /* The other track is already a cluster member, so we can merge the 2 clusters */
{
change_equipot( pt_start_conn, pt_end_conn,
Merge_Two_SubNets( pt_start_conn, pt_end_conn,
pt_autre_piste->GetSubNet(), pt_conn->GetSubNet() );
}
else /* The other track is not yet attached to a cluster , so we can add this other track to the cluster */
@ -220,8 +222,8 @@ static void propage_equipot( TRACK* pt_start_conn, TRACK* pt_end_conn )
}
else /* it is connected to an other segment not in a cluster, so we must create a new cluster (only with the 2 track segments) */
{
sous_net_code++;
pt_conn->SetSubNet( sous_net_code );
sub_netcode++;
pt_conn->SetSubNet( sub_netcode );
pt_autre_piste->SetSubNet( pt_conn->GetSubNet() );
}
}
@ -236,7 +238,7 @@ static void propage_equipot( TRACK* pt_start_conn, TRACK* pt_end_conn )
{
if( pt_autre_piste->GetSubNet() )
{
change_equipot( pt_start_conn, pt_end_conn,
Merge_Two_SubNets( pt_start_conn, pt_end_conn,
pt_autre_piste->GetSubNet(), pt_conn->GetSubNet() );
}
else
@ -250,8 +252,8 @@ static void propage_equipot( TRACK* pt_start_conn, TRACK* pt_end_conn )
}
else
{
sous_net_code++;
pt_conn->SetSubNet( sous_net_code );
sub_netcode++;
pt_conn->SetSubNet( sub_netcode );
pt_autre_piste->SetSubNet( pt_conn->GetSubNet() );
}
}
@ -283,9 +285,12 @@ void WinEDA_BasePcbFrame::test_connexions( wxDC* DC )
pt_pad = m_Pcb->m_Pads;
for( ii = 0; ii < m_Pcb->m_NbPads; ii++, pt_pad++ )
{
(*pt_pad)->m_physical_connexion = 0;
(*pt_pad)->SetZoneSubNet( 0 );
(*pt_pad)->SetSubNet( 0 );
}
m_Pcb->Test_Connections_To_Copper_Areas( );
/* Test existing connections net by net */
pt_start_conn = m_Pcb->m_Track; // this is the first segment of the first net
while( pt_start_conn != NULL )
@ -293,11 +298,13 @@ void WinEDA_BasePcbFrame::test_connexions( wxDC* DC )
current_net_code = pt_start_conn->GetNet(); // this is the current net because pt_start_conn is the first segment of the net
pt_end_conn = pt_start_conn->GetEndNetCode( current_net_code ); // this is the last segment of the current net
calcule_connexite_1_net( pt_start_conn, pt_end_conn );
Build_Pads_Info_Connections_By_Tracks( pt_start_conn, pt_end_conn );
pt_start_conn = (TRACK*) pt_end_conn->Pnext; // this is now the first segment of the next net
}
Merge_SubNets_Connected_By_CopperAreas( m_Pcb );
return;
}
@ -333,9 +340,11 @@ void WinEDA_BasePcbFrame::test_1_net_connexion( wxDC* DC, int net_code )
if( pad_net_code > net_code )
break;
(*pt_pad)->m_physical_connexion = 0;
(*pt_pad)->SetSubNet( 0 );
}
m_Pcb->Test_Connections_To_Copper_Areas( net_code );
/* Search for the first and the last segment relative to the given net code */
if( m_Pcb->m_Track )
{
@ -347,9 +356,10 @@ void WinEDA_BasePcbFrame::test_1_net_connexion( wxDC* DC, int net_code )
if( pt_start_conn && pt_end_conn ) // c.a.d. s'il y a des segments
{
calcule_connexite_1_net( pt_start_conn, pt_end_conn );
Build_Pads_Info_Connections_By_Tracks( pt_start_conn, pt_end_conn );
}
}
Merge_SubNets_Connected_By_CopperAreas( m_Pcb, net_code );
/* Test the rastnest for this net */
nb_net_noconnect = Test_1_Net_Ratsnest( DC, net_code );
@ -364,9 +374,9 @@ void WinEDA_BasePcbFrame::test_1_net_connexion( wxDC* DC, int net_code )
}
/***************************************************************************/
static void calcule_connexite_1_net( TRACK* pt_start_conn, TRACK* pt_end_conn )
/***************************************************************************/
/*******************************************************************************************/
static void Build_Pads_Info_Connections_By_Tracks( TRACK* pt_start_conn, TRACK* pt_end_conn )
/*******************************************************************************************/
/** Used after a track change (delete a track ou add a track)
* Compute connections (initialize the .start and .end members) for a single net.
@ -435,8 +445,8 @@ static void calcule_connexite_1_net( TRACK* pt_start_conn, TRACK* pt_end_conn )
break;
}
/* Generation des sous equipots du net */
propage_equipot( pt_start_conn, pt_end_conn );
/* Creates sub nets (cluster) for the current net: */
Propagate_SubNet( pt_start_conn, pt_end_conn );
}
@ -600,6 +610,7 @@ void WinEDA_BasePcbFrame::reattribution_reference_piste( int affiche )
for( ; pt_piste != NULL; pt_piste = (TRACK*) pt_piste->Pnext )
{
pt_piste->SetState( BUSY | EDIT | BEGIN_ONPAD | END_ONPAD, OFF );
pt_piste->SetZoneSubNet( 0 );
pt_piste->SetNet( 0 ); // net code = 0 means not connected
}

View File

@ -548,7 +548,9 @@ void WinEDA_PcbFrame::Process_Special_Functions( wxCommandEvent& event )
case ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_CURRENT_ZONE:
if ( ( GetCurItem())->Type() == TYPEZONE_CONTAINER)
{
((ZONE_CONTAINER* )GetCurItem())->m_FilledPolysList.clear();
ZONE_CONTAINER* zone_container = (ZONE_CONTAINER* )GetCurItem();
zone_container->m_FilledPolysList.clear();
test_1_net_connexion( NULL, zone_container->GetNet( ));
GetScreen()->SetModify();
DrawPanel->Refresh();
}
@ -566,13 +568,16 @@ void WinEDA_PcbFrame::Process_Special_Functions( wxCommandEvent& event )
ZONE_CONTAINER* zone_container = m_Pcb->GetArea( ii );
zone_container->m_FilledPolysList.clear();;
}
test_connexions( NULL );
GetScreen()->SetModify();
DrawPanel->Refresh();
break;
case ID_POPUP_PCB_FILL_ZONE:
DrawPanel->MouseToCursorSchema();
Fill_Zone( &dc, (ZONE_CONTAINER*) GetCurItem() );
Fill_Zone( NULL, (ZONE_CONTAINER*) GetCurItem() );
test_1_net_connexion( NULL, ((ZONE_CONTAINER* )GetCurItem())->GetNet( ));
DrawPanel->Refresh();
break;
case ID_PCB_DELETE_ITEM_BUTT:

View File

@ -158,7 +158,7 @@ void CreatePadsShapesSection( FILE* file, BOARD* pcb )
/*****************************************************/
/* Cree la liste des formes des pads ( 1 forme par pad )
* initialise le membre .m_logical_connexion de la struct pad, la valeur 1 ..n
* initialise le membre .GetSubRatsnest de la struct pad, la valeur 1 ..n
* pour les formes de pad PAD1 a PADn
*/
{
@ -186,7 +186,7 @@ void CreatePadsShapesSection( FILE* file, BOARD* pcb )
for( padlist = pad_list_base, ii = 0; ii < pcb->m_NbPads; padlist++, ii++ )
{
pad = *padlist;
pad->m_logical_connexion = pad_name_number;
pad->SetSubRatsnest( pad_name_number );
if( old_pad && 0==D_PAD::Compare( old_pad, pad ) )
continue; // Forme deja generee
@ -194,9 +194,9 @@ void CreatePadsShapesSection( FILE* file, BOARD* pcb )
old_pad = pad;
pad_name_number++;
pad->m_logical_connexion = pad_name_number;
pad->SetSubRatsnest( pad_name_number );
fprintf( file, "PAD PAD%d", pad->m_logical_connexion );
fprintf( file, "PAD PAD%d", pad->GetSubRatsnest() );
dx = pad->m_Size.x / 2;
dy = pad->m_Size.y / 2;
@ -336,7 +336,7 @@ void CreateShapesSection( FILE* file, BOARD* pcb )
orient = pad->m_Orient - module->m_Orient;
NORMALIZE_ANGLE_POS( orient );
fprintf( file, "PIN %s PAD%d %d %d %s %d %s",
CONV_TO_UTF8( pinname ), pad->m_logical_connexion,
CONV_TO_UTF8( pinname ), pad->GetSubRatsnest(),
pad->m_Pos0.x, -pad->m_Pos0.y,
layer, orient / 10, mirror );
if( orient % 10 )

View File

@ -18,7 +18,8 @@ ZONE_FILES = zones_by_polygon.o zones_test_and_combine_areas.o\
dialog_non_copper_zones_properties_base.o\
zones_non_copper_type_functions.o\
zones_convert_brd_items_to_polygons.o\
zones_polygons_insulated_copper_islands.o
zones_polygons_insulated_copper_islands.o\
zones_polygons_test_connections.o
SPECCTRA_TOOLS = specctra.o specctra_export.o dsn.o specctra_import.o
@ -54,6 +55,7 @@ OBJECTS= $(TARGET).o classpcb.o\
class_text_mod.o\
class_pcb_text.o\
class_board_item.o\
class_board_connected_item.o\
class_drc_item.o\
class_board.o\
class_zone.o\

View File

@ -28,8 +28,8 @@ static bool DisplayRastnestInProgress; // Enable the display of the ratsnes
* Building the general ratsnest:
* I used the "lee algoritm".
* This is a 2 steps algoritm.
* the m_logical_connexion member of pads handle a "block number" or a "cluster number" or a "subnet number"
* initially, m_logical_connexion = 0 (pad not connected).
* the m_SubRatsnest member of pads handle a "block number" or a "cluster number" or a "subnet number"
* initially, m_SubRatsnest = 0 (pad not connected).
* Build_Board_Ratsnest( wxDC* DC ) Create this rastnest
* for each net:
* First:
@ -40,7 +40,7 @@ static bool DisplayRastnestInProgress; // Enable the display of the ratsnes
* the pads are grouped in a logical block ( a cluster).
* until no pad without link found.
* Each logical block has a number called block number or "subnet number",
* stored in m_logical_connexion member for each pad of the block.
* stored in m_SubRatsnest member for each pad of the block.
* The first block has its block number = 1, the second is 2 ...
* the function to do thas is gen_rats_pad_to_pad()
*
@ -72,7 +72,7 @@ static bool DisplayRastnestInProgress; // Enable the display of the ratsnes
* (no physical track exists) or not (a physical track exists)
* if a track is added or deleted only the corresponding net is tested.
*
* the m_logical_connexion member of pads is set to 0 (no blocks), and alls links are set to INACTIVE (ratsnest not show).
* the m_SubRatsnest member of pads is set to 0 (no blocks), and alls links are set to INACTIVE (ratsnest not show).
* Before running this fast lee algorithm, we create blocks (and their corresponding block number)
* by grouping pads connected by tracks.
* So, when tracks exists, the fast lee algorithm is started with some blocks already created.
@ -81,7 +81,7 @@ static bool DisplayRastnestInProgress; // Enable the display of the ratsnes
* when a track is created without noticeable computing time
* First:
* for all links (in this step, all are inactive):
* search for a link which have 1 (or 2) pad having the m_logical_connexion member = 0.
* search for a link which have 1 (or 2) pad having the m_SubRatsnest member = 0.
* if found the link is set to ACTIVE (i.e. the ratsnest will be showed) and the pad is meged with the block
* or a new block is created ( see tst_rats_pad_to_pad() ).
* Secondly:
@ -192,7 +192,7 @@ static int gen_rats_block_to_block( WinEDA_DrawPanel* DrawPanel, wxDC* DC,
* The search is made between the pads in block 1 (the reference block) and other blocks
* the block n ( n > 1 ) it connected to block 1 by their 2 nearest pads.
* When the block is found, it is merged with the block 1
* the D_PAD member m_logical_connexion handles the block number
* the D_PAD member m_SubRatsnest handles the block number
* @param pt_liste_pad = starting address (within the pad list) for search
* @param pt_limite = ending address (within the pad list) for search
* return in global variables:
@ -223,7 +223,7 @@ static int gen_rats_block_to_block( WinEDA_DrawPanel* DrawPanel, wxDC* DC,
D_PAD* ref_pad = *pt_liste_pad;
/* search a pad which is in the block 1 */
if( ref_pad->m_logical_connexion != 1 )
if( ref_pad->GetSubRatsnest() != 1 )
continue;
/* pad is found, search its nearest neighbour in other blocks */
@ -234,7 +234,7 @@ static int gen_rats_block_to_block( WinEDA_DrawPanel* DrawPanel, wxDC* DC,
if( pt_liste_pad_aux >= pt_limite )
break;
if( curr_pad->m_logical_connexion == 1 ) // not in an other block
if( curr_pad->GetSubRatsnest() == 1 ) // not in an other block
continue;
/* Compare distance between pads ("Manhattan" distance) */
@ -245,7 +245,7 @@ static int gen_rats_block_to_block( WinEDA_DrawPanel* DrawPanel, wxDC* DC,
{
// The tested block can be a good candidate for merging
// we memorise the "best" current values for merging
current_num_block = curr_pad->m_logical_connexion;
current_num_block = curr_pad->GetSubRatsnest();
dist_min = current_dist;
pt_liste_pad_tmp = pt_liste_pad_aux;
@ -262,12 +262,12 @@ static int gen_rats_block_to_block( WinEDA_DrawPanel* DrawPanel, wxDC* DC,
if( current_num_block > 1 )
{
/* The block n is merged with the bloc 1 :
* to do that, we set the m_logical_connexion member to 1 for all pads in block n
* to do that, we set the m_SubRatsnest member to 1 for all pads in block n
*/
for( pt_liste_pad = pt_start_liste; pt_liste_pad < pt_limite; pt_liste_pad++ )
{
if( (*pt_liste_pad)->m_logical_connexion == current_num_block )
(*pt_liste_pad)->m_logical_connexion = 1;
if( (*pt_liste_pad)->GetSubRatsnest() == current_num_block )
(*pt_liste_pad)->SetSubRatsnest( 1 );
}
pt_liste_pad = pt_liste_pad_block1;
@ -336,7 +336,7 @@ static int gen_rats_pad_to_pad( WinEDA_DrawPanel* DrawPanel, wxDC* DC,
{
ref_pad = *pt_liste_pad;
if( ref_pad->m_logical_connexion )
if( ref_pad->GetSubRatsnest() )
continue; // Pad already connected
pt_liste_pad_tmp = NULL;
@ -370,16 +370,16 @@ static int gen_rats_pad_to_pad( WinEDA_DrawPanel* DrawPanel, wxDC* DC,
/* Update the block number
* if the 2 pads are not already created : a new block is created
*/
if( (pad->m_logical_connexion == 0) && (ref_pad->m_logical_connexion == 0) )
if( (pad->GetSubRatsnest() == 0) && (ref_pad->GetSubRatsnest() == 0) )
{
current_num_block++;
pad->m_logical_connexion = current_num_block;
ref_pad->m_logical_connexion = current_num_block;
pad->SetSubRatsnest( current_num_block);
ref_pad->SetSubRatsnest( current_num_block);
}
/* If a pad is already connected connected : merge the other pad in the block */
else
{
ref_pad->m_logical_connexion = pad->m_logical_connexion;
ref_pad->SetSubRatsnest( pad->GetSubRatsnest());
}
(*nblinks)++;
@ -456,7 +456,7 @@ void WinEDA_BasePcbFrame::Build_Board_Ratsnest( wxDC* DC )
for( ii = m_Pcb->m_NbPads; ii > 0; pt_liste_pad++, ii-- )
{
pad = *pt_liste_pad;
pad->m_logical_connexion = 0;
pad->SetSubRatsnest( 0 );
}
/* Sort the pad list by nets */
@ -503,7 +503,7 @@ void WinEDA_BasePcbFrame::Build_Board_Ratsnest( wxDC* DC )
}
/* Search the end of pad list des pads for the current net */
num_block = pad->m_logical_connexion;
num_block = pad->GetSubRatsnest();
nbpads = 0;
for( pt_end_liste = pt_liste_pad + 1; ; pt_end_liste++ )
{
@ -515,8 +515,8 @@ void WinEDA_BasePcbFrame::Build_Board_Ratsnest( wxDC* DC )
break;
nbpads++;
if( num_block < pad->m_logical_connexion )
num_block = pad->m_logical_connexion;
if( num_block < pad->GetSubRatsnest() )
num_block = pad->GetSubRatsnest();
}
m_Pcb->m_NbLinks += nbpads;
@ -668,7 +668,7 @@ static int tst_rats_block_to_block( WinEDA_DrawPanel* DrawPanel, wxDC* DC,
min_chevelu = NULL;
for( chevelu = start_rat_list; chevelu < end_rat_list; chevelu++ )
{
if( chevelu->pad_start->m_logical_connexion == chevelu->pad_end->m_logical_connexion ) // Same block
if( chevelu->pad_start->GetSubRatsnest() == chevelu->pad_end->GetSubRatsnest() ) // Same block
continue;
if( min_chevelu == NULL )
@ -684,8 +684,8 @@ static int tst_rats_block_to_block( WinEDA_DrawPanel* DrawPanel, wxDC* DC,
* we must set its status to ACTIVE and merge the 2 blocks
*/
min_chevelu->status |= CH_ACTIF;
current_num_block = min_chevelu->pad_start->m_logical_connexion;
min_block = min_chevelu->pad_end->m_logical_connexion;
current_num_block = min_chevelu->pad_start->GetSubRatsnest();
min_block = min_chevelu->pad_end->GetSubRatsnest();
if( min_block > current_num_block )
EXCHG( min_block, current_num_block );
@ -693,9 +693,9 @@ static int tst_rats_block_to_block( WinEDA_DrawPanel* DrawPanel, wxDC* DC,
/* Merging the 2 blocks in one cluster */
for( pt_liste_pad = pt_liste_pad_start; pt_liste_pad < pt_liste_pad_end; pt_liste_pad++ )
{
if( (*pt_liste_pad)->m_logical_connexion == current_num_block )
if( (*pt_liste_pad)->GetSubRatsnest() == current_num_block )
{
(*pt_liste_pad)->m_logical_connexion = min_block;
(*pt_liste_pad)->SetSubRatsnest( min_block);
}
}
@ -723,7 +723,7 @@ static int tst_rats_pad_to_pad( WinEDA_DrawPanel* DrawPanel, wxDC* DC,
*
* output:
* ratsnest list (status member set)
* and pad list (m_logical_connexion set)
* and pad list (m_SubRatsnest set)
*
* @return new block number
*/
@ -738,22 +738,22 @@ static int tst_rats_pad_to_pad( WinEDA_DrawPanel* DrawPanel, wxDC* DC,
/* Update the block if the 2 pads are not connected : a new block is created
*/
if( (pad_start->m_logical_connexion == 0) && (pad_end->m_logical_connexion == 0) )
if( (pad_start->GetSubRatsnest() == 0) && (pad_end->GetSubRatsnest() == 0) )
{
current_num_block++;
pad_start->m_logical_connexion = current_num_block;
pad_end->m_logical_connexion = current_num_block;
pad_start->SetSubRatsnest( current_num_block);
pad_end->SetSubRatsnest( current_num_block);
chevelu->status |= CH_ACTIF;
}
/* If a pad is already connected : the other is merged in the current block */
else if( pad_start->m_logical_connexion == 0 )
else if( pad_start->GetSubRatsnest() == 0 )
{
pad_start->m_logical_connexion = pad_end->m_logical_connexion;
pad_start->SetSubRatsnest( pad_end->GetSubRatsnest() );
chevelu->status |= CH_ACTIF;
}
else if( pad_end->m_logical_connexion == 0 )
else if( pad_end->GetSubRatsnest() == 0 )
{
pad_end->m_logical_connexion = pad_start->m_logical_connexion;
pad_end->SetSubRatsnest( pad_start->GetSubRatsnest() );
chevelu->status |= CH_ACTIF;
}
}
@ -795,8 +795,8 @@ void WinEDA_BasePcbFrame::Tst_Ratsnest( wxDC* DC, int ref_netcode )
for( ; pt_liste_pad < equipot->m_PadzoneEnd; pt_liste_pad++ )
{
pad = *pt_liste_pad;
pad->m_logical_connexion = pad->m_physical_connexion;
num_block = MAX( num_block, pad->m_logical_connexion );
pad->SetSubRatsnest( pad->GetSubNet() );
num_block = MAX( num_block, pad->GetSubRatsnest() );
}
for( chevelu = equipot->m_RatsnestStart; chevelu < equipot->m_RatsnestEnd; chevelu++ )
@ -981,7 +981,7 @@ void WinEDA_BasePcbFrame::build_liste_pads()
* m_Pcb->m_NbPads = pad count
* m_Pcb->m_NbNodes = node count
* set m_Pcb->m_Status_Pcb = LISTE_PAD_OK;
* and clear for all pad their m_logical_connexion member;
* and clear for all pad their m_SubRatsnest member;
* delete ( free memory) m_Pcb->m_Ratsnest and set m_Pcb->m_Ratsnest to NULL
*/
{
@ -1025,7 +1025,7 @@ void WinEDA_BasePcbFrame::build_liste_pads()
for( ; PtPad != NULL; PtPad = (D_PAD*) PtPad->Pnext )
{
*pt_liste_pad = PtPad;
PtPad->m_logical_connexion = 0;
PtPad->SetSubRatsnest( 0 );
PtPad->m_Parent = Module; // Just in case
if( PtPad->GetNet() )
@ -1106,8 +1106,8 @@ char* WinEDA_BasePcbFrame::build_ratsnest_module( wxDC* DC, MODULE* Module )
continue;
*pt_liste_pad = pad_ref;
pad_ref->m_logical_connexion = 0;
pad_ref->m_physical_connexion = 0;
pad_ref->SetSubRatsnest( 0 );
pad_ref->SetSubNet( 0 );
pt_liste_pad++; nb_pads_ref++;
}
@ -1140,8 +1140,8 @@ char* WinEDA_BasePcbFrame::build_ratsnest_module( wxDC* DC, MODULE* Module )
if( pad_externe->m_Parent == Module )
continue;
pad_externe->m_logical_connexion = 0;
pad_externe->m_physical_connexion = 0;
pad_externe->SetSubRatsnest(0);
pad_externe->SetSubNet( 0 );
*pt_liste_pad = pad_externe;
pt_liste_pad++;
@ -1154,7 +1154,7 @@ char* WinEDA_BasePcbFrame::build_ratsnest_module( wxDC* DC, MODULE* Module )
qsort( pt_liste_ref + nb_pads_ref, nb_pads_externes, sizeof(D_PAD*),
tri_par_net );
/* Compute the internal ratsnet:
/* Compute the internal rats nest:
* this is the same as general ratsnest, but considers only the current footprint pads
* it is therefore not time consuming, and it is made only once
*/
@ -1413,7 +1413,7 @@ int* WinEDA_BasePcbFrame::build_ratsnest_pad( EDA_BaseStruct* ref,
case TYPEPAD:
pad_ref = (D_PAD*) ref;
current_net_code = pad_ref->GetNet();
conn_number = pad_ref->m_physical_connexion;
conn_number = pad_ref->GetSubNet();
break;
case TYPETRACK:
@ -1448,7 +1448,7 @@ int* WinEDA_BasePcbFrame::build_ratsnest_pad( EDA_BaseStruct* ref,
if( pad == pad_ref )
continue;
if( !pad->m_physical_connexion || (pad->m_physical_connexion != conn_number) )
if( !pad->GetSubNet() || (pad->GetSubNet() != conn_number) )
{
*pt_coord = pad->m_Pos.x; pt_coord++;
*pt_coord = pad->m_Pos.y; pt_coord++;

View File

@ -199,7 +199,7 @@ void Out_Pads( BOARD* Pcb, FILE* outfile )
{
pt_pad = *pt_liste_pad;
netcode = pt_pad->GetNet();
plink = pt_pad->m_physical_connexion;
plink = pt_pad->GetSubNet();
/* plink = numero unique si pad non deja connecte a une piste */
if( plink <= 0 )
plink = no_conn++;

View File

@ -956,7 +956,7 @@ int WinEDA_PcbFrame::Fill_All_Zones( wxDC* DC, bool verbose )
if( error_level && !verbose )
break;
}
m_Pcb->Test_Connections_To_Copper_Areas( );
DrawPanel->Refresh( true );
return error_level;
}

View File

@ -19,7 +19,6 @@
using namespace std;
#include "fctsys.h"
#include "gr_basic.h"
#include "common.h"
#include "pcbnew.h"
@ -28,17 +27,8 @@ using namespace std;
#include "zones.h"
static void CalculateSubAreaBoundaryBox( EDA_Rect& aBbox,
std::vector <CPolyPt> aPolysList,
int aIndexStart,
int aIndexEnd );
/* Local variables */
std::vector <wxPoint> s_ListPoints; // list of coordinates of pads and vias on this layer and on this net.
/***************************************************************************************/
void ZONE_CONTAINER::Test_For_Copper_Island_And_Remove_Insulated_Islands( BOARD* aPcb )
void ZONE_CONTAINER::Test_For_Copper_Island_And_Remove_Insulated_Islands( BOARD * aPcb )
/***************************************************************************************/
/**
@ -50,11 +40,15 @@ void ZONE_CONTAINER::Test_For_Copper_Island_And_Remove_Insulated_Islands( BOARD*
if( m_FilledPolysList.size() == 0 )
return;
// Build the list:
s_ListPoints.clear();
for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
// Build a list of points connected to the net:
std::vector <wxPoint> ListPointsCandidates; // list of coordinates of pads and vias on this layer and on this net.
for( MODULE* module = aPcb->m_Modules;
module;
module = module->Next() )
{
for( D_PAD* pad = module->m_Pads; pad != NULL; pad = pad->Next() )
for( D_PAD* pad = module->m_Pads;
pad != NULL;
pad = pad->Next() )
{
if( !pad->IsOnLayer( GetLayer() ) )
continue;
@ -62,82 +56,91 @@ void ZONE_CONTAINER::Test_For_Copper_Island_And_Remove_Insulated_Islands( BOARD*
if( pad->GetNet() != GetNet() )
continue;
s_ListPoints.push_back( pad->m_Pos );
ListPointsCandidates.push_back( pad->m_Pos );
}
}
for( TRACK* track = aPcb->m_Track; track; track = track->Next() )
for( TRACK* track = aPcb->m_Track;
track;
track = track->Next() )
{
if( !track->IsOnLayer( GetLayer() ) )
continue;
if( track->GetNet() != GetNet() )
continue;
s_ListPoints.push_back( track->m_Start );
ListPointsCandidates.push_back( track->m_Start );
if( track->Type() != TYPEVIA )
s_ListPoints.push_back( track->m_End );
ListPointsCandidates.push_back( track->m_End );
}
// test if a point is inside
unsigned indexstart = 0, indexend;
bool connected = false;
for( indexend = 0; indexend < m_FilledPolysList.size(); indexend++ )
for( indexend = 0;
indexend < m_FilledPolysList.size();
indexend++ )
{
if( m_FilledPolysList[indexend].end_contour ) // end of area found
if( m_FilledPolysList[indexend].end_contour ) // end of a filled sub-area found
{
EDA_Rect bbox;
CalculateSubAreaBoundaryBox( bbox, m_FilledPolysList, indexstart, indexend );
for( unsigned ic = 0; ic < s_ListPoints.size(); ic++ )
{
wxPoint pos = s_ListPoints[ic];
EDA_Rect bbox =
CalculateSubAreaBoundaryBox( indexstart,
indexend );
for( unsigned ic = 0;
ic < ListPointsCandidates.size();
ic++ )
{ // test if this area is connected to a board item:
wxPoint pos = ListPointsCandidates[ic];
if( !bbox.Inside( pos ) )
continue;
if( TestPointInsidePolygon( m_FilledPolysList, indexstart, indexend, pos.x, pos.y ) )
if( TestPointInsidePolygon(
m_FilledPolysList, indexstart,
indexend, pos.x,
pos.y ) )
{
connected = true;
break;
}
}
if( connected ) // this polygon is connected: analyse next polygon
if( connected ) // this polygon is connected: analyse next polygon
{
indexstart = indexend + 1; // indexstart points the first point of the next polygon
indexstart = indexend + 1; // indexstart points the first point of the next polygon
connected = false;
}
else // Not connected: remove this polygon
else // Not connected: remove this polygon
{
m_FilledPolysList.erase(
m_FilledPolysList.begin() + indexstart,
m_FilledPolysList.begin() + indexend + 1 );
indexend = indexstart; /* indexstart points the first point of the next polygon
* because the current poly is removed */
m_FilledPolysList.begin() + indexend +
1 );
indexend = indexstart; /* indexstart points the first point of the next polygon
* because the current poly is removed */
}
}
}
}
/******************************************************************/
void CalculateSubAreaBoundaryBox( EDA_Rect& aBbox,
std::vector <CPolyPt> aPolysList,
int aIndexStart,
int aIndexEnd )
/******************************************************************/
/**************************************************************************************/
EDA_Rect ZONE_CONTAINER::CalculateSubAreaBoundaryBox( int aIndexStart, int aIndexEnd )
/**************************************************************************************/
/** function CalculateSubAreaBoundaryBox
* Calculates the bounding box of a polygon stored in a vector <CPolyPt>
* @param aBbox = EDA_Rect to init as bounding box
* @param aPolysList = set of CPolyPt that are the corners of one or more polygons
* @param aIndexStart = index of the first corner of a polygon in aPolysList
* @param aIndexEnd = index of the last corner of a polygon in aPolysList
* Calculates the bounding box of a a filled area ( list of CPolyPt )
* use m_FilledPolysList as list of CPolyPt (that are the corners of one or more polygons or filled areas )
* @return an EDA_Rect as bounding box
* @param aIndexStart = index of the first corner of a polygon (filled area) in m_FilledPolysList
* @param aIndexEnd = index of the last corner of a polygon in m_FilledPolysList
*/
{
CPolyPt start_point, end_point;
CPolyPt start_point, end_point;
EDA_Rect bbox;
start_point = aPolysList[aIndexStart];
start_point = m_FilledPolysList[aIndexStart];
end_point = start_point;
for( int ii = aIndexStart; ii <= aIndexEnd; ii++ )
{
CPolyPt ptst = aPolysList[ii];
CPolyPt ptst = m_FilledPolysList[ii];
if( start_point.x > ptst.x )
start_point.x = ptst.x;
if( start_point.y > ptst.y )
@ -148,6 +151,8 @@ void CalculateSubAreaBoundaryBox( EDA_Rect& aBbox,
end_point.y = ptst.y;
}
aBbox.SetOrigin( start_point.x, start_point.y );
aBbox.SetEnd( wxPoint( end_point.x, end_point.y ) );
bbox.SetOrigin( start_point.x, start_point.y );
bbox.SetEnd( wxPoint( end_point.x, end_point.y ) );
return bbox;
}

View File

@ -0,0 +1,337 @@
/////////////////////////////////////////////////////////////////////////////
// Name: zones_polygons_test_connections.cpp
// Licence: GPL License
/////////////////////////////////////////////////////////////////////////////
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
using namespace std;
#include <algorithm> // sort
#include <vector>
#include "fctsys.h"
#include "common.h"
#include "pcbnew.h"
#include "PolyLine.h"
#include "zones.h"
static bool CmpZoneSubnetValue( const BOARD_CONNECTED_ITEM* a, const BOARD_CONNECTED_ITEM* b );
void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb, int aNetcode );
/***********************************************************/
void BOARD::Test_Connections_To_Copper_Areas( int aNetcode )
/***********************************************************/
/**
* Function Test_Connection_To_Copper_Areas
* init .m_ZoneSubnet parameter in tracks and pads according to the connections to areas found
* @param aNetcode = netcode to analyse. if -1, analyse all nets
*/
{
std::vector <BOARD_CONNECTED_ITEM*> Candidates; // list of pads and tracks candidates on this layer and on this net.
int subnet = 0;
int netcode;
ZONE_CONTAINER* curr_zone;
BOARD_CONNECTED_ITEM* item;
// clear .m_ZoneSubnet parameter for pads
for( MODULE* module = m_Modules; module; module = module->Next() )
{
for( D_PAD* pad = module->m_Pads; pad != NULL; pad = pad->Next() )
if( (aNetcode < 0) || ( aNetcode == pad->GetNet() ) )
pad->SetZoneSubNet( 0 );
}
// clear .m_ZoneSubnet parameter for tracks and vias
for( TRACK* track = m_Track; track; track = track->Next() )
{
if( (aNetcode < 0) || ( aNetcode == track->GetNet() ) )
track->SetZoneSubNet( 0 );
}
// examine all zones, net by net:
for( int index = 0; index < GetAreaCount(); index++ )
{
curr_zone = GetArea( index );
if( !curr_zone->IsOnCopperLayer() )
continue;
netcode = curr_zone->GetNet();
if( (aNetcode >= 0) && !( aNetcode == netcode ) )
continue;
if( curr_zone->m_FilledPolysList.size() == 0 )
continue;
// Build a list of candidates connected to the net:
Candidates.clear();
// At this point, layers are not considered, because areas on different layers can be connected by a via or a pad.
for( MODULE* module = m_Modules; module; module = module->Next() )
{
for( D_PAD* pad = module->m_Pads; pad != NULL; pad = pad->Next() )
{
if( pad->GetNet() != curr_zone->GetNet() )
continue;
Candidates.push_back( pad );
}
}
for( TRACK* track = m_Track; track; track = track->Next() )
{
if( track->GetNet() != netcode )
continue;
Candidates.push_back( track );
}
// test if a candidate is inside a filled area of this zone
unsigned indexstart = 0, indexend;
for( indexend = 0; indexend < curr_zone->m_FilledPolysList.size(); indexend++ )
{
if( curr_zone->m_FilledPolysList[indexend].end_contour ) // end of a filled sub-area found
{
subnet++;
EDA_Rect bbox = curr_zone->CalculateSubAreaBoundaryBox( indexstart, indexend );
for( unsigned ic = 0; ic < Candidates.size(); ic++ )
{ // test if this area is connected to a board item:
item = Candidates[ic];
if( !item->IsOnLayer( curr_zone->GetLayer() ) )
continue;
wxPoint pos1, pos2;
if( item->Type() == TYPEPAD )
{
pos1 = pos2 = ( (D_PAD*) item )->m_Pos;
}
else if( item->Type() == TYPEVIA )
{
pos1 = pos2 = ( (SEGVIA*) item )->m_Start;
}
else if( item->Type() == TYPETRACK )
{
pos1 = ( (TRACK*) item )->m_Start;
pos2 = ( (TRACK*) item )->m_End;
}
else
continue;
bool connected = false;
if( bbox.Inside( pos1 ) )
{
if( TestPointInsidePolygon( curr_zone->m_FilledPolysList, indexstart,
indexend, pos1.x, pos1.y ) )
connected = true;
}
if( !connected && (pos1 != pos2 ) )
{
if( bbox.Inside( pos2 ) )
if( TestPointInsidePolygon( curr_zone->m_FilledPolysList, indexstart,
indexend, pos2.x, pos2.y ) )
connected = true;
}
if( connected )
{ // Set ZoneSubnet to the current subnet value.
// If the previous subnet is not 0, merge all items with old subnet to the new one
int old_subnet = 0;
old_subnet = item->GetZoneSubNet();
item->SetZoneSubNet( subnet );
if( (old_subnet > 0) && (old_subnet != subnet) ) // Merge previous subnet with the current
{
//printf(" merge subnets: %d et %d (%d)\n", old_subnet, subnet,item->Type());
for( unsigned jj = 0; jj < Candidates.size(); jj++ )
{
BOARD_CONNECTED_ITEM* item_to_merge = Candidates[jj];
if( old_subnet == item_to_merge->GetZoneSubNet() )
item_to_merge->SetZoneSubNet( subnet );
}
} // End if ( old_subnet > 0 )
} // End if( connected )
}
// End test candidates for the current filled area
indexstart = indexend + 1; // prepare test next area, starting at indexend+1 (if exists)
} // End read one area in curr_zone->m_FilledPolysList
}
// End read full curr_zone->m_FilledPolysList
}
// End read all zones in board
}
/**************************************************************************************************/
void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb )
/**************************************************************************************************/
/** Function Merge_SubNets_Connected_By_CopperAreas(BOARD* aPcb)
* Calls Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb, int aNetcode ) for each netcode found in zone list
* @param aPcb = the current board
*/
{
for( int index = 0; index < aPcb->GetAreaCount(); index++ )
{
ZONE_CONTAINER* curr_zone = aPcb->GetArea( index );
if ( ! curr_zone->IsOnCopperLayer() )
continue;
if ( curr_zone->GetNet() <= 0 )
continue;
Merge_SubNets_Connected_By_CopperAreas( aPcb, curr_zone->GetNet() );
}
}
/**************************************************************************************************/
void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb, int aNetcode )
/**************************************************************************************************/
/** Function Merge_SubNets_Connected_By_CopperAreas(BOARD* aPcb, int aNetcode)
* Used after connections by tracks calculations
* Merge subnets, in tracks ans pads when they are connected by a filled copper area
* for pads, this is the .m_physical_connexion member which is tested and modified
* for tracks, this is the .m_Subnet member which is tested and modified
* these members are block numbers (or cluster numbers) for a given net,
* calculated by Build_Pads_Info_Connections_By_Tracks()
* The result is merging 2 blocks (or subnets)
* @param aPcb = the current board
* @param aNetcode = netcode to consider
*/
{
BOARD_CONNECTED_ITEM* item;
int old_subnet, subnet, next_subnet_free_number;
int old_zone_subnet, zone_subnet;
// Ensure a zone with the given netcode exists: examine all zones:
bool found = false;
for( int index = 0; index < aPcb->GetAreaCount(); index++ )
{
ZONE_CONTAINER* curr_zone = aPcb->GetArea( index );
if( aNetcode == curr_zone->GetNet() )
{
found = true;
break;
}
}
if( !found ) // No zone with this netcode, therefore no connection by zone
return;
printf(" Merge_SubNets net = %d\n", aNetcode);
std::vector <BOARD_CONNECTED_ITEM*> Candidates; // list of pads and tracks candidates to test.
// Build a list of candidates connected to the net:
next_subnet_free_number = 0;
for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
{
for( D_PAD* pad = module->m_Pads; pad != NULL; pad = pad->Next() )
{
if( pad->GetNet() == aNetcode )
{
Candidates.push_back( pad );
next_subnet_free_number = MAX( next_subnet_free_number, pad->GetSubNet() );
}
}
}
for( TRACK* track = aPcb->m_Track; track; track = track->Next() )
{
if( track->GetNet() == aNetcode )
{
Candidates.push_back( track );
next_subnet_free_number = MAX( next_subnet_free_number, track->GetSubNet() );
}
}
if( Candidates.size() == 0 )
return;
next_subnet_free_number++; // This is a subnet we can use with not connected items by tracks, but connected by zone.
// Sort by zone_subnet:
sort( Candidates.begin(), Candidates.end(), CmpZoneSubnetValue );
// Some items can be not connected, but they can be connected to a filled area:
// give them a subnet common to these items connected only by the area, and not already used.
// a value like next_subnet_free_number+zone_subnet is right
for( unsigned jj = 0; jj < Candidates.size(); jj++ )
{
item = Candidates[jj];
if ( item->GetSubNet() == 0 && (item->GetZoneSubNet() > 0) )
{
item->SetSubNet( next_subnet_free_number + item->GetZoneSubNet() );
}
}
// Now, for each zone subnet, we search for 2 items with different subnets.
// if found, the 2 subnet are merged in the whole candidate list.
old_subnet = 0;
old_zone_subnet = 0;
for( unsigned ii = 0; ii < Candidates.size(); ii++ )
{
item = Candidates[ii];
zone_subnet = item->GetZoneSubNet();
if( zone_subnet == 0 ) // Not connected by a filled area, skip it
continue;
subnet = item->GetSubNet();
if( zone_subnet != old_zone_subnet ) // a new zone subnet is found
{
old_subnet = subnet;
old_zone_subnet = zone_subnet;
continue;
}
zone_subnet = old_zone_subnet;
if( subnet == old_subnet ) // 2 successive items already from the same cluster: nothing to do
continue;
// Here we have 2 items connected by the same area have 2 differents subnets: merge subnets
if( (subnet > old_subnet) || ( subnet <= 0) )
EXCHG( subnet, old_subnet );
for( unsigned jj = 0; jj < Candidates.size(); jj++ )
{
BOARD_CONNECTED_ITEM * item_to_merge = Candidates[jj];
if( item_to_merge->GetSubNet() == old_subnet )
item_to_merge->SetSubNet( subnet );
}
old_subnet = subnet;
}
}
/* Compare function used for sorting candidates by increasing zone zubnet
*/
static bool CmpZoneSubnetValue( const BOARD_CONNECTED_ITEM* a, const BOARD_CONNECTED_ITEM* b )
{
int asubnet, bsubnet;
asubnet = a->GetZoneSubNet();
bsubnet = b->GetZoneSubNet();
return asubnet < bsubnet;
}

View File

@ -22,7 +22,7 @@ using namespace std;
* the first version is for explanations and tests (used to test the second version)
* both use the same algorithm.
*/
#if 0
#if 1
/* This text and the algorithm come from http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
*