Commit 178bc946 authored by charras's avatar charras

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

parent f43a7acc
......@@ -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
......
......@@ -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
......
......@@ -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
......@@ -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
......
......@@ -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
hotkeys.o: hotkeys.cpp hotkeys.h $(COMMON)
set_color.o: set_color.cpp set_color.h
set_color.o: set_color.cpp set_color.h $(COMMON)
files.o: files.cpp
files.o: files.cpp $(COMMON)
class_board_connected_item.o: ../pcbnew/class_board_connected_item.cpp
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_marker.o: ../pcbnew/class_marker.cpp ../pcbnew/class_marker.h $(COMMON)
class_marker.o: ../pcbnew/class_marker.cpp ../pcbnew/class_marker.h
$(CXX) -c $(EDACPPFLAGS) -o $@ ../pcbnew/$*.cpp
class_zone.o: ../pcbnew/class_zone.cpp ../pcbnew/class_zone.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 $(COMMON)
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
/*********************************************************************/
/* 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 */
No preview for this file type
This diff is collapsed.
......@@ -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
)
......
......@@ -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++;
......
......@@ -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
/*************************************************************************/
/* 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;
}
......@@ -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�
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;
......
......@@ -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
......
......@@ -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() );
......
......@@ -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.
......
......@@ -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
......
This diff is collapsed.
......@@ -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:
......
......@@ -23,7 +23,7 @@ static void CreateShapesSection( FILE* file, BOARD* pcb );
static void CreatePadsShapesSection( FILE* file, BOARD* pcb );
static void ModuleWriteShape( FILE* File, MODULE* module );
// layer name pour extensions fichiers de tracewxString
// layer name pour extensions fichiers de tracewxString
static const wxString GenCAD_Layer_Name[32] = {
wxT( "BOTTOM" ), wxT( "INNER1" ), wxT( "INNER2" ), wxT("INNER3" ),
wxT( "INNER4" ), wxT( "INNER5" ), wxT( "INNER6" ), wxT("INNER7" ),
......@@ -149,7 +149,7 @@ static int Pad_list_Sort_by_Shapes( const void* refptr, const void* objptr )
const D_PAD* padref = *(D_PAD**)refptr;
const D_PAD* padcmp = *(D_PAD**)objptr;
return D_PAD::Compare( padref, padcmp );
return D_PAD::Compare( padref, padcmp );
}
......@@ -158,14 +158,14 @@ 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
*/
{
D_PAD* pad;
D_PAD** padlist;
D_PAD** pad_list_base = NULL;
const char* pad_type;
int memsize, ii, dx, dy;
D_PAD* old_pad = NULL;
......@@ -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,11 +194,11 @@ 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;
dx = pad->m_Size.x / 2;
dy = pad->m_Size.y / 2;
switch( pad->m_PadShape )
......@@ -273,7 +273,7 @@ void CreatePadsShapesSection( FILE* file, BOARD* pcb )
}
fputs( "$ENDPADS\n\n", file );
MyFree( pad_list_base );
}
......@@ -287,13 +287,13 @@ void CreateShapesSection( FILE* file, BOARD* pcb )
* une forme est creee par composant
* La forme est donnee normalisee, c'est a dire orientation 0, position 0 non miroir
* Il y aura donc des formes indentiques redondantes
*
*
* Syntaxe:
* $SHAPES
* SHAPE <shape_name>
* shape_descr (line, arc ..)
* PIN <pin_name> <pad_name> <x_y_ref> <layer> <rot> <mirror>
*
*
* SHAPE <shape_name>
* ..
* $ENDSHAPES
......@@ -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 )
......@@ -459,8 +459,8 @@ void CreateSignalsSection( FILE* file, BOARD* pcb )
continue;
msg = wxT( "\nSIGNAL " ) + equipot->m_Netname;
fputs( CONV_TO_UTF8( msg ), file );
fputs( CONV_TO_UTF8( msg ), file );
fputs( "\n", file );
for( module = pcb->m_Modules; module != NULL; module = (MODULE*) module->Pnext )
......@@ -470,12 +470,12 @@ void CreateSignalsSection( FILE* file, BOARD* pcb )
wxString padname;
if( pad->GetNet() != equipot->GetNet() )
continue;
pad->ReturnStringPadName( padname );
msg.Printf( wxT( "NODE %s %.4s" ),
module->m_Reference->m_Text.GetData(), padname.GetData() );
fputs( CONV_TO_UTF8( msg ), file );
fputs( CONV_TO_UTF8( msg ), file );
fputs( "\n", file );
}
}
......@@ -706,7 +706,7 @@ int* CreateTracksInfoData( FILE* file, BOARD* pcb )
* $TRACK
* TRACK <name> <width>
* $ENDTRACK
*
*
* on attribut ici comme nom l'epaisseur des traits precede de "TRACK": ex
* pour une largeur de 120 : nom = "TRACK120".
*/
......
......@@ -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\
......
This diff is collapsed.
......@@ -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++;
......
......@@ -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;
}
......
......@@ -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;
}
This diff is collapsed.
......@@ -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
*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment