Commit b8ea76fe authored by charras's avatar charras

Solved netlist problems for multiple parts per package components in complex hierarchies.

B.O.M. generation still have a minor problem wih this.
parent 88055164
...@@ -5,6 +5,15 @@ Started 2007-June-11 ...@@ -5,6 +5,15 @@ Started 2007-June-11
Please add newer entries at the top, list the date and your name with Please add newer entries at the top, list the date and your name with
email address. email address.
2008-May-15 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================
+eeschema:
Solved netlist problems for multiple parts per package components
in complex hierarchies.
B.O.M. generation still have a minor problem wih this.
2008-May-5 UPDATE Dick Hollenbeck <dick@softplc.com> 2008-May-5 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================ ================================================================================
+common.c +common.c
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
****************************************************************/ ****************************************************************/
#include "fctsys.h" #include "fctsys.h"
#include "gr_basic.h"
#include "common.h" #include "common.h"
#include "program.h" #include "program.h"
...@@ -15,8 +14,6 @@ ...@@ -15,8 +14,6 @@
#include "dialog_backanno.cpp" #include "dialog_backanno.cpp"
#include "protos.h"
/**************************************************************/ /**************************************************************/
SCH_COMPONENT * WinEDA_SchematicFrame::FindComponentByRef( SCH_COMPONENT * WinEDA_SchematicFrame::FindComponentByRef(
const wxString& reference ) const wxString& reference )
......
...@@ -293,9 +293,7 @@ SCH_COMPONENT::SCH_COMPONENT( const wxPoint& aPos ) : ...@@ -293,9 +293,7 @@ SCH_COMPONENT::SCH_COMPONENT( const wxPoint& aPos ) :
m_Pos = aPos; m_Pos = aPos;
//m_FlagControlMulti = 0; m_Convert = 0; /* De Morgan Handling */
m_UsedOnSheets.Clear();
m_Convert = 0; /* Gestion des mutiples representations (conversion De Morgan) */
/* The rotation/mirror transformation matrix. pos normal*/ /* The rotation/mirror transformation matrix. pos normal*/
m_Transform[0][0] = 1; m_Transform[0][0] = 1;
...@@ -469,6 +467,9 @@ void SCH_COMPONENT::ClearAnnotation( DrawSheetPath* aSheet ) ...@@ -469,6 +467,9 @@ void SCH_COMPONENT::ClearAnnotation( DrawSheetPath* aSheet )
defRef.Append( wxT( "?" ) ); defRef.Append( wxT( "?" ) );
wxString multi = wxT( "1" ); wxString multi = wxT( "1" );
if ( KeepMulti ) // We cannot remove all annotations: part selection must be kept
{
wxString NewHref; wxString NewHref;
wxString path; wxString path;
if( aSheet ) if( aSheet )
...@@ -486,15 +487,20 @@ void SCH_COMPONENT::ClearAnnotation( DrawSheetPath* aSheet ) ...@@ -486,15 +487,20 @@ void SCH_COMPONENT::ClearAnnotation( DrawSheetPath* aSheet )
m_PathsAndReferences[ii] = NewHref; m_PathsAndReferences[ii] = NewHref;
} }
} }
}
else
{
m_PathsAndReferences.Empty(); // Empty strings, but does not free memory because a new annotation will reuse it
m_Multi = 1;
}
// These 2 changes do not work in complex hierarchy. // These 2 changes do not work in complex hierarchy.
// When a clear annotation is made, the calling function must call a // When a clear annotation is made, the calling function must call a
// UpdateAllScreenReferences for the active sheet. // UpdateAllScreenReferences for the active sheet.
// But this call does not made here. // But this call cannot made here.
m_Field[REFERENCE].m_Text = defRef; //for drawing. m_Field[REFERENCE].m_Text = defRef; //for drawing.
if( !KeepMulti )
m_Multi = 1;
} }
...@@ -510,8 +516,6 @@ SCH_COMPONENT* SCH_COMPONENT::GenCopy() ...@@ -510,8 +516,6 @@ SCH_COMPONENT* SCH_COMPONENT::GenCopy()
new_item->m_ChipName = m_ChipName; new_item->m_ChipName = m_ChipName;
new_item->m_PrefixString = m_PrefixString; new_item->m_PrefixString = m_PrefixString;
//new_item->m_FlagControlMulti = m_FlagControlMulti;
new_item->m_UsedOnSheets = m_UsedOnSheets;
new_item->m_Convert = m_Convert; new_item->m_Convert = m_Convert;
new_item->m_Transform[0][0] = m_Transform[0][0]; new_item->m_Transform[0][0] = m_Transform[0][0];
new_item->m_Transform[0][1] = m_Transform[0][1]; new_item->m_Transform[0][1] = m_Transform[0][1];
......
...@@ -100,8 +100,6 @@ public: ...@@ -100,8 +100,6 @@ public:
* determined, upon file load, by the first non-digits in the reference fields. */ * determined, upon file load, by the first non-digits in the reference fields. */
PartTextStruct m_Field[NUMBER_OF_FIELDS]; PartTextStruct m_Field[NUMBER_OF_FIELDS];
//int m_FlagControlMulti;
ArrayOfSheetLists m_UsedOnSheets; // Used as flags when calculating netlist
int m_Convert; /* Gestion (management) des mutiples representations (ex: conversion De Morgan) */ int m_Convert; /* Gestion (management) des mutiples representations (ex: conversion De Morgan) */
int m_Transform[2][2]; /* The rotation/mirror transformation matrix. */ int m_Transform[2][2]; /* The rotation/mirror transformation matrix. */
......
...@@ -402,7 +402,7 @@ DanglingEndHandle* RebuildEndList( EDA_BaseStruct* DrawList ) ...@@ -402,7 +402,7 @@ DanglingEndHandle* RebuildEndList( EDA_BaseStruct* DrawList )
#undef STRUCT #undef STRUCT
#define STRUCT ( (SCH_COMPONENT*) DrawItem ) #define STRUCT ( (SCH_COMPONENT*) DrawItem )
EDA_LibComponentStruct* Entry; EDA_LibComponentStruct* Entry;
Entry = FindLibPart( STRUCT->m_ChipName, wxEmptyString, FIND_ROOT ); Entry = FindLibPart( STRUCT->m_ChipName.GetData(), wxEmptyString, FIND_ROOT );
if( Entry == NULL ) if( Entry == NULL )
break; break;
......
...@@ -691,13 +691,6 @@ void WinEDA_Build_BOM_Frame::GenereListeOfItems( const wxString& FullFileName ) ...@@ -691,13 +691,6 @@ void WinEDA_Build_BOM_Frame::GenereListeOfItems( const wxString& FullFileName )
GenListeCmp( List ); GenListeCmp( List );
#if 0
for( int i = 0; i<NbItems; i++ )
{
printf( "found component: %s\n", List[i].m_Ref );
}
#endif
/* generation du fichier listing */ /* generation du fichier listing */
DateAndTime( Line ); DateAndTime( Line );
wxString Title = g_Main_Title + wxT( " " ) + GetBuildVersion(); wxString Title = g_Main_Title + wxT( " " ) + GetBuildVersion();
...@@ -707,13 +700,7 @@ void WinEDA_Build_BOM_Frame::GenereListeOfItems( const wxString& FullFileName ) ...@@ -707,13 +700,7 @@ void WinEDA_Build_BOM_Frame::GenereListeOfItems( const wxString& FullFileName )
qsort( List, NbItems, sizeof( ListComponent ), qsort( List, NbItems, sizeof( ListComponent ),
( int( * ) ( const void*, const void* ) )ListTriComposantByRef ); ( int( * ) ( const void*, const void* ) )ListTriComposantByRef );
#if 0
printf( "sorted by reference:\n" );
for( int i = 0; i<NbItems; i++ )
{
printf( "found component: %s\n", List[i].m_Ref );
}
#endif
// if( ! s_ListWithSubCmponents ) // if( ! s_ListWithSubCmponents )
if( !m_ListSubCmpItems->GetValue() ) if( !m_ListSubCmpItems->GetValue() )
DeleteSubCmp( List, NbItems ); DeleteSubCmp( List, NbItems );
...@@ -785,20 +772,17 @@ void WinEDA_Build_BOM_Frame::GenereListeOfItems( const wxString& FullFileName ) ...@@ -785,20 +772,17 @@ void WinEDA_Build_BOM_Frame::GenereListeOfItems( const wxString& FullFileName )
int GenListeCmp( ListComponent* List ) int GenListeCmp( ListComponent* List )
/****************************************/ /****************************************/
/* Routine de generation de la liste des elements utiles du dessin /* Creates the list of components in the schematic
* Si List == NULL: comptage des elements
* Sinon remplissage de la liste
* Initialise "FlagControlMulti" a SheetNumber pour la sortie des listes
* et m_Father comme pointeur sur la sheet d'appartenance
* *
* routine for generating a list of the used components. * routine for generating a list of the used components.
* if List == null, just returns the count. if not, fills the list. * if List == null, just returns the count. if not, fills the list.
* goes through the sheets, not the screens, so that we account for * goes through the sheets, not the screens, so that we account for
* multiple instances of a given screen. * multiple instances of a given screen.
* Also Initialise m_Father as pointer pointeur of the SCH_SCREN parent
*/ */
{ {
int ItemCount = 0; int ItemCount = 0;
EDA_BaseStruct* DrawList; EDA_BaseStruct* SchItem;
SCH_COMPONENT* DrawLibItem; SCH_COMPONENT* DrawLibItem;
DrawSheetPath* sheet; DrawSheetPath* sheet;
...@@ -807,14 +791,13 @@ int GenListeCmp( ListComponent* List ) ...@@ -807,14 +791,13 @@ int GenListeCmp( ListComponent* List )
for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() )
{ {
DrawList = sheet->LastDrawList(); for ( SchItem = sheet->LastDrawList(); SchItem;SchItem = SchItem->Next() )
while( DrawList )
{ {
switch( DrawList->Type() ) if( SchItem->Type() != TYPE_SCH_COMPONENT )
{ continue;
case TYPE_SCH_COMPONENT:
ItemCount++; ItemCount++;
DrawLibItem = (SCH_COMPONENT*) DrawList; DrawLibItem = (SCH_COMPONENT*) SchItem;
DrawLibItem->m_Parent = sheet->LastScreen(); DrawLibItem->m_Parent = sheet->LastScreen();
if( List ) if( List )
{ {
...@@ -825,13 +808,6 @@ int GenListeCmp( ListComponent* List ) ...@@ -825,13 +808,6 @@ int GenListeCmp( ListComponent* List )
sizeof( List->m_Ref ) ); sizeof( List->m_Ref ) );
List++; List++;
} }
break;
default:
break;
}
DrawList = DrawList->Pnext;
} }
} }
......
...@@ -25,17 +25,22 @@ static void WriteGENERICListOfNets( FILE* f, ObjetNetListStruct* ObjNet ); ...@@ -25,17 +25,22 @@ static void WriteGENERICListOfNets( FILE* f, ObjetNetListStruct* ObjNet );
static void AddPinToComponentPinList( SCH_COMPONENT* Component, static void AddPinToComponentPinList( SCH_COMPONENT* Component,
DrawSheetPath* sheet, DrawSheetPath* sheet,
LibDrawPin* PinEntry ); LibDrawPin* PinEntry );
static void FindOthersUnits( SCH_COMPONENT* Component, DrawSheetPath* Sheet_in); static void FindAllsInstancesOfComponent( SCH_COMPONENT* Component,
EDA_LibComponentStruct* Entry,
DrawSheetPath* Sheet_in );
static int SortPinsByNum( ObjetNetListStruct** Pin1, ObjetNetListStruct** Pin2 ); static int SortPinsByNum( ObjetNetListStruct** Pin1, ObjetNetListStruct** Pin2 );
static void EraseDuplicatePins( ObjetNetListStruct** TabPin, int NbrPin ); static void EraseDuplicatePins( ObjetNetListStruct** TabPin, int NbrPin );
static void ClearUsedFlags( WinEDA_SchematicFrame* frame ); static void ClearUsedFlags( void );
/* Variable locales */ /* Local variables */
static int s_SortedPinCount; static int s_SortedPinCount;
static ObjetNetListStruct** s_SortedComponentPinList; static ObjetNetListStruct** s_SortedComponentPinList;
// list of references arready found for multi part per packages components
// (used to avoid to used more than one time a component)
static wxArrayString s_ReferencesAlreadyFound;
/******************************************************************************/ /******************************************************************************/
void WriteNetList( WinEDA_SchematicFrame* frame, const wxString& FileNameNL, void WriteNetList( WinEDA_SchematicFrame* frame, const wxString& FileNameNL,
...@@ -91,7 +96,7 @@ void WriteNetList( WinEDA_SchematicFrame* frame, const wxString& FileNameNL, ...@@ -91,7 +96,7 @@ void WriteNetList( WinEDA_SchematicFrame* frame, const wxString& FileNameNL,
/****************************************************************************/ /****************************************************************************/
static SCH_COMPONENT* FindNextComponentAndCreatPinList( static SCH_COMPONENT* FindNextComponentAndCreatPinList(
EDA_BaseStruct* DrawList, DrawSheetPath* sheet) EDA_BaseStruct* DrawList, DrawSheetPath* sheet )
/****************************************************************************/ /****************************************************************************/
/* Find a "suitable" component from the DrawList /* Find a "suitable" component from the DrawList
...@@ -115,15 +120,12 @@ static SCH_COMPONENT* FindNextComponentAndCreatPinList( ...@@ -115,15 +120,12 @@ static SCH_COMPONENT* FindNextComponentAndCreatPinList(
continue; continue;
Component = (SCH_COMPONENT*) DrawList; Component = (SCH_COMPONENT*) DrawList;
/* already tested ? : */ /* Power symbol and other component which have the reference starting by
bool found = false; * "#" are not included in netlist (pseudo or virtual components) */
for(unsigned int i =0; i<Component->m_UsedOnSheets.GetCount(); i++){ wxString str = Component->GetRef( sheet );
if( Component->m_UsedOnSheets.Item(i) == *sheet ){ if( str[0] == '#' ) // ignore it
found = true; continue;
break;
}
}
if( found ) continue;
//if( Component->m_FlagControlMulti == 1 ) //if( Component->m_FlagControlMulti == 1 )
// continue; /* yes */ // continue; /* yes */
// removed because with multiple instances of one schematic // removed because with multiple instances of one schematic
...@@ -133,11 +135,26 @@ static SCH_COMPONENT* FindNextComponentAndCreatPinList( ...@@ -133,11 +135,26 @@ static SCH_COMPONENT* FindNextComponentAndCreatPinList(
if( Entry == NULL ) if( Entry == NULL )
continue; continue;
/* Power symbol and other component which have the reference starting by if( Entry->m_UnitCount > 1 ) // Multi parts per package: test if already visited:
* "#" are not included in netlist (pseudo components) */ {
wxString str = Component->GetRef(sheet); bool found = false;
if( str[0] == '#' ) for( unsigned jj = 0; jj < s_ReferencesAlreadyFound.GetCount(); jj++ )
{
if( str == s_ReferencesAlreadyFound[jj] ) // Already visited
{
found = true;
break;
}
}
if( found )
continue; continue;
else
{
s_ReferencesAlreadyFound.Add( str ); // Mark as visited
}
}
/* Create the pin table for this component */ /* Create the pin table for this component */
int ii = sizeof(ObjetNetListStruct*) * MAXPIN; int ii = sizeof(ObjetNetListStruct*) * MAXPIN;
...@@ -146,12 +163,14 @@ static SCH_COMPONENT* FindNextComponentAndCreatPinList( ...@@ -146,12 +163,14 @@ static SCH_COMPONENT* FindNextComponentAndCreatPinList(
memset( s_SortedComponentPinList, 0, ii ); memset( s_SortedComponentPinList, 0, ii );
DEntry = Entry->m_Drawings; DEntry = Entry->m_Drawings;
if( Entry->m_UnitCount <= 1 ) // One part per package
{
for( ; DEntry != NULL; DEntry = DEntry->Next() ) for( ; DEntry != NULL; DEntry = DEntry->Next() )
{ {
if( DEntry->Type() != COMPONENT_PIN_DRAW_TYPE ) if( DEntry->Type() != COMPONENT_PIN_DRAW_TYPE )
continue; continue;
if( DEntry->m_Unit if( DEntry->m_Unit
&& (DEntry->m_Unit != Component->m_Multi) ) && ( DEntry->m_Unit != Component->GetUnitSelection( sheet ) ) )
continue; continue;
if( DEntry->m_Convert if( DEntry->m_Convert
&& (DEntry->m_Convert != Component->m_Convert) ) && (DEntry->m_Convert != Component->m_Convert) )
...@@ -160,18 +179,15 @@ static SCH_COMPONENT* FindNextComponentAndCreatPinList( ...@@ -160,18 +179,15 @@ static SCH_COMPONENT* FindNextComponentAndCreatPinList(
AddPinToComponentPinList( Component, sheet, (LibDrawPin*) DEntry ); AddPinToComponentPinList( Component, sheet, (LibDrawPin*) DEntry );
} }
} }
}
else // Multiple parts per package: Collect all parts ans pins for this reference
FindAllsInstancesOfComponent( Component, Entry, sheet );
//Component->m_FlagControlMulti = 1; /* Sort Pins in s_SortedComponentPinList by pin number */
Component->m_UsedOnSheets.Add(*sheet);
if( Entry->m_UnitCount > 1 )
FindOthersUnits( Component, sheet);
/* Tri sur le numero de Pin de TabListePin */
qsort( s_SortedComponentPinList, s_SortedPinCount, sizeof(ObjetNetListStruct*), qsort( s_SortedComponentPinList, s_SortedPinCount, sizeof(ObjetNetListStruct*),
( int( * ) ( const void*, const void* ) )SortPinsByNum ); ( int( * ) ( const void*, const void* ) )SortPinsByNum );
/* Elimination des Pins redondantes du s_SortedComponentPinList */ /* Remove duplicate Pins in s_SortedComponentPinList */
EraseDuplicatePins( s_SortedComponentPinList, s_SortedPinCount ); EraseDuplicatePins( s_SortedComponentPinList, s_SortedPinCount );
return Component; return Component;
...@@ -218,10 +234,12 @@ static wxString ReturnPinNetName( ObjetNetListStruct* Pin, ...@@ -218,10 +234,12 @@ static wxString ReturnPinNetName( ObjetNetListStruct* Pin,
if( !NetName.IsEmpty() ) if( !NetName.IsEmpty() )
{ {
if( g_TabObjNet[jj].m_Type != NET_PINLABEL ){ if( g_TabObjNet[jj].m_Type != NET_PINLABEL )
{
NetName = g_TabObjNet[jj].m_SheetList.PathHumanReadable() NetName = g_TabObjNet[jj].m_SheetList.PathHumanReadable()
+ NetName; + NetName;
} }
//NetName << wxT("_") << g_TabObjNet[jj].m_SheetList.PathHumanReadable(); //NetName << wxT("_") << g_TabObjNet[jj].m_SheetList.PathHumanReadable();
} }
else else
...@@ -232,6 +250,7 @@ static wxString ReturnPinNetName( ObjetNetListStruct* Pin, ...@@ -232,6 +250,7 @@ static wxString ReturnPinNetName( ObjetNetListStruct* Pin,
return NetName; return NetName;
} }
/***********************************************************************/ /***********************************************************************/
void Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, void Write_GENERIC_NetList( WinEDA_SchematicFrame* frame,
const wxString& FullFileName ) const wxString& FullFileName )
...@@ -239,12 +258,11 @@ void Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, ...@@ -239,12 +258,11 @@ void Write_GENERIC_NetList( WinEDA_SchematicFrame* frame,
/* Create a generic netlist, and call an external netlister /* Create a generic netlist, and call an external netlister
* to change the netlist syntax and create the file * to change the netlist syntax and create the file
* -- does this still work?
*/ */
{ {
wxString Line, FootprintName; wxString Line, FootprintName;
DrawSheetPath* sheet; DrawSheetPath* sheet;
EDA_BaseStruct* DrawList; EDA_BaseStruct* SchItem;
SCH_COMPONENT* Component; SCH_COMPONENT* Component;
wxString netname; wxString netname;
int ii; int ii;
...@@ -260,7 +278,7 @@ void Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, ...@@ -260,7 +278,7 @@ void Write_GENERIC_NetList( WinEDA_SchematicFrame* frame,
return; return;
} }
ClearUsedFlags( frame ); /* Reset the flags FlagControlMulti in all schematic files*/ ClearUsedFlags( ); /* Reset the flags FlagControlMulti in all schematic files*/
fprintf( tmpfile, "$BeginNetlist\n" ); fprintf( tmpfile, "$BeginNetlist\n" );
/* Create netlist module section */ /* Create netlist module section */
...@@ -269,9 +287,9 @@ void Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, ...@@ -269,9 +287,9 @@ void Write_GENERIC_NetList( WinEDA_SchematicFrame* frame,
for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() )
{ {
for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Pnext ) for( SchItem = sheet->LastDrawList(); SchItem != NULL; SchItem = SchItem->Pnext )
{ {
DrawList = Component = FindNextComponentAndCreatPinList( DrawList, sheet ); SchItem = Component = FindNextComponentAndCreatPinList( SchItem, sheet );
if( Component == NULL ) if( Component == NULL )
break; // No component left break; // No component left
...@@ -286,7 +304,7 @@ void Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, ...@@ -286,7 +304,7 @@ void Write_GENERIC_NetList( WinEDA_SchematicFrame* frame,
fprintf( tmpfile, "\n$BeginComponent\n" ); fprintf( tmpfile, "\n$BeginComponent\n" );
fprintf( tmpfile, "TimeStamp=%8.8lX\n", Component->m_TimeStamp ); fprintf( tmpfile, "TimeStamp=%8.8lX\n", Component->m_TimeStamp );
fprintf( tmpfile, "Footprint=%s\n", CONV_TO_UTF8( FootprintName ) ); fprintf( tmpfile, "Footprint=%s\n", CONV_TO_UTF8( FootprintName ) );
Line = wxT( "Reference=" ) + Component->GetRef(sheet) + wxT( "\n" ); Line = wxT( "Reference=" ) + Component->GetRef( sheet ) + wxT( "\n" );
Line.Replace( wxT( " " ), wxT( "_" ) ); Line.Replace( wxT( " " ), wxT( "_" ) );
fprintf( tmpfile, CONV_TO_UTF8( Line ) ); fprintf( tmpfile, CONV_TO_UTF8( Line ) );
...@@ -346,30 +364,12 @@ void Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, ...@@ -346,30 +364,12 @@ void Write_GENERIC_NetList( WinEDA_SchematicFrame* frame,
} }
/********************************************************/ /**********************************/
static void ClearUsedFlags( WinEDA_SchematicFrame* frame ) static void ClearUsedFlags( void )
/********************************************************/ /*********************************/
/* Clear flag list, used in netlist generation */ /* Clear flag list, used in netlist generation */
{ {
SCH_SCREEN* screen; s_ReferencesAlreadyFound.Clear();
EDA_BaseStruct* DrawList;
EDA_ScreenList ScreenList;
for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
{
DrawList = screen->EEDrawList;
while( DrawList )
{
if( DrawList->Type() == TYPE_SCH_COMPONENT )
{
SCH_COMPONENT* Component = (SCH_COMPONENT*) DrawList;
//Component->m_FlagControlMulti = 0;
Component->m_UsedOnSheets.Clear();
}
DrawList = DrawList->Pnext;
}
}
} }
...@@ -384,7 +384,7 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, ...@@ -384,7 +384,7 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f,
* sinon les nodes sont identifies par le netnumber * sinon les nodes sont identifies par le netnumber
* *
* tous les textes graphiques commen�ant par [.-+]pspice ou [.-+]gnucap * tous les textes graphiques commen�ant par [.-+]pspice ou [.-+]gnucap
* sont consid�r�s comme des commandes a placer dans la netliste * sont consideres comme des commandes a placer dans la netliste
* [.-]pspice ou gnucap sont en debut * [.-]pspice ou gnucap sont en debut
+pspice et +gnucap sont en fin de netliste +pspice et +gnucap sont en fin de netliste
*/ */
...@@ -461,7 +461,7 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, ...@@ -461,7 +461,7 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f,
/* Create component list */ /* Create component list */
ClearUsedFlags( frame ); /* Reset the flags FlagControlMulti in all schematic files*/ ClearUsedFlags(); /* Reset the flags FlagControlMulti in all schematic files*/
for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() )
{ {
for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Pnext ) for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Pnext )
...@@ -524,7 +524,7 @@ static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with ...@@ -524,7 +524,7 @@ static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with
/*****************************************************************************************/ /*****************************************************************************************/
/* Routine de generation du fichier netliste ( Format ORCAD PCB 2 ameliore ) /* Routine de generation du fichier netliste ( Format ORCAD PCB 2 ameliore )
* si with_pcbnew = FALSE * si with_pcbnew = TRUE
* format PCBNEW (OrcadPcb2 + commentaires et liste des nets) * format PCBNEW (OrcadPcb2 + commentaires et liste des nets)
* si with_pcbnew = FALSE * si with_pcbnew = FALSE
* Format ORCADPCB2 strict * Format ORCADPCB2 strict
...@@ -547,7 +547,7 @@ static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with ...@@ -547,7 +547,7 @@ static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with
/* Create netlist module section */ /* Create netlist module section */
ClearUsedFlags( frame ); /* Reset the flags FlagControlMulti in all schematic files*/ ClearUsedFlags( ); /* Reset the flags FlagControlMulti in all schematic files*/
EDA_SheetList SheetList( NULL ); EDA_SheetList SheetList( NULL );
...@@ -555,7 +555,7 @@ static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with ...@@ -555,7 +555,7 @@ static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with
{ {
for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Pnext ) for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Pnext )
{ {
DrawList = Component = FindNextComponentAndCreatPinList( DrawList, sheet); DrawList = Component = FindNextComponentAndCreatPinList( DrawList, sheet );
if( Component == NULL ) if( Component == NULL )
break; break;
...@@ -566,7 +566,8 @@ static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with ...@@ -566,7 +566,8 @@ static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with
{ {
if( Entry->m_FootprintList.GetCount() != 0 ) /* Put in list */ if( Entry->m_FootprintList.GetCount() != 0 ) /* Put in list */
{ {
if( CmpList == NULL ){ if( CmpList == NULL )
{
CmpList = (ListComponent*) CmpList = (ListComponent*)
MyZMalloc( sizeof(ListComponent) * CmpListSize ); MyZMalloc( sizeof(ListComponent) * CmpListSize );
} }
...@@ -578,7 +579,7 @@ static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with ...@@ -578,7 +579,7 @@ static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with
sizeof(ListComponent) * CmpListSize ); sizeof(ListComponent) * CmpListSize );
} }
CmpList[CmpListCount].m_Comp = Component; CmpList[CmpListCount].m_Comp = Component;
strcpy(CmpList[CmpListCount].m_Ref, Component->GetRef( sheet ).mb_str()); strcpy( CmpList[CmpListCount].m_Ref, Component->GetRef( sheet ).mb_str() );
CmpListCount++; CmpListCount++;
} }
} }
...@@ -591,9 +592,9 @@ static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with ...@@ -591,9 +592,9 @@ static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with
else else
FootprintName = wxT( "$noname" ); FootprintName = wxT( "$noname" );
Line = Component->GetRef(sheet); Line = Component->GetRef( sheet );
fprintf( f, " ( %s %s", fprintf( f, " ( %s %s",
CONV_TO_UTF8(Component->GetPath(sheet)), CONV_TO_UTF8( Component->GetPath( sheet ) ),
CONV_TO_UTF8( FootprintName ) ); CONV_TO_UTF8( FootprintName ) );
fprintf( f, " %s", CONV_TO_UTF8( Line ) ); fprintf( f, " %s", CONV_TO_UTF8( Line ) );
...@@ -640,13 +641,16 @@ static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with ...@@ -640,13 +641,16 @@ static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with
{ {
Component = CmpList[ii].m_Comp; Component = CmpList[ii].m_Comp;
Entry = FindLibPart( Component->m_ChipName.GetData(), wxEmptyString, FIND_ROOT ); Entry = FindLibPart( Component->m_ChipName.GetData(), wxEmptyString, FIND_ROOT );
//Line.Printf(_("%s"), CmpList[ii].m_Ref); //Line.Printf(_("%s"), CmpList[ii].m_Ref);
//Line.Replace( wxT( " " ), wxT( "_" ) ); //Line.Replace( wxT( " " ), wxT( "_" ) );
unsigned int i; unsigned int i;
for(i=0; i<sizeof(CmpList[ii].m_Ref) && CmpList[ii].m_Ref[i]; i++){ for( i = 0; i<sizeof(CmpList[ii].m_Ref) && CmpList[ii].m_Ref[i]; i++ )
if(CmpList[ii].m_Ref[i] == ' ') {
if( CmpList[ii].m_Ref[i] == ' ' )
CmpList[ii].m_Ref[i] = '_'; CmpList[ii].m_Ref[i] = '_';
} }
fprintf( f, "$component %s\n", CmpList[ii].m_Ref ); fprintf( f, "$component %s\n", CmpList[ii].m_Ref );
/* Write the footprint list */ /* Write the footprint list */
for( unsigned int jj = 0; jj < Entry->m_FootprintList.GetCount(); jj++ ) for( unsigned int jj = 0; jj < Entry->m_FootprintList.GetCount(); jj++ )
...@@ -714,10 +718,12 @@ static void EraseDuplicatePins( ObjetNetListStruct** TabPin, int NbrPin ) ...@@ -714,10 +718,12 @@ static void EraseDuplicatePins( ObjetNetListStruct** TabPin, int NbrPin )
/**********************************************************************/ /**********************************************************************/
/* /*
* Routine qui elimine les Pins de meme Numero de la liste des objets * Function to remove duplicate Pins in the TabPin pin list
* (Liste des Pins d'un boitier) passee en entree * (This is a list of pins found in the whole schematic, for a given component)
* Ces pins redondantes proviennent des pins (alims... ) communes a plusieurs * These duplicate pins were put in list because some pins (powers... )
* elements d'un boitier a multiple parts. * are found more than one time when we have a multiple parts per package component
* for instance, a 74ls00 has 4 parts, and therefor the VCC pin and GND pin apperas 4 times
* in the list.
*/ */
{ {
int ii, jj; int ii, jj;
...@@ -739,56 +745,40 @@ static void EraseDuplicatePins( ObjetNetListStruct** TabPin, int NbrPin ) ...@@ -739,56 +745,40 @@ static void EraseDuplicatePins( ObjetNetListStruct** TabPin, int NbrPin )
} }
/**********************************************************************/ /**********************************************************************************/
static void FindOthersUnits( SCH_COMPONENT* Component_in, DrawSheetPath* Sheet_in) static void FindAllsInstancesOfComponent( SCH_COMPONENT* Component_in,
/**********************************************************************/ EDA_LibComponentStruct* Entry,
DrawSheetPath* Sheet_in )
/**********************************************************************************/
/* Recherche les autres parts du boitier auquel appartient la part Component, /**
* pour les boitiers a parts multiples. * Used for multiple parts per package components
* Appelle AddPinToComponentPinList() pour classer les pins des parts trouvees * Search all instances of Component_in,
* Calls AddPinToComponentPinList() to and pins founds to the current component pin list
*/ */
{ {
EDA_BaseStruct* DrawList; EDA_BaseStruct* SchItem;
SCH_COMPONENT* Component2; SCH_COMPONENT* Component2;
EDA_LibComponentStruct* Entry;
LibEDA_BaseStruct* DEntry; LibEDA_BaseStruct* DEntry;
DrawSheetPath* sheet; DrawSheetPath* sheet;
wxString str; wxString str, Reference = Component_in->GetRef( Sheet_in );
EDA_SheetList SheetList( NULL ); EDA_SheetList SheetList( NULL );
unsigned int i;
bool found;
for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() )
{ {
DrawList = sheet->LastDrawList(); for( SchItem = sheet->LastDrawList(); SchItem; SchItem = SchItem->Pnext )
while( DrawList )
{ {
switch( DrawList->Type() ) if( SchItem->Type() != TYPE_SCH_COMPONENT )
{ continue;
case TYPE_SCH_COMPONENT:
Component2 = (SCH_COMPONENT*) DrawList;
found = false;
for( i =0; i<Component2->m_UsedOnSheets.GetCount(); i++){
if( Component2->m_UsedOnSheets.Item(i) == *Sheet_in ){
found = true;
}
}
if( found ) break;
//if( Component2->m_FlagControlMulti == 1 ) //has it been used? (on this sheet?)
// break;
str = Component2->GetRef(sheet);
if( str.CmpNoCase( Component_in->GetRef(Sheet_in) ) != 0 )
break;
Entry = FindLibPart( Component2->m_ChipName.GetData(), wxEmptyString, FIND_ROOT ); Component2 = (SCH_COMPONENT*) SchItem;
if( Entry == NULL )
break;
if( str[0] == '#' ) str = Component2->GetRef( sheet );
break; if( str.CmpNoCase( Reference ) != 0 )
continue;
if( Entry->m_Drawings != NULL ) if( Entry && Entry->m_Drawings != NULL )
{ {
DEntry = Entry->m_Drawings; DEntry = Entry->m_Drawings;
for( ; DEntry != NULL; DEntry = DEntry->Next() ) for( ; DEntry != NULL; DEntry = DEntry->Next() )
...@@ -796,26 +786,16 @@ static void FindOthersUnits( SCH_COMPONENT* Component_in, DrawSheetPath* Sheet_i ...@@ -796,26 +786,16 @@ static void FindOthersUnits( SCH_COMPONENT* Component_in, DrawSheetPath* Sheet_i
if( DEntry->Type() != COMPONENT_PIN_DRAW_TYPE ) if( DEntry->Type() != COMPONENT_PIN_DRAW_TYPE )
continue; continue;
if( DEntry->m_Unit if( DEntry->m_Unit
&& (DEntry->m_Unit != Component2->m_Multi) ) && ( DEntry->m_Unit != Component2->GetUnitSelection( sheet ) ) )
continue; continue;
if( DEntry->m_Convert if( DEntry->m_Convert
&& (DEntry->m_Convert != Component2->m_Convert) ) && (DEntry->m_Convert != Component2->m_Convert) )
continue; continue;
{ // A suitable pin in found: add it to the current list
AddPinToComponentPinList( Component2, sheet, (LibDrawPin*) DEntry ); AddPinToComponentPinList( Component2, sheet, (LibDrawPin*) DEntry );
} }
} }
} }
Component2->m_UsedOnSheets.Add(*Sheet_in);
//Component2->m_FlagControlMulti = 1; //mark it as used..
break;
default:
break;
}
DrawList = DrawList->Pnext;
}
} }
} }
...@@ -858,7 +838,7 @@ static void WriteGENERICListOfNets( FILE* f, ObjetNetListStruct* ObjNet ) ...@@ -858,7 +838,7 @@ static void WriteGENERICListOfNets( FILE* f, ObjetNetListStruct* ObjNet )
for( ii = 0; ii < g_NbrObjNet; ii++ ) for( ii = 0; ii < g_NbrObjNet; ii++ )
{ {
if( (NetCode = ObjNet[ii].GetNet()) != LastNetCode ) // New net found, write net id; if( ( NetCode = ObjNet[ii].GetNet() ) != LastNetCode ) // New net found, write net id;
{ {
SameNetcodeCount = 0; // Items count for this net SameNetcodeCount = 0; // Items count for this net
NetName.Empty(); NetName.Empty();
...@@ -879,10 +859,12 @@ static void WriteGENERICListOfNets( FILE* f, ObjetNetListStruct* ObjNet ) ...@@ -879,10 +859,12 @@ static void WriteGENERICListOfNets( FILE* f, ObjetNetListStruct* ObjNet )
if( !NetName.IsEmpty() ) if( !NetName.IsEmpty() )
{ {
NetcodeName += NetName; NetcodeName += NetName;
if( g_TabObjNet[jj].m_Type != NET_PINLABEL ){ if( g_TabObjNet[jj].m_Type != NET_PINLABEL )
{
// usual net name, add in the sheet path // usual net name, add in the sheet path
NetcodeName = g_TabObjNet[jj].m_SheetList.PathHumanReadable() NetcodeName = g_TabObjNet[jj].m_SheetList.PathHumanReadable()
+ NetcodeName; + NetcodeName;
//NetcodeName << wxT("_") << //NetcodeName << wxT("_") <<
// g_TabObjNet[jj].m_SheetList.PathHumanReadable(); // g_TabObjNet[jj].m_SheetList.PathHumanReadable();
} }
...@@ -895,7 +877,7 @@ static void WriteGENERICListOfNets( FILE* f, ObjetNetListStruct* ObjNet ) ...@@ -895,7 +877,7 @@ static void WriteGENERICListOfNets( FILE* f, ObjetNetListStruct* ObjNet )
continue; continue;
Cmp = (SCH_COMPONENT*) ObjNet[ii].m_Link; Cmp = (SCH_COMPONENT*) ObjNet[ii].m_Link;
CmpRef = Cmp->GetRef(&ObjNet[ii].m_SheetList); //is this correct? CmpRef = Cmp->GetRef( &ObjNet[ii].m_SheetList ); //is this correct?
if( CmpRef.StartsWith( wxT( "#" ) ) ) if( CmpRef.StartsWith( wxT( "#" ) ) )
continue; // Pseudo component (Like Power symbol) continue; // Pseudo component (Like Power symbol)
...@@ -971,14 +953,14 @@ static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f ) ...@@ -971,14 +953,14 @@ static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f )
fprintf( f, "\n" ); fprintf( f, "\n" );
/* Create netlist module section */ /* Create netlist module section */
ClearUsedFlags( frame ); /* Reset the flags FlagControlMulti in all schematic files*/ ClearUsedFlags( ); /* Reset the flags FlagControlMulti in all schematic files*/
EDA_SheetList SheetList( NULL ); EDA_SheetList SheetList( NULL );
for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() )
{ {
for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Pnext ) for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Pnext )
{ {
DrawList = Component = FindNextComponentAndCreatPinList( DrawList, sheet); DrawList = Component = FindNextComponentAndCreatPinList( DrawList, sheet );
if( Component == NULL ) if( Component == NULL )
break; break;
...@@ -990,7 +972,7 @@ static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f ) ...@@ -990,7 +972,7 @@ static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f )
else else
FootprintName = wxT( "$noname" ); FootprintName = wxT( "$noname" );
msg = Component->GetRef(sheet); msg = Component->GetRef( sheet );
fprintf( f, "%s ", CONV_TO_UTF8( StartCmpDesc ) ); fprintf( f, "%s ", CONV_TO_UTF8( StartCmpDesc ) );
fprintf( f, "%s", CONV_TO_UTF8( msg ) ); fprintf( f, "%s", CONV_TO_UTF8( msg ) );
...@@ -1038,7 +1020,7 @@ static void WriteListOfNetsCADSTAR( FILE* f, ObjetNetListStruct* ObjNet ) ...@@ -1038,7 +1020,7 @@ static void WriteListOfNetsCADSTAR( FILE* f, ObjetNetListStruct* ObjNet )
for( ii = 0; ii < g_NbrObjNet; ii++ ) for( ii = 0; ii < g_NbrObjNet; ii++ )
{ {
// Get the NetName of the current net : // Get the NetName of the current net :
if( (NetCode = ObjNet[ii].GetNet()) != LastNetCode ) if( ( NetCode = ObjNet[ii].GetNet() ) != LastNetCode )
{ {
NetName.Empty(); NetName.Empty();
for( jj = 0; jj < g_NbrObjNet; jj++ ) for( jj = 0; jj < g_NbrObjNet; jj++ )
...@@ -1057,9 +1039,11 @@ static void WriteListOfNetsCADSTAR( FILE* f, ObjetNetListStruct* ObjNet ) ...@@ -1057,9 +1039,11 @@ static void WriteListOfNetsCADSTAR( FILE* f, ObjetNetListStruct* ObjNet )
if( !NetName.IsEmpty() ) if( !NetName.IsEmpty() )
{ {
NetcodeName += NetName; NetcodeName += NetName;
if( g_TabObjNet[jj].m_Type != NET_PINLABEL ){ if( g_TabObjNet[jj].m_Type != NET_PINLABEL )
{
NetcodeName = g_TabObjNet[jj].m_SheetList.PathHumanReadable() NetcodeName = g_TabObjNet[jj].m_SheetList.PathHumanReadable()
+ NetcodeName; + NetcodeName;
//NetcodeName << wxT("_") << //NetcodeName << wxT("_") <<
// g_TabObjNet[jj].m_SheetList.PathHumanReadable(); // g_TabObjNet[jj].m_SheetList.PathHumanReadable();
} }
...@@ -1079,7 +1063,7 @@ static void WriteListOfNetsCADSTAR( FILE* f, ObjetNetListStruct* ObjNet ) ...@@ -1079,7 +1063,7 @@ static void WriteListOfNetsCADSTAR( FILE* f, ObjetNetListStruct* ObjNet )
continue; continue;
Cmp = (SCH_COMPONENT*) ObjNet[ii].m_Link; Cmp = (SCH_COMPONENT*) ObjNet[ii].m_Link;
wxString refstr = Cmp->GetRef(&(ObjNet[ii].m_SheetList)); wxString refstr = Cmp->GetRef( &(ObjNet[ii].m_SheetList) );
if( refstr[0] == '#' ) if( refstr[0] == '#' )
continue; // Pseudo composant (symboles d'alims) continue; // Pseudo composant (symboles d'alims)
...@@ -1129,7 +1113,7 @@ static void WriteListOfNetsCADSTAR( FILE* f, ObjetNetListStruct* ObjNet ) ...@@ -1129,7 +1113,7 @@ static void WriteListOfNetsCADSTAR( FILE* f, ObjetNetListStruct* ObjNet )
(SCH_COMPONENT*) ObjNet[jj].m_Link; (SCH_COMPONENT*) ObjNet[jj].m_Link;
wxString p = Cmp->GetPath( &( ObjNet[ii].m_SheetList ) ); wxString p = Cmp->GetPath( &( ObjNet[ii].m_SheetList ) );
wxString tstp = tstcmp->GetPath( &( ObjNet[jj].m_SheetList ) ); wxString tstp = tstcmp->GetPath( &( ObjNet[jj].m_SheetList ) );
if( p.Cmp(tstp) != 0 ) if( p.Cmp( tstp ) != 0 )
continue; continue;
if( ObjNet[jj].m_PinNum == ObjNet[ii].m_PinNum ) if( ObjNet[jj].m_PinNum == ObjNet[ii].m_PinNum )
......
...@@ -17,8 +17,7 @@ ...@@ -17,8 +17,7 @@
/* Routines locales */ /* Routines locales */
static void PropageNetCode( int OldNetCode, int NewNetCode, int IsBus ); static void PropageNetCode( int OldNetCode, int NewNetCode, int IsBus );
static void SheetLabelConnect( ObjetNetListStruct* SheetLabel ); static void SheetLabelConnect( ObjetNetListStruct* SheetLabel );
static int ListeObjetConnection( WinEDA_SchematicFrame* frame, static int ListeObjetConnection( DrawSheetPath* sheetlist,
DrawSheetPath* sheetlist,
ObjetNetListStruct* ObjNet ); ObjetNetListStruct* ObjNet );
static int ConvertBusToMembers( ObjetNetListStruct* ObjNet ); static int ConvertBusToMembers( ObjetNetListStruct* ObjNet );
static void PointToPointConnect( ObjetNetListStruct* Ref, int IsBus, static void PointToPointConnect( ObjetNetListStruct* Ref, int IsBus,
...@@ -165,7 +164,7 @@ void* WinEDA_SchematicFrame::BuildNetListBase() ...@@ -165,7 +164,7 @@ void* WinEDA_SchematicFrame::BuildNetListBase()
/* Build the sheet (not screen) list (flattened)*/ /* Build the sheet (not screen) list (flattened)*/
EDA_SheetList SheetListList( NULL ); EDA_SheetList SheetListList( NULL );
i=0; i=0;
/* 1ere passe : Comptage du nombre d'objet de Net */ /* first pass : count objects used in connectivty calculation */
g_NbrObjNet = 0; g_NbrObjNet = 0;
g_TabObjNet = NULL; /* Init pour le 1er passage dans ListeObjetConnection */ g_TabObjNet = NULL; /* Init pour le 1er passage dans ListeObjetConnection */
...@@ -174,7 +173,7 @@ void* WinEDA_SchematicFrame::BuildNetListBase() ...@@ -174,7 +173,7 @@ void* WinEDA_SchematicFrame::BuildNetListBase()
for( sheet = SheetListList.GetFirst(); sheet != NULL; sheet = SheetListList.GetNext() ) for( sheet = SheetListList.GetFirst(); sheet != NULL; sheet = SheetListList.GetNext() )
{ {
g_NbrObjNet += ListeObjetConnection( this, sheet, NULL ); g_NbrObjNet += ListeObjetConnection( sheet, NULL );
} }
if( g_NbrObjNet == 0 ) if( g_NbrObjNet == 0 )
...@@ -188,8 +187,7 @@ void* WinEDA_SchematicFrame::BuildNetListBase() ...@@ -188,8 +187,7 @@ void* WinEDA_SchematicFrame::BuildNetListBase()
if( g_TabObjNet == NULL ) if( g_TabObjNet == NULL )
return NULL; return NULL;
/* 2eme passe : Remplissage des champs des structures des objets de Net */ /* second pass: fill the fields of the structures used in connectivty calculation */
/* second pass: fill the fields of the structures in the Net */
s_PassNumber++; s_PassNumber++;
...@@ -197,15 +195,14 @@ void* WinEDA_SchematicFrame::BuildNetListBase() ...@@ -197,15 +195,14 @@ void* WinEDA_SchematicFrame::BuildNetListBase()
for( ObjetNetListStruct* tabObjNet = g_TabObjNet; for( ObjetNetListStruct* tabObjNet = g_TabObjNet;
sheet != NULL; sheet = SheetListList.GetNext() ) sheet != NULL; sheet = SheetListList.GetNext() )
{ {
tabObjNet += ListeObjetConnection( this, sheet, tabObjNet ); tabObjNet += ListeObjetConnection( sheet, tabObjNet );
} }
activity.Empty(); activity.Empty();
activity << wxT(" ") << _( "NbItems" ) << wxT(" ") << g_NbrObjNet; activity << wxT(" ") << _( "NbItems" ) << wxT(" ") << g_NbrObjNet;
SetStatusText( activity ); SetStatusText( activity );
/* Recherche des connections pour les Segments et les Pins */ /* Sort objects by Sheet */
/* Tri du Tableau des objets de Net par Sheet */
qsort( g_TabObjNet, g_NbrObjNet, sizeof(ObjetNetListStruct), TriBySheet ); qsort( g_TabObjNet, g_NbrObjNet, sizeof(ObjetNetListStruct), TriBySheet );
...@@ -363,7 +360,7 @@ void* WinEDA_SchematicFrame::BuildNetListBase() ...@@ -363,7 +360,7 @@ void* WinEDA_SchematicFrame::BuildNetListBase()
SheetLabelConnect( g_TabObjNet + i ); SheetLabelConnect( g_TabObjNet + i );
} }
/* Tri du Tableau des objets de Net par NetCode */ /* Sort objects by NetCode */
qsort( g_TabObjNet, g_NbrObjNet, sizeof(ObjetNetListStruct), TriNetCode ); qsort( g_TabObjNet, g_NbrObjNet, sizeof(ObjetNetListStruct), TriNetCode );
...@@ -438,17 +435,14 @@ static void SheetLabelConnect( ObjetNetListStruct* SheetLabel ) ...@@ -438,17 +435,14 @@ static void SheetLabelConnect( ObjetNetListStruct* SheetLabel )
} }
/*****************************************************************************/ /**************************************************************************************/
static int ListeObjetConnection( WinEDA_SchematicFrame* frame, DrawSheetPath* sheetlist, static int ListeObjetConnection( DrawSheetPath* sheetlist, ObjetNetListStruct* ObjNet )
ObjetNetListStruct* ObjNet ) /**************************************************************************************/
/*****************************************************************************/
/* Routine generant la liste des objets relatifs aux connection /** Function ListeObjetConnection
* entree: * Creates the list of objects related to connections (pins of components, wires, labels, junctions ...)
* sheetlist: pointer to a sheetlist. * @param sheetlist: pointer to a sheetlist.
* ObjNet: * @param ObjNet: if NULL, objects count else list to fill
* si NULL: la routine compte seulement le nombre des objets
* sinon: pointe le tableau a remplir
*/ */
{ {
int ii, NbrItem = 0; int ii, NbrItem = 0;
...@@ -596,8 +590,7 @@ static int ListeObjetConnection( WinEDA_SchematicFrame* frame, DrawSheetPath* sh ...@@ -596,8 +590,7 @@ static int ListeObjetConnection( WinEDA_SchematicFrame* frame, DrawSheetPath* sh
if( DEntry->Type() != COMPONENT_PIN_DRAW_TYPE ) if( DEntry->Type() != COMPONENT_PIN_DRAW_TYPE )
continue; continue;
if( DEntry->m_Unit if( DEntry->m_Unit && (DEntry->m_Unit != DrawLibItem->GetUnitSelection( sheetlist ) ) )
&& (DEntry->m_Unit != DrawLibItem->m_Multi) )
continue; continue;
if( DEntry->m_Convert if( DEntry->m_Convert
...@@ -684,7 +677,7 @@ static int ListeObjetConnection( WinEDA_SchematicFrame* frame, DrawSheetPath* sh ...@@ -684,7 +677,7 @@ static int ListeObjetConnection( WinEDA_SchematicFrame* frame, DrawSheetPath* sh
break; break;
case DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE: case DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE:
DisplayError( frame, wxT( "Netlist: Type DRAW_SHEETLABEL inattendu" ) ); DisplayError( NULL, wxT( "Netlist: Type DRAW_SHEETLABEL inattendu" ) );
break; break;
default: default:
...@@ -692,7 +685,7 @@ static int ListeObjetConnection( WinEDA_SchematicFrame* frame, DrawSheetPath* sh ...@@ -692,7 +685,7 @@ static int ListeObjetConnection( WinEDA_SchematicFrame* frame, DrawSheetPath* sh
wxString msg; wxString msg;
msg.Printf( wxT( "Netlist: unexpected type struct %d" ), msg.Printf( wxT( "Netlist: unexpected type struct %d" ),
DrawList->Type() ); DrawList->Type() );
DisplayError( frame, msg ); DisplayError( NULL, msg );
break; break;
} }
} }
......
...@@ -26,7 +26,7 @@ typedef enum { ...@@ -26,7 +26,7 @@ typedef enum {
* NET_TYPE_CUSTOM1+CUSTOMPANEL_COUNTMAX-1 * NET_TYPE_CUSTOM1+CUSTOMPANEL_COUNTMAX-1
* is the last id for user netlist format * is the last id for user netlist format
*/ */
NET_TYPE_CUSTOM_MAX = NET_TYPE_CUSTOM1+CUSTOMPANEL_COUNTMAX-1 NET_TYPE_CUSTOM_MAX = NET_TYPE_CUSTOM1 + CUSTOMPANEL_COUNTMAX - 1
} TypeNetForm; } TypeNetForm;
...@@ -68,7 +68,7 @@ public: ...@@ -68,7 +68,7 @@ public:
int m_Flag; /* flag pour calculs internes */ int m_Flag; /* flag pour calculs internes */
DrawSheetPath m_SheetList; DrawSheetPath m_SheetList;
NetObjetType m_Type; NetObjetType m_Type;
int m_ElectricalType;/* Pour Pins et sheet labels: type electrique */ int m_ElectricalType; /* Pour Pins et sheet labels: type electrique */
private: private:
int m_NetCode; /* pour elements simples */ int m_NetCode; /* pour elements simples */
public: public:
...@@ -94,14 +94,16 @@ public: ...@@ -94,14 +94,16 @@ public:
typedef struct ListLabel typedef struct ListLabel
{ {
int m_LabelType; int m_LabelType;
void * m_Label; void* m_Label;
char m_SheetPath[64]; char m_SheetPath[64];
} ListLabel; } ListLabel;
typedef struct ListComponent typedef struct ListComponent
{ {
SCH_COMPONENT * m_Comp; SCH_COMPONENT* m_Comp;
char m_Ref[32]; char m_Ref[32];
//have to store it here since the object refrerences will be duplicated.
//have to store it here since the object references will be duplicated.
DrawSheetPath m_SheetList; //composed of UIDs DrawSheetPath m_SheetList; //composed of UIDs
} ListComponent; } ListComponent;
......
...@@ -610,7 +610,7 @@ void WinEDA_SchematicFrame::Process_Special_Functions( wxCommandEvent& event ) ...@@ -610,7 +610,7 @@ void WinEDA_SchematicFrame::Process_Special_Functions( wxCommandEvent& event )
{ {
EDA_LibComponentStruct* LibEntry; EDA_LibComponentStruct* LibEntry;
LibEntry = FindLibPart( LibEntry = FindLibPart(
( (SCH_COMPONENT*) screen->GetCurItem() )->m_ChipName, ( (SCH_COMPONENT*) screen->GetCurItem() )->m_ChipName.GetData(),
wxEmptyString, wxEmptyString,
FIND_ALIAS ); FIND_ALIAS );
if( LibEntry && LibEntry->m_DocFile != wxEmptyString ) if( LibEntry && LibEntry->m_DocFile != wxEmptyString )
......
...@@ -253,7 +253,7 @@ wxClientDC dc(DrawPanel); ...@@ -253,7 +253,7 @@ wxClientDC dc(DrawPanel);
g_ViewUnit = 1; g_ViewUnit = 1;
g_ViewConvert = 1; g_ViewConvert = 1;
LibEntry = FindLibPart(CmpName,Lib->m_Name, FIND_ALIAS); LibEntry = FindLibPart(CmpName.GetData(),Lib->m_Name, FIND_ALIAS);
g_CurrentViewComponentName = CmpName; g_CurrentViewComponentName = CmpName;
DisplayLibInfos(); DisplayLibInfos();
Zoom_Automatique(FALSE); Zoom_Automatique(FALSE);
......
...@@ -212,20 +212,20 @@ ...@@ -212,20 +212,20 @@
#include "../bitmaps/annotate_right_down.xpm" #include "../bitmaps/annotate_right_down.xpm"
#include "../bitmaps/annotate_down_right.xpm" #include "../bitmaps/annotate_down_right.xpm"
#include "../bitmaps/new_sch.xpm" // #include "../bitmaps/new_sch.xpm"
#include "../bitmaps/Open_Project.xpm" #include "../bitmaps/Open_Project.xpm"
#include "../bitmaps/new_cvpcb.xpm" // #include "../bitmaps/new_cvpcb.xpm"
#include "../bitmaps/zip.xpm" #include "../bitmaps/zip.xpm"
#include "../bitmaps/icon_gerbview_small.xpm" #include "../bitmaps/icon_gerbview_small.xpm"
#include "../bitmaps/zip_tool.xpm" // #include "../bitmaps/zip_tool.xpm"
#include "../bitmaps/unzip.xpm" #include "../bitmaps/unzip.xpm"
#include "../bitmaps/Browse_Files.xpm" #include "../bitmaps/Browse_Files.xpm"
#include "../bitmaps/New_Project.xpm" #include "../bitmaps/New_Project.xpm"
#include "../bitmaps/new_gerb.xpm" // #include "../bitmaps/new_gerb.xpm"
#include "../bitmaps/new_python.xpm" // #include "../bitmaps/new_python.xpm"
#include "../bitmaps/icon_cvpcb_small.xpm" #include "../bitmaps/icon_cvpcb_small.xpm"
#include "../bitmaps/unknown.xpm" #include "../bitmaps/unknown.xpm"
#include "../bitmaps/new_pcb.xpm" // #include "../bitmaps/new_pcb.xpm"
#include "../bitmaps/reload.xpm" #include "../bitmaps/reload.xpm"
......
...@@ -280,7 +280,7 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea, ...@@ -280,7 +280,7 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea,
{ {
std::vector<CPolyLine*> * pa = new std::vector<CPolyLine*>; std::vector<CPolyLine*> * pa = new std::vector<CPolyLine*>;
curr_polygon->Undraw(); curr_polygon->Undraw();
int n_poly = CurrArea->m_Poly->NormalizeWithGpc( pa, bRetainArcs ); int n_poly = CurrArea->m_Poly->NormalizeAreaOutlines( pa, bRetainArcs );
if( n_poly > 1 ) // i.e if clipping has created some polygons, we must add these new copper areas if( n_poly > 1 ) // i.e if clipping has created some polygons, we must add these new copper areas
{ {
ZONE_CONTAINER* NewArea; ZONE_CONTAINER* NewArea;
...@@ -310,7 +310,8 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea, ...@@ -310,7 +310,8 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea,
* itself and the polygons for any other areas on the same net. * itself and the polygons for any other areas on the same net.
* This may change the number and order of copper areas in the net. * This may change the number and order of copper areas in the net.
* @param modified_area = area to test * @param modified_area = area to test
* @param bMessageBox : if true, shows message boxes when clipping occurs. * @param bMessageBoxInt == true, shows message when clipping occurs.
* @param bMessageBoxArc == true, shows message when clipping can't be done due to arcs.
* @return : * @return :
* -1 if arcs intersect other sides, so polygon can't be clipped * -1 if arcs intersect other sides, so polygon can't be clipped
* 0 if no intersecting sides * 0 if no intersecting sides
...@@ -697,8 +698,11 @@ int BOARD::CombineAreas( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combi ...@@ -697,8 +698,11 @@ int BOARD::CombineAreas( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combi
CPolyLine* poly2 = area_to_combine->m_Poly; CPolyLine* poly2 = area_to_combine->m_Poly;
std::vector<CArc> arc_array1; std::vector<CArc> arc_array1;
std::vector<CArc> arc_array2; std::vector<CArc> arc_array2;
poly1->MakeGpcPoly( -1, &arc_array1 );
poly2->MakeGpcPoly( -1, &arc_array2 ); poly1->MakePolygonFromAreaOutlines( -1, &arc_array1 );
poly2->MakePolygonFromAreaOutlines( -1, &arc_array2 );
#ifdef USE_GPC_POLY_LIB
int n_ext_cont1 = 0; int n_ext_cont1 = 0;
for( int ic = 0; ic<poly1->GetGpcPoly()->num_contours; ic++ ) for( int ic = 0; ic<poly1->GetGpcPoly()->num_contours; ic++ )
if( !( (poly1->GetGpcPoly()->hole)[ic] ) ) if( !( (poly1->GetGpcPoly()->hole)[ic] ) )
...@@ -776,7 +780,97 @@ int BOARD::CombineAreas( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combi ...@@ -776,7 +780,97 @@ int BOARD::CombineAreas( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combi
area_ref->m_Poly->Draw(); area_ref->m_Poly->Draw();
gpc_free_polygon( union_gpc ); gpc_free_polygon( union_gpc );
delete union_gpc; delete union_gpc;
return 1; return 1;
#endif
#ifdef USE_GPL_POLY_LIB
//@todo
#warning work in progress
wxString msg;
int n_ext_cont1 = poly1->GetPhpPoly()->m_cnt;
int n_ext_cont2 = poly2->GetPhpPoly()->m_cnt;
polygon* union_polygon = NULL;
union_polygon = poly1->GetPhpPoly()->boolean( poly2->GetPhpPoly(), A_OR_B );
if ( union_polygon == NULL )
return 0;
// get number of outside contours
int n_union_ext_cont = union_polygon->m_cnt;
msg.Printf(wxT("cnt res = %d, pts1,2 = %d,%d"), n_union_ext_cont , n_ext_cont1, n_ext_cont2);
wxMessageBox(msg);
// if no intersection, free new gpc and return
#if 0
if( n_union_ext_cont == n_ext_cont1 + n_ext_cont2 )
{
wxMessageBox(wxT("no change polys"));
delete union_polygon;
return 0;
}
#endif
wxMessageBox(wxT("merge areas"));
// intersection, replace area_ref->m_Poly with combined areas and remove area_to_combine
RemoveArea( area_to_combine );
area_ref->m_Poly->RemoveAllContours();
// create area with external contour
// for( int ic = 0; ic < union_polygon->m_cnt; ic++ )
{
// if( !(union_gpc->hole)[ic] ) // Recreate only area edges, NOT holes (todo..)
{
// external contour, replace this poly
vertex * curr_vertex = union_polygon->getFirst();
for( int ii = 0; ii < union_polygon->m_cnt; ii++ )
{
int x = (int) curr_vertex->X();
int y = (int) curr_vertex->Y();
msg.Printf(wxT("ii = %d, pts = %d,%d, wid = %d"), ii , x, y, curr_vertex->id());
wxMessageBox(msg);
if( ii==0 )
{
area_ref->m_Poly->Start( area_ref->GetLayer(
), x, y, area_ref->m_Poly->GetHatchStyle() );
}
else
area_ref->m_Poly->AppendCorner( x, y );
curr_vertex = curr_vertex->Next();
// if( curr_vertex->id() == union_polygon->getFirst()->id() ) break;
}
area_ref->m_Poly->Close();
}
}
// add holes
#if 0
for( int ic = 0; ic<union_gpc->num_contours; ic++ )
{
if( (union_gpc->hole)[ic] )
{
// hole
for( int i = 0; i<union_gpc->contour[ic].num_vertices; i++ )
{
int x = (int) ( (union_gpc->contour)[ic].vertex )[i].x;
int y = (int) ( (union_gpc->contour)[ic].vertex )[i].y;
area_ref->m_Poly->AppendCorner( x, y );
}
area_ref->m_Poly->Close();
}
}
#endif
area_ref->utility = 1;
area_ref->m_Poly->RestoreArcs( &arc_array1 );
area_ref->m_Poly->RestoreArcs( &arc_array2 );
area_ref->m_Poly->Draw();
delete union_polygon;
return 0;
#endif
} }
...@@ -785,7 +879,7 @@ int BOARD::CombineAreas( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combi ...@@ -785,7 +879,7 @@ int BOARD::CombineAreas( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combi
/** /**
* Function Is_Area_Inside_Area * Function Is_Area_Inside_Area
* Test a given area to see if it is inside an other area, or an other area is inside the given area * Test a given area to see if it is inside an other area, or an other area is inside the given area
* an area is inside an other are if ALL its corners are inside * an area is inside an other are if ALL its edges are inside the other area
* @param Area_Ref: the given area to compare with other areas * @param Area_Ref: the given area to compare with other areas
* used to remove redundant areas * used to remove redundant areas
*/ */
......
// PolyLine.cpp ... implementation of CPolyLine class from FreePCB. // PolyLine.cpp ... implementation of CPolyLine class from FreePCB.
// //
// implementation for kicad // implementation for kicad
// //
...@@ -12,33 +13,47 @@ using namespace std; ...@@ -12,33 +13,47 @@ using namespace std;
#include "PolyLine.h" #include "PolyLine.h"
#define to_int(x) (int)round((x)) #define to_int( x ) (int) round( (x) )
#define pi 3.14159265359 #define pi 3.14159265359
#define DENOM 10 // to use mils for php clipping
//#define DENOM 1 // to use internal units for php clipping
CPolyLine::CPolyLine() CPolyLine::CPolyLine()
{ {
m_HatchStyle = 0; m_HatchStyle = 0;
m_Width = 0; m_Width = 0;
utility = 0; utility = 0;
#ifdef USE_GPC_POLY_LIB
m_gpc_poly = new gpc_polygon; m_gpc_poly = new gpc_polygon;
m_gpc_poly->num_contours = 0; m_gpc_poly->num_contours = 0;
#else
m_gpc_poly = NULL;
#endif
#ifdef USE_GPL_POLY_LIB
m_php_poly = new polygon; m_php_poly = new polygon;
#else
m_php_poly = NULL;
#endif
} }
// destructor, removes display elements // destructor, removes display elements
// //
CPolyLine::~CPolyLine() CPolyLine::~CPolyLine()
{ {
Undraw(); Undraw();
#ifdef USE_GPC_POLY_LIB
FreeGpcPoly(); FreeGpcPoly();
delete m_gpc_poly; delete m_gpc_poly;
#endif
#ifdef USE_GPL_POLY_LIB
delete m_php_poly; delete m_php_poly;
#endif
} }
#ifdef USE_GPC_POLY_LIB
// Use the General Polygon Clipping Library to clip contours // Use the General Polygon Clipping Library to clip contours
// If this results in new polygons, return them as std::vector p // If this results in new polygons, return them as std::vector p
// If bRetainArcs == TRUE, try to retain arcs in polys // If bRetainArcs == TRUE, try to retain arcs in polys
...@@ -58,7 +73,7 @@ int CPolyLine::NormalizeWithGpc( std::vector<CPolyLine*> * pa, bool bRetainArcs ...@@ -58,7 +73,7 @@ int CPolyLine::NormalizeWithGpc( std::vector<CPolyLine*> * pa, bool bRetainArcs
// now, recreate poly // now, recreate poly
// first, find outside contours and create new CPolyLines if necessary // first, find outside contours and create new CPolyLines if necessary
int n_ext_cont = 0; int n_ext_cont = 0;
for( int ic=0; ic<m_gpc_poly->num_contours; ic++ ) for( int ic = 0; ic<m_gpc_poly->num_contours; ic++ )
{ {
if( !(m_gpc_poly->hole)[ic] ) if( !(m_gpc_poly->hole)[ic] )
{ {
...@@ -67,45 +82,46 @@ int CPolyLine::NormalizeWithGpc( std::vector<CPolyLine*> * pa, bool bRetainArcs ...@@ -67,45 +82,46 @@ int CPolyLine::NormalizeWithGpc( std::vector<CPolyLine*> * pa, bool bRetainArcs
// first external contour, replace this poly // first external contour, replace this poly
corner.clear(); corner.clear();
side_style.clear(); side_style.clear();
for( int i=0; i<m_gpc_poly->contour[ic].num_vertices; i++ ) for( int i = 0; i<m_gpc_poly->contour[ic].num_vertices; i++ )
{ {
int x = to_int(((m_gpc_poly->contour)[ic].vertex)[i].x); int x = to_int( ( (m_gpc_poly->contour)[ic].vertex )[i].x );
int y = to_int(((m_gpc_poly->contour)[ic].vertex)[i].y); int y = to_int( ( (m_gpc_poly->contour)[ic].vertex )[i].y );
if( i==0 ) if( i==0 )
Start( m_layer, x, y, m_HatchStyle ); Start( m_layer, x, y, m_HatchStyle );
else else
AppendCorner( x, y, STRAIGHT, FALSE ); AppendCorner( x, y, STRAIGHT, FALSE );
} }
Close(); Close();
n_ext_cont++; n_ext_cont++;
} }
else if( pa ) else if( pa )
{ {
// next external contour, create new poly // next external contour, create new poly
CPolyLine * poly = new CPolyLine; CPolyLine* poly = new CPolyLine;
pa->push_back(poly); // put in array pa->push_back( poly ); // put in array
for( int i=0; i<m_gpc_poly->contour[ic].num_vertices; i++ ) for( int i = 0; i<m_gpc_poly->contour[ic].num_vertices; i++ )
{ {
int x = to_int(((m_gpc_poly->contour)[ic].vertex)[i].x); int x = to_int( ( (m_gpc_poly->contour)[ic].vertex )[i].x );
int y = to_int(((m_gpc_poly->contour)[ic].vertex)[i].y); int y = to_int( ( (m_gpc_poly->contour)[ic].vertex )[i].y );
if( i==0 ) if( i==0 )
poly->Start( m_layer, x, y, m_HatchStyle ); poly->Start( m_layer, x, y, m_HatchStyle );
else else
poly->AppendCorner( x, y, STRAIGHT, FALSE ); poly->AppendCorner( x, y, STRAIGHT, FALSE );
} }
poly->Close( STRAIGHT, FALSE ); poly->Close( STRAIGHT, FALSE );
n_ext_cont++; n_ext_cont++;
} }
} }
} }
// now add cutouts to the CPolyLine(s) // now add cutouts to the CPolyLine(s)
for( int ic=0; ic<m_gpc_poly->num_contours; ic++ ) for( int ic = 0; ic<m_gpc_poly->num_contours; ic++ )
{ {
if( (m_gpc_poly->hole)[ic] ) if( (m_gpc_poly->hole)[ic] )
{ {
CPolyLine * ext_poly = NULL; CPolyLine* ext_poly = NULL;
if( n_ext_cont == 1 ) if( n_ext_cont == 1 )
{ {
ext_poly = this; ext_poly = this;
...@@ -113,15 +129,15 @@ int CPolyLine::NormalizeWithGpc( std::vector<CPolyLine*> * pa, bool bRetainArcs ...@@ -113,15 +129,15 @@ int CPolyLine::NormalizeWithGpc( std::vector<CPolyLine*> * pa, bool bRetainArcs
else else
{ {
// find the polygon that contains this hole // find the polygon that contains this hole
for( int i=0; i<m_gpc_poly->contour[ic].num_vertices; i++ ) for( int i = 0; i<m_gpc_poly->contour[ic].num_vertices; i++ )
{ {
int x = to_int(((m_gpc_poly->contour)[ic].vertex)[i].x); int x = to_int( ( (m_gpc_poly->contour)[ic].vertex )[i].x );
int y = to_int(((m_gpc_poly->contour)[ic].vertex)[i].y); int y = to_int( ( (m_gpc_poly->contour)[ic].vertex )[i].y );
if( TestPointInside( x, y ) ) if( TestPointInside( x, y ) )
ext_poly = this; ext_poly = this;
else else
{ {
for( int ext_ic=0; ext_ic<n_ext_cont-1; ext_ic++ ) for( int ext_ic = 0; ext_ic<n_ext_cont - 1; ext_ic++ )
{ {
if( (*pa)[ext_ic]->TestPointInside( x, y ) ) if( (*pa)[ext_ic]->TestPointInside( x, y ) )
{ {
...@@ -135,16 +151,18 @@ int CPolyLine::NormalizeWithGpc( std::vector<CPolyLine*> * pa, bool bRetainArcs ...@@ -135,16 +151,18 @@ int CPolyLine::NormalizeWithGpc( std::vector<CPolyLine*> * pa, bool bRetainArcs
} }
} }
if( !ext_poly ) if( !ext_poly )
wxASSERT(0); wxASSERT( 0 );
for( int i=0; i<m_gpc_poly->contour[ic].num_vertices; i++ ) for( int i = 0; i<m_gpc_poly->contour[ic].num_vertices; i++ )
{ {
int x = to_int(((m_gpc_poly->contour)[ic].vertex)[i].x); int x = to_int( ( (m_gpc_poly->contour)[ic].vertex )[i].x );
int y = to_int(((m_gpc_poly->contour)[ic].vertex)[i].y); int y = to_int( ( (m_gpc_poly->contour)[ic].vertex )[i].y );
ext_poly->AppendCorner( x, y, STRAIGHT, FALSE ); ext_poly->AppendCorner( x, y, STRAIGHT, FALSE );
} }
ext_poly->Close( STRAIGHT, FALSE ); ext_poly->Close( STRAIGHT, FALSE );
} }
} }
if( bRetainArcs ) if( bRetainArcs )
RestoreArcs( &arc_array, pa ); RestoreArcs( &arc_array, pa );
FreeGpcPoly(); FreeGpcPoly();
...@@ -152,42 +170,47 @@ int CPolyLine::NormalizeWithGpc( std::vector<CPolyLine*> * pa, bool bRetainArcs ...@@ -152,42 +170,47 @@ int CPolyLine::NormalizeWithGpc( std::vector<CPolyLine*> * pa, bool bRetainArcs
return n_ext_cont; return n_ext_cont;
} }
#endif
#ifdef USE_GPL_POLY_LIB
// make a php_polygon from first contour // make a php_polygon from first contour
int CPolyLine::MakePhpPoly() int CPolyLine::MakePhpPoly()
{ {
FreePhpPoly(); FreePhpPoly();
polygon test_poly; int nv = GetContourEnd( 0 );
int nv = GetContourEnd(0); for( int iv = 0; iv <= nv; iv++ )
for( int iv=0; iv<=nv; iv++ ) m_php_poly->addv( GetX( iv ), GetY( iv ) );
{
int x = GetX(iv)/DENOM; m_php_poly->getFirst()->m_id = 1;
int y = GetY(iv)/DENOM;
m_php_poly->addv( x, y );
}
return 0; return 0;
} }
void CPolyLine::FreePhpPoly() void CPolyLine::FreePhpPoly()
{ {
// delete all vertices // delete all vertices
while( m_php_poly->m_cnt > 1 ) while( m_php_poly->m_cnt > 1 )
{ {
vertex * fv = m_php_poly->getFirst(); vertex* fv = m_php_poly->getFirst();
m_php_poly->del( fv->m_nextV ); m_php_poly->del( fv->m_nextV );
} }
delete m_php_poly->m_first; delete m_php_poly->m_first;
m_php_poly->m_first = NULL; m_php_poly->m_first = NULL;
m_php_poly->m_cnt = 0; m_php_poly->m_cnt = 0;
} }
// Use the php clipping lib to clip this poly against poly // Use the php clipping lib to clip this poly against poly
// //
void CPolyLine::ClipPhpPolygon( int php_op, CPolyLine * poly ) void CPolyLine::ClipPhpPolygon( int php_op, CPolyLine* poly )
{ {
Undraw(); Undraw();
poly->MakePhpPoly(); poly->MakePhpPoly();
MakePhpPoly(); MakePhpPoly();
polygon * p = m_php_poly->boolean( poly->m_php_poly, php_op ); polygon* p = m_php_poly->boolean( poly->m_php_poly, php_op );
poly->FreePhpPoly(); poly->FreePhpPoly();
FreePhpPoly(); FreePhpPoly();
...@@ -196,38 +219,81 @@ void CPolyLine::ClipPhpPolygon( int php_op, CPolyLine * poly ) ...@@ -196,38 +219,81 @@ void CPolyLine::ClipPhpPolygon( int php_op, CPolyLine * poly )
// now screw with the PolyLine // now screw with the PolyLine
corner.clear(); corner.clear();
side_style.clear(); side_style.clear();
do do
{ {
vertex * v = p->getFirst(); vertex* v = p->getFirst();
Start( m_layer, to_int(v->X()*DENOM), to_int(v->Y()*DENOM), m_HatchStyle ); Start( m_layer, to_int( v->X() ), to_int( v->Y() ), m_HatchStyle );
do do
{ {
vertex * n = v->Next(); vertex* n = v->Next();
AppendCorner( to_int(v->X()*DENOM), to_int((v->Y()*DENOM )) ); AppendCorner( to_int( v->X() ), to_int( (v->Y()) ) );
v = n; v = n;
} } while( v->id() != p->getFirst()->id() );
while( v->id() != p->getFirst()->id() );
Close(); Close();
// p = p->NextPoly(); // p = p->NextPoly();
delete p; delete p;
p = NULL; p = NULL;
} } while( p );
while( p );
} }
Draw(); Draw();
} }
// make a gpc_polygon for a closed polyline contour
// approximates arcs with multiple straight-line segments #endif
// if icontour = -1, make polygon with all contours,
// combining intersecting contours if possible int CPolyLine::MakePolygonFromAreaOutlines( int icontour, std::vector<CArc> * arc_array )
// returns data on arcs in arc_array {
// #ifdef USE_GPC_POLY_LIB
return MakeGpcPoly( icontour, arc_array );
#endif
#ifdef USE_GPL_POLY_LIB
return MakePhpPoly( );
#endif
}
void CPolyLine::FreePolygon()
{
#ifdef USE_GPC_POLY_LIB
FreeGpcPoly();
#endif
#ifdef USE_GPL_POLY_LIB
FreePhpPoly();
#endif
}
int CPolyLine::NormalizeAreaOutlines( std::vector<CPolyLine*> * pa, bool bRetainArcs )
{
#ifdef USE_GPC_POLY_LIB
return NormalizeWithGpc( pa, bRetainArcs );
#endif
#ifdef USE_GPL_POLY_LIB
#warning NormalizeAreaOutlines with GPL lib must be finished (TODO)
return 1;
#endif
}
#ifdef USE_GPC_POLY_LIB
/** Function MakeGpcPoly
* make a gpc_polygon for a closed polyline contour
* approximates arcs with multiple straight-line segments
* @param icontour : if icontour = -1, make polygon with all contours,
* combining intersecting contours if possible
* @param arc_array : return data on arcs in arc_array
* @return error: 0 if Ok, 1 if error
*/
int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array ) int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array )
{ {
if( m_gpc_poly->num_contours ) if( m_gpc_poly->num_contours )
FreeGpcPoly(); FreeGpcPoly();
if( !GetClosed() && (icontour == (GetNumContours()-1) || icontour == -1)) if( !GetClosed() && (icontour == (GetNumContours() - 1) || icontour == -1) )
return 1; // error return 1; // error
// initialize m_gpc_poly // initialize m_gpc_poly
...@@ -246,19 +312,19 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array ) ...@@ -246,19 +312,19 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array )
if( arc_array ) if( arc_array )
arc_array->clear(); arc_array->clear();
int iarc = 0; int iarc = 0;
for( int icont=first_contour; icont<=last_contour; icont++ ) for( int icont = first_contour; icont<=last_contour; icont++ )
{ {
// make gpc_polygon for this contour // make gpc_polygon for this contour
gpc_polygon * gpc = new gpc_polygon; gpc_polygon* gpc = new gpc_polygon;
gpc->num_contours = 0; gpc->num_contours = 0;
gpc->hole = NULL; gpc->hole = NULL;
gpc->contour = NULL; gpc->contour = NULL;
// first, calculate number of vertices in contour // first, calculate number of vertices in contour
int n_vertices = 0; int n_vertices = 0;
int ic_st = GetContourStart(icont); int ic_st = GetContourStart( icont );
int ic_end = GetContourEnd(icont); int ic_end = GetContourEnd( icont );
for( int ic=ic_st; ic<=ic_end; ic++ ) for( int ic = ic_st; ic<=ic_end; ic++ )
{ {
int style = side_style[ic]; int style = side_style[ic];
int x1 = corner[ic].x; int x1 = corner[ic].x;
...@@ -266,8 +332,8 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array ) ...@@ -266,8 +332,8 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array )
int x2, y2; int x2, y2;
if( ic < ic_end ) if( ic < ic_end )
{ {
x2 = corner[ic+1].x; x2 = corner[ic + 1].x;
y2 = corner[ic+1].y; y2 = corner[ic + 1].y;
} }
else else
{ {
...@@ -280,18 +346,19 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array ) ...@@ -280,18 +346,19 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array )
{ {
// style is ARC_CW or ARC_CCW // style is ARC_CW or ARC_CCW
int n; // number of steps for arcs int n; // number of steps for arcs
n = (abs(x2-x1)+abs(y2-y1))/(CArc::MAX_STEP); n = ( abs( x2 - x1 ) + abs( y2 - y1 ) ) / (CArc::MAX_STEP);
n = max( n, CArc::MIN_STEPS ); // or at most 5 degrees of arc n = max( n, CArc::MIN_STEPS ); // or at most 5 degrees of arc
n_vertices += n; n_vertices += n;
n_arcs++; n_arcs++;
} }
} }
// now create gcp_vertex_list for this contour // now create gcp_vertex_list for this contour
gpc_vertex_list * g_v_list = new gpc_vertex_list; gpc_vertex_list* g_v_list = new gpc_vertex_list;
g_v_list->vertex = (gpc_vertex*)calloc( sizeof(gpc_vertex), n_vertices ); g_v_list->vertex = (gpc_vertex*) calloc( sizeof(gpc_vertex), n_vertices );
g_v_list->num_vertices = n_vertices; g_v_list->num_vertices = n_vertices;
int ivtx = 0; int ivtx = 0;
for( int ic=ic_st; ic<=ic_end; ic++ ) for( int ic = ic_st; ic<=ic_end; ic++ )
{ {
int style = side_style[ic]; int style = side_style[ic];
int x1 = corner[ic].x; int x1 = corner[ic].x;
...@@ -299,8 +366,8 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array ) ...@@ -299,8 +366,8 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array )
int x2, y2; int x2, y2;
if( ic < ic_end ) if( ic < ic_end )
{ {
x2 = corner[ic+1].x; x2 = corner[ic + 1].x;
y2 = corner[ic+1].y; y2 = corner[ic + 1].y;
} }
else else
{ {
...@@ -317,11 +384,11 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array ) ...@@ -317,11 +384,11 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array )
{ {
// style is arc_cw or arc_ccw // style is arc_cw or arc_ccw
int n; // number of steps for arcs int n; // number of steps for arcs
n = (abs(x2-x1)+abs(y2-y1))/(CArc::MAX_STEP); n = ( abs( x2 - x1 ) + abs( y2 - y1 ) ) / (CArc::MAX_STEP);
n = max( n, CArc::MIN_STEPS ); // or at most 5 degrees of arc n = max( n, CArc::MIN_STEPS ); // or at most 5 degrees of arc
double xo, yo, theta1, theta2, a, b; double xo, yo, theta1, theta2, a, b;
a = fabs( (double)(x1 - x2) ); a = fabs( (double) (x1 - x2) );
b = fabs( (double)(y1 - y2) ); b = fabs( (double) (y1 - y2) );
if( style == CPolyLine::ARC_CW ) if( style == CPolyLine::ARC_CW )
{ {
// clockwise arc (ie.quadrant of ellipse) // clockwise arc (ie.quadrant of ellipse)
...@@ -331,14 +398,14 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array ) ...@@ -331,14 +398,14 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array )
xo = x2; xo = x2;
yo = y1; yo = y1;
theta1 = pi; theta1 = pi;
theta2 = pi/2.0; theta2 = pi / 2.0;
} }
else if( x2 < x1 && y2 > y1 ) else if( x2 < x1 && y2 > y1 )
{ {
// second quadrant, draw third quadrant of ellipse // second quadrant, draw third quadrant of ellipse
xo = x1; xo = x1;
yo = y2; yo = y2;
theta1 = 3.0*pi/2.0; theta1 = 3.0 * pi / 2.0;
theta2 = pi; theta2 = pi;
} }
else if( x2 < x1 && y2 < y1 ) else if( x2 < x1 && y2 < y1 )
...@@ -346,14 +413,14 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array ) ...@@ -346,14 +413,14 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array )
// third quadrant, draw fourth quadrant of ellipse // third quadrant, draw fourth quadrant of ellipse
xo = x2; xo = x2;
yo = y1; yo = y1;
theta1 = 2.0*pi; theta1 = 2.0 * pi;
theta2 = 3.0*pi/2.0; theta2 = 3.0 * pi / 2.0;
} }
else else
{ {
xo = x1; // fourth quadrant, draw first quadrant of ellipse xo = x1; // fourth quadrant, draw first quadrant of ellipse
yo = y2; yo = y2;
theta1 = pi/2.0; theta1 = pi / 2.0;
theta2 = 0.0; theta2 = 0.0;
} }
} }
...@@ -364,21 +431,21 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array ) ...@@ -364,21 +431,21 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array )
{ {
xo = x1; // first quadrant, draw fourth quadrant of ellipse xo = x1; // first quadrant, draw fourth quadrant of ellipse
yo = y2; yo = y2;
theta1 = 3.0*pi/2.0; theta1 = 3.0 * pi / 2.0;
theta2 = 2.0*pi; theta2 = 2.0 * pi;
} }
else if( x2 < x1 && y2 > y1 ) else if( x2 < x1 && y2 > y1 )
{ {
xo = x2; // second quadrant xo = x2; // second quadrant
yo = y1; yo = y1;
theta1 = 0.0; theta1 = 0.0;
theta2 = pi/2.0; theta2 = pi / 2.0;
} }
else if( x2 < x1 && y2 < y1 ) else if( x2 < x1 && y2 < y1 )
{ {
xo = x1; // third quadrant xo = x1; // third quadrant
yo = y2; yo = y2;
theta1 = pi/2.0; theta1 = pi / 2.0;
theta2 = pi; theta2 = pi;
} }
else else
...@@ -386,9 +453,10 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array ) ...@@ -386,9 +453,10 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array )
xo = x2; // fourth quadrant xo = x2; // fourth quadrant
yo = y1; yo = y1;
theta1 = pi; theta1 = pi;
theta2 = 3.0*pi/2.0; theta2 = 3.0 * pi / 2.0;
} }
} }
// now write steps for arc // now write steps for arc
if( arc_array ) if( arc_array )
{ {
...@@ -399,14 +467,14 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array ) ...@@ -399,14 +467,14 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array )
new_arc.yi = y1; new_arc.yi = y1;
new_arc.xf = x2; new_arc.xf = x2;
new_arc.yf = y2; new_arc.yf = y2;
arc_array->push_back(new_arc); arc_array->push_back( new_arc );
iarc++; iarc++;
} }
for( int is=0; is<n; is++ ) for( int is = 0; is<n; is++ )
{ {
double theta = theta1 + ((theta2-theta1)*(double)is)/n; double theta = theta1 + ( (theta2 - theta1) * (double) is ) / n;
double x = xo + a*cos(theta); double x = xo + a* cos( theta );
double y = yo + b*sin(theta); double y = yo + b* sin( theta );
if( is == 0 ) if( is == 0 )
{ {
x = x1; x = x1;
...@@ -418,12 +486,15 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array ) ...@@ -418,12 +486,15 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array )
} }
} }
} }
if( n_vertices != ivtx ) if( n_vertices != ivtx )
wxASSERT(0); wxASSERT( 0 );
// add vertex_list to gpc // add vertex_list to gpc
gpc_add_contour( gpc, g_v_list, 0 ); gpc_add_contour( gpc, g_v_list, 0 );
// now clip m_gpc_poly with gpc, put new poly into result // now clip m_gpc_poly with gpc, put new poly into result
gpc_polygon * result = new gpc_polygon; gpc_polygon* result = new gpc_polygon;
if( icontour == -1 && icont != 0 ) if( icontour == -1 && icont != 0 )
gpc_polygon_clip( GPC_DIFF, m_gpc_poly, gpc, result ); // hole gpc_polygon_clip( GPC_DIFF, m_gpc_poly, gpc, result ); // hole
else else
...@@ -437,10 +508,12 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array ) ...@@ -437,10 +508,12 @@ int CPolyLine::MakeGpcPoly( int icontour, std::vector<CArc> * arc_array )
free( g_v_list->vertex ); free( g_v_list->vertex );
free( g_v_list ); free( g_v_list );
} }
return 0; return 0;
} }
int CPolyLine::FreeGpcPoly()
void CPolyLine::FreeGpcPoly()
{ {
if( m_gpc_poly->num_contours ) if( m_gpc_poly->num_contours )
{ {
...@@ -449,10 +522,11 @@ int CPolyLine::FreeGpcPoly() ...@@ -449,10 +522,11 @@ int CPolyLine::FreeGpcPoly()
delete m_gpc_poly->hole; delete m_gpc_poly->hole;
} }
m_gpc_poly->num_contours = 0; m_gpc_poly->num_contours = 0;
return 0;
} }
#endif
// Restore arcs to a polygon where they were replaced with steps // Restore arcs to a polygon where they were replaced with steps
// If pa != NULL, also use polygons in pa array // If pa != NULL, also use polygons in pa array
// //
...@@ -460,27 +534,29 @@ int CPolyLine::RestoreArcs( std::vector<CArc> * arc_array, std::vector<CPolyLine ...@@ -460,27 +534,29 @@ int CPolyLine::RestoreArcs( std::vector<CArc> * arc_array, std::vector<CPolyLine
{ {
// get poly info // get poly info
int n_polys = 1; int n_polys = 1;
if( pa ) if( pa )
n_polys += pa->size(); n_polys += pa->size();
CPolyLine * poly; CPolyLine* poly;
// undraw polys and clear utility flag for all corners // undraw polys and clear utility flag for all corners
for( int ip=0; ip<n_polys; ip++ ) for( int ip = 0; ip<n_polys; ip++ )
{ {
if( ip == 0 ) if( ip == 0 )
poly = this; poly = this;
else else
poly = (*pa)[ip-1]; poly = (*pa)[ip - 1];
poly->Undraw(); poly->Undraw();
for( int ic=0; ic<poly->GetNumCorners(); ic++ ) for( int ic = 0; ic<poly->GetNumCorners(); ic++ )
poly->SetUtility( ic, 0 ); // clear utility flag poly->SetUtility( ic, 0 ); // clear utility flag
} }
// find arcs and replace them // find arcs and replace them
bool bFound; bool bFound;
int arc_start = 0; int arc_start = 0;
int arc_end = 0; int arc_end = 0;
for( unsigned iarc=0; iarc<arc_array->size(); iarc++ ) for( unsigned iarc = 0; iarc<arc_array->size(); iarc++ )
{ {
int arc_xi = (*arc_array)[iarc].xi; int arc_xi = (*arc_array)[iarc].xi;
int arc_yi = (*arc_array)[iarc].yi; int arc_yi = (*arc_array)[iarc].yi;
...@@ -489,34 +565,35 @@ int CPolyLine::RestoreArcs( std::vector<CArc> * arc_array, std::vector<CPolyLine ...@@ -489,34 +565,35 @@ int CPolyLine::RestoreArcs( std::vector<CArc> * arc_array, std::vector<CPolyLine
int n_steps = (*arc_array)[iarc].n_steps; int n_steps = (*arc_array)[iarc].n_steps;
int style = (*arc_array)[iarc].style; int style = (*arc_array)[iarc].style;
bFound = FALSE; bFound = FALSE;
// loop through polys // loop through polys
for( int ip=0; ip<n_polys; ip++ ) for( int ip = 0; ip<n_polys; ip++ )
{ {
if( ip == 0 ) if( ip == 0 )
poly = this; poly = this;
else else
poly = (*pa)[ip-1]; poly = (*pa)[ip - 1];
for( int icont=0; icont<poly->GetNumContours(); icont++ ) for( int icont = 0; icont<poly->GetNumContours(); icont++ )
{ {
int ic_start = poly->GetContourStart(icont); int ic_start = poly->GetContourStart( icont );
int ic_end = poly->GetContourEnd(icont); int ic_end = poly->GetContourEnd( icont );
if( (ic_end-ic_start) > n_steps ) if( (ic_end - ic_start) > n_steps )
{ {
for( int ic=ic_start; ic<=ic_end; ic++ ) for( int ic = ic_start; ic<=ic_end; ic++ )
{ {
int ic_next = ic+1; int ic_next = ic + 1;
if( ic_next > ic_end ) if( ic_next > ic_end )
ic_next = ic_start; ic_next = ic_start;
int xi = poly->GetX(ic); int xi = poly->GetX( ic );
int yi = poly->GetY(ic); int yi = poly->GetY( ic );
if( xi == arc_xi && yi == arc_yi ) if( xi == arc_xi && yi == arc_yi )
{ {
// test for forward arc // test for forward arc
int ic2 = ic + n_steps; int ic2 = ic + n_steps;
if( ic2 > ic_end ) if( ic2 > ic_end )
ic2 = ic2 - ic_end + ic_start - 1; ic2 = ic2 - ic_end + ic_start - 1;
int xf = poly->GetX(ic2); int xf = poly->GetX( ic2 );
int yf = poly->GetY(ic2); int yf = poly->GetY( ic2 );
if( xf == arc_xf && yf == arc_yf ) if( xf == arc_xf && yf == arc_yf )
{ {
// arc from ic to ic2 // arc from ic to ic2
...@@ -530,8 +607,8 @@ int CPolyLine::RestoreArcs( std::vector<CArc> * arc_array, std::vector<CPolyLine ...@@ -530,8 +607,8 @@ int CPolyLine::RestoreArcs( std::vector<CArc> * arc_array, std::vector<CPolyLine
ic2 = ic - n_steps; ic2 = ic - n_steps;
if( ic2 < ic_start ) if( ic2 < ic_start )
ic2 = ic2 - ic_start + ic_end + 1; ic2 = ic2 - ic_start + ic_end + 1;
xf = poly->GetX(ic2); xf = poly->GetX( ic2 );
yf = poly->GetY(ic2); yf = poly->GetY( ic2 );
if( xf == arc_xf && yf == arc_yf ) if( xf == arc_xf && yf == arc_yf )
{ {
// arc from ic2 to ic // arc from ic2 to ic
...@@ -544,8 +621,9 @@ int CPolyLine::RestoreArcs( std::vector<CArc> * arc_array, std::vector<CPolyLine ...@@ -544,8 +621,9 @@ int CPolyLine::RestoreArcs( std::vector<CArc> * arc_array, std::vector<CPolyLine
if( bFound ) if( bFound )
{ {
poly->side_style[arc_start] = style; poly->side_style[arc_start] = style;
// mark corners for deletion from arc_start+1 to arc_end-1 // mark corners for deletion from arc_start+1 to arc_end-1
for( int i=arc_start+1; i!=arc_end; ) for( int i = arc_start + 1; i!=arc_end; )
{ {
if( i > ic_end ) if( i > ic_end )
i = ic_start; i = ic_start;
...@@ -555,6 +633,7 @@ int CPolyLine::RestoreArcs( std::vector<CArc> * arc_array, std::vector<CPolyLine ...@@ -555,6 +633,7 @@ int CPolyLine::RestoreArcs( std::vector<CArc> * arc_array, std::vector<CPolyLine
else else
i++; i++;
} }
break; break;
} }
} }
...@@ -566,26 +645,29 @@ int CPolyLine::RestoreArcs( std::vector<CArc> * arc_array, std::vector<CPolyLine ...@@ -566,26 +645,29 @@ int CPolyLine::RestoreArcs( std::vector<CArc> * arc_array, std::vector<CPolyLine
break; break;
} }
} }
if( bFound ) if( bFound )
(*arc_array)[iarc].bFound = TRUE; (*arc_array)[iarc].bFound = TRUE;
} }
// now delete all marked corners // now delete all marked corners
for( int ip=0; ip<n_polys; ip++ ) for( int ip = 0; ip<n_polys; ip++ )
{ {
if( ip == 0 ) if( ip == 0 )
poly = this; poly = this;
else else
poly = (*pa)[ip-1]; poly = (*pa)[ip - 1];
for( int ic=poly->GetNumCorners()-1; ic>=0; ic-- ) for( int ic = poly->GetNumCorners() - 1; ic>=0; ic-- )
{ {
if( poly->GetUtility(ic) ) if( poly->GetUtility( ic ) )
poly->DeleteCorner( ic, FALSE ); poly->DeleteCorner( ic, FALSE );
} }
} }
return 0; return 0;
} }
// initialize new polyline // initialize new polyline
// set layer, width, selection box size, starting point, id and pointer // set layer, width, selection box size, starting point, id and pointer
// //
...@@ -610,10 +692,11 @@ void CPolyLine::Start( int layer, int x, int y, int hatch ) ...@@ -610,10 +692,11 @@ void CPolyLine::Start( int layer, int x, int y, int hatch )
CPolyPt poly_pt( x, y ); CPolyPt poly_pt( x, y );
poly_pt.end_contour = FALSE; poly_pt.end_contour = FALSE;
corner.push_back(poly_pt); corner.push_back( poly_pt );
side_style.push_back(0); side_style.push_back( 0 );
} }
// add a corner to unclosed polyline // add a corner to unclosed polyline
// //
void CPolyLine::AppendCorner( int x, int y, int style, bool bDraw ) void CPolyLine::AppendCorner( int x, int y, int style, bool bDraw )
...@@ -623,10 +706,10 @@ void CPolyLine::AppendCorner( int x, int y, int style, bool bDraw ) ...@@ -623,10 +706,10 @@ void CPolyLine::AppendCorner( int x, int y, int style, bool bDraw )
poly_pt.end_contour = FALSE; poly_pt.end_contour = FALSE;
// add entries for new corner and side // add entries for new corner and side
corner.push_back(poly_pt); corner.push_back( poly_pt );
side_style.push_back(style); side_style.push_back( style );
if( corner.size() > 0 && !corner[corner.size()-1].end_contour ) if( corner.size() > 0 && !corner[corner.size() - 1].end_contour )
side_style[corner.size()-1] = style; side_style[corner.size() - 1] = style;
int dl_type; int dl_type;
if( style == CPolyLine::STRAIGHT ) if( style == CPolyLine::STRAIGHT )
dl_type = DL_LINE; dl_type = DL_LINE;
...@@ -635,24 +718,26 @@ void CPolyLine::AppendCorner( int x, int y, int style, bool bDraw ) ...@@ -635,24 +718,26 @@ void CPolyLine::AppendCorner( int x, int y, int style, bool bDraw )
else if( style == CPolyLine::ARC_CCW ) else if( style == CPolyLine::ARC_CCW )
dl_type = DL_ARC_CCW; dl_type = DL_ARC_CCW;
else else
wxASSERT(0); wxASSERT( 0 );
if( bDraw ) if( bDraw )
Draw(); Draw();
} }
// close last polyline contour // close last polyline contour
// //
void CPolyLine::Close( int style, bool bDraw ) void CPolyLine::Close( int style, bool bDraw )
{ {
if( GetClosed() ) if( GetClosed() )
wxASSERT(0); wxASSERT( 0 );
Undraw(); Undraw();
side_style[corner.size()-1] = style; side_style[corner.size() - 1] = style;
corner[corner.size()-1].end_contour = TRUE; corner[corner.size() - 1].end_contour = TRUE;
if( bDraw ) if( bDraw )
Draw(); Draw();
} }
// move corner of polyline // move corner of polyline
// //
void CPolyLine::MoveCorner( int ic, int x, int y ) void CPolyLine::MoveCorner( int ic, int x, int y )
...@@ -663,6 +748,7 @@ void CPolyLine::MoveCorner( int ic, int x, int y ) ...@@ -663,6 +748,7 @@ void CPolyLine::MoveCorner( int ic, int x, int y )
Draw(); Draw();
} }
// delete corner and adjust arrays // delete corner and adjust arrays
// //
void CPolyLine::DeleteCorner( int ic, bool bDraw ) void CPolyLine::DeleteCorner( int ic, bool bDraw )
...@@ -671,7 +757,7 @@ void CPolyLine::DeleteCorner( int ic, bool bDraw ) ...@@ -671,7 +757,7 @@ void CPolyLine::DeleteCorner( int ic, bool bDraw )
int icont = GetContour( ic ); int icont = GetContour( ic );
int istart = GetContourStart( icont ); int istart = GetContourStart( icont );
int iend = GetContourEnd( icont ); int iend = GetContourEnd( icont );
bool bClosed = icont < GetNumContours()-1 || GetClosed(); bool bClosed = icont < GetNumContours() - 1 || GetClosed();
if( !bClosed ) if( !bClosed )
{ {
...@@ -679,7 +765,7 @@ void CPolyLine::DeleteCorner( int ic, bool bDraw ) ...@@ -679,7 +765,7 @@ void CPolyLine::DeleteCorner( int ic, bool bDraw )
corner.erase( corner.begin() + ic ); corner.erase( corner.begin() + ic );
if( ic != istart ) if( ic != istart )
side_style.erase( side_style.begin() + ic-1 ); side_style.erase( side_style.begin() + ic - 1 );
} }
else else
{ {
...@@ -687,9 +773,9 @@ void CPolyLine::DeleteCorner( int ic, bool bDraw ) ...@@ -687,9 +773,9 @@ void CPolyLine::DeleteCorner( int ic, bool bDraw )
corner.erase( corner.begin() + ic ); corner.erase( corner.begin() + ic );
side_style.erase( side_style.begin() + ic ); side_style.erase( side_style.begin() + ic );
if( ic == iend ) if( ic == iend )
corner[ic-1].end_contour = TRUE; corner[ic - 1].end_contour = TRUE;
} }
if( bClosed && GetContourSize(icont) < 3 ) if( bClosed && GetContourSize( icont ) < 3 )
{ {
// delete the entire contour // delete the entire contour
RemoveContour( icont ); RemoveContour( icont );
...@@ -698,9 +784,11 @@ void CPolyLine::DeleteCorner( int ic, bool bDraw ) ...@@ -698,9 +784,11 @@ void CPolyLine::DeleteCorner( int ic, bool bDraw )
Draw(); Draw();
} }
/******************************************/ /******************************************/
void CPolyLine::RemoveContour( int icont ) void CPolyLine::RemoveContour( int icont )
/******************************************/ /******************************************/
/** /**
* Function RemoveContour * Function RemoveContour
* @param icont = contour number to remove * @param icont = contour number to remove
...@@ -714,9 +802,9 @@ void CPolyLine::RemoveContour( int icont ) ...@@ -714,9 +802,9 @@ void CPolyLine::RemoveContour( int icont )
if( icont == 0 && GetNumContours() == 1 ) if( icont == 0 && GetNumContours() == 1 )
{ {
// remove the only contour // remove the only contour
wxASSERT(0); wxASSERT( 0 );
} }
else if( icont == GetNumContours()-1 ) else if( icont == GetNumContours() - 1 )
{ {
// remove last contour // remove last contour
corner.erase( corner.begin() + istart, corner.end() ); corner.erase( corner.begin() + istart, corner.end() );
...@@ -725,7 +813,7 @@ void CPolyLine::RemoveContour( int icont ) ...@@ -725,7 +813,7 @@ void CPolyLine::RemoveContour( int icont )
else else
{ {
// remove closed contour // remove closed contour
for( int ic=iend; ic>=istart; ic-- ) for( int ic = iend; ic>=istart; ic-- )
{ {
corner.erase( corner.begin() + ic ); corner.erase( corner.begin() + ic );
side_style.erase( side_style.begin() + ic ); side_style.erase( side_style.begin() + ic );
...@@ -738,14 +826,15 @@ void CPolyLine::RemoveContour( int icont ) ...@@ -738,14 +826,15 @@ void CPolyLine::RemoveContour( int icont )
/******************************************/ /******************************************/
void CPolyLine::RemoveAllContours( void ) void CPolyLine::RemoveAllContours( void )
/******************************************/ /******************************************/
/** /**
* function RemoveAllContours * function RemoveAllContours
* removes all corners from the lists. * removes all corners from the lists.
* Others params are not chnaged * Others params are not chnaged
*/ */
{ {
corner.clear( ); corner.clear();
side_style.clear( ); side_style.clear();
} }
...@@ -757,28 +846,29 @@ void CPolyLine::RemoveAllContours( void ) ...@@ -757,28 +846,29 @@ void CPolyLine::RemoveAllContours( void )
void CPolyLine::InsertCorner( int ic, int x, int y ) void CPolyLine::InsertCorner( int ic, int x, int y )
{ {
Undraw(); Undraw();
if ( (unsigned)(ic) >= corner.size() ) if( (unsigned) (ic) >= corner.size() )
{ {
corner.push_back( CPolyPt(x,y) ); corner.push_back( CPolyPt( x, y ) );
side_style.push_back( STRAIGHT ); side_style.push_back( STRAIGHT );
} }
else else
{ {
corner.insert( corner.begin() + ic + 1, CPolyPt(x,y) ); corner.insert( corner.begin() + ic + 1, CPolyPt( x, y ) );
side_style.insert( side_style.begin() + ic + 1, STRAIGHT ); side_style.insert( side_style.begin() + ic + 1, STRAIGHT );
} }
if( (unsigned)(ic+1) < corner.size() ) if( (unsigned) (ic + 1) < corner.size() )
{ {
if( corner[ic].end_contour ) if( corner[ic].end_contour )
{ {
corner[ic+1].end_contour = TRUE; corner[ic + 1].end_contour = TRUE;
corner[ic].end_contour = FALSE; corner[ic].end_contour = FALSE;
} }
} }
Draw(); Draw();
} }
// undraw polyline by removing all graphic elements from display list // undraw polyline by removing all graphic elements from display list
// //
void CPolyLine::Undraw() void CPolyLine::Undraw()
...@@ -787,13 +877,13 @@ void CPolyLine::Undraw() ...@@ -787,13 +877,13 @@ void CPolyLine::Undraw()
bDrawn = FALSE; bDrawn = FALSE;
} }
// draw polyline by adding all graphics to display list // draw polyline by adding all graphics to display list
// if side style is ARC_CW or ARC_CCW but endpoints are not angled, // if side style is ARC_CW or ARC_CCW but endpoints are not angled,
// convert to STRAIGHT // convert to STRAIGHT
// //
void CPolyLine::Draw( ) void CPolyLine::Draw()
{ {
// first, undraw if necessary // first, undraw if necessary
if( bDrawn ) if( bDrawn )
Undraw(); Undraw();
...@@ -808,125 +898,146 @@ int CPolyLine::GetX( int ic ) ...@@ -808,125 +898,146 @@ int CPolyLine::GetX( int ic )
return corner[ic].x; return corner[ic].x;
} }
int CPolyLine::GetY( int ic ) int CPolyLine::GetY( int ic )
{ {
return corner[ic].y; return corner[ic].y;
} }
int CPolyLine::GetEndContour( int ic ) int CPolyLine::GetEndContour( int ic )
{ {
return corner[ic].end_contour; return corner[ic].end_contour;
} }
CRect CPolyLine::GetBounds() CRect CPolyLine::GetBounds()
{ {
CRect r = GetCornerBounds(); CRect r = GetCornerBounds();
r.left -= m_Width/2;
r.right += m_Width/2; r.left -= m_Width / 2;
r.bottom -= m_Width/2; r.right += m_Width / 2;
r.top += m_Width/2; r.bottom -= m_Width / 2;
r.top += m_Width / 2;
return r; return r;
} }
CRect CPolyLine::GetCornerBounds() CRect CPolyLine::GetCornerBounds()
{ {
CRect r; CRect r;
r.left = r.bottom = INT_MAX; r.left = r.bottom = INT_MAX;
r.right = r.top = INT_MIN; r.right = r.top = INT_MIN;
for( unsigned i=0; i<corner.size(); i++ ) for( unsigned i = 0; i<corner.size(); i++ )
{ {
r.left = min( r.left, corner[i].x ); r.left = min( r.left, corner[i].x );
r.right = max( r.right, corner[i].x ); r.right = max( r.right, corner[i].x );
r.bottom = min( r.bottom, corner[i].y ); r.bottom = min( r.bottom, corner[i].y );
r.top = max( r.top, corner[i].y ); r.top = max( r.top, corner[i].y );
} }
return r; return r;
} }
CRect CPolyLine::GetCornerBounds( int icont ) CRect CPolyLine::GetCornerBounds( int icont )
{ {
CRect r; CRect r;
r.left = r.bottom = INT_MAX; r.left = r.bottom = INT_MAX;
r.right = r.top = INT_MIN; r.right = r.top = INT_MIN;
int istart = GetContourStart( icont ); int istart = GetContourStart( icont );
int iend = GetContourEnd( icont ); int iend = GetContourEnd( icont );
for( int i=istart; i<=iend; i++ ) for( int i = istart; i<=iend; i++ )
{ {
r.left = min( r.left, corner[i].x ); r.left = min( r.left, corner[i].x );
r.right = max( r.right, corner[i].x ); r.right = max( r.right, corner[i].x );
r.bottom = min( r.bottom, corner[i].y ); r.bottom = min( r.bottom, corner[i].y );
r.top = max( r.top, corner[i].y ); r.top = max( r.top, corner[i].y );
} }
return r; return r;
} }
int CPolyLine::GetNumCorners() int CPolyLine::GetNumCorners()
{ {
return corner.size(); return corner.size();
} }
int CPolyLine::GetNumSides() int CPolyLine::GetNumSides()
{ {
if( GetClosed() ) if( GetClosed() )
return corner.size(); return corner.size();
else else
return corner.size()-1; return corner.size() - 1;
} }
int CPolyLine::GetNumContours() int CPolyLine::GetNumContours()
{ {
int ncont = 0; int ncont = 0;
if( !corner.size() ) if( !corner.size() )
return 0; return 0;
for( unsigned ic=0; ic<corner.size(); ic++ ) for( unsigned ic = 0; ic<corner.size(); ic++ )
if( corner[ic].end_contour ) if( corner[ic].end_contour )
ncont++; ncont++;
if( !corner[corner.size()-1].end_contour )
if( !corner[corner.size() - 1].end_contour )
ncont++; ncont++;
return ncont; return ncont;
} }
int CPolyLine::GetContour( int ic ) int CPolyLine::GetContour( int ic )
{ {
int ncont = 0; int ncont = 0;
for( int i=0; i<ic; i++ )
for( int i = 0; i<ic; i++ )
{ {
if( corner[i].end_contour ) if( corner[i].end_contour )
ncont++; ncont++;
} }
return ncont; return ncont;
} }
int CPolyLine::GetContourStart( int icont ) int CPolyLine::GetContourStart( int icont )
{ {
if( icont == 0 ) if( icont == 0 )
return 0; return 0;
int ncont = 0; int ncont = 0;
for( unsigned i=0; i<corner.size(); i++ ) for( unsigned i = 0; i<corner.size(); i++ )
{ {
if( corner[i].end_contour ) if( corner[i].end_contour )
{ {
ncont++; ncont++;
if( ncont == icont ) if( ncont == icont )
return i+1; return i + 1;
} }
} }
wxASSERT(0);
wxASSERT( 0 );
return 0; return 0;
} }
int CPolyLine::GetContourEnd( int icont ) int CPolyLine::GetContourEnd( int icont )
{ {
if( icont < 0 ) if( icont < 0 )
return 0; return 0;
if( icont == GetNumContours()-1 ) if( icont == GetNumContours() - 1 )
return corner.size()-1; return corner.size() - 1;
int ncont = 0; int ncont = 0;
for( unsigned i=0; i<corner.size(); i++ ) for( unsigned i = 0; i<corner.size(); i++ )
{ {
if( corner[i].end_contour ) if( corner[i].end_contour )
{ {
...@@ -935,13 +1046,15 @@ int CPolyLine::GetContourEnd( int icont ) ...@@ -935,13 +1046,15 @@ int CPolyLine::GetContourEnd( int icont )
ncont++; ncont++;
} }
} }
wxASSERT(0);
wxASSERT( 0 );
return 0; return 0;
} }
int CPolyLine::GetContourSize( int icont ) int CPolyLine::GetContourSize( int icont )
{ {
return GetContourEnd(icont) - GetContourStart(icont) + 1; return GetContourEnd( icont ) - GetContourStart( icont ) + 1;
} }
...@@ -949,10 +1062,10 @@ void CPolyLine::SetSideStyle( int is, int style ) ...@@ -949,10 +1062,10 @@ void CPolyLine::SetSideStyle( int is, int style )
{ {
Undraw(); Undraw();
CPoint p1, p2; CPoint p1, p2;
if( is == (int)(corner.size()-1) ) if( is == (int) (corner.size() - 1) )
{ {
p1.x = corner[corner.size()-1].x; p1.x = corner[corner.size() - 1].x;
p1.y = corner[corner.size()-1].y; p1.y = corner[corner.size() - 1].y;
p2.x = corner[0].x; p2.x = corner[0].x;
p2.y = corner[0].y; p2.y = corner[0].y;
} }
...@@ -960,8 +1073,8 @@ void CPolyLine::SetSideStyle( int is, int style ) ...@@ -960,8 +1073,8 @@ void CPolyLine::SetSideStyle( int is, int style )
{ {
p1.x = corner[is].x; p1.x = corner[is].x;
p1.y = corner[is].y; p1.y = corner[is].y;
p2.x = corner[is+1].x; p2.x = corner[is + 1].x;
p2.y = corner[is+1].y; p2.y = corner[is + 1].y;
} }
if( p1.x == p2.x || p1.y == p2.y ) if( p1.x == p2.x || p1.y == p2.y )
side_style[is] = STRAIGHT; side_style[is] = STRAIGHT;
...@@ -970,6 +1083,7 @@ void CPolyLine::SetSideStyle( int is, int style ) ...@@ -970,6 +1083,7 @@ void CPolyLine::SetSideStyle( int is, int style )
Draw(); Draw();
} }
int CPolyLine::GetSideStyle( int is ) int CPolyLine::GetSideStyle( int is )
{ {
return side_style[is]; return side_style[is];
...@@ -981,9 +1095,10 @@ int CPolyLine::GetClosed() ...@@ -981,9 +1095,10 @@ int CPolyLine::GetClosed()
if( corner.size() == 0 ) if( corner.size() == 0 )
return 0; return 0;
else else
return corner[corner.size()-1].end_contour; return corner[corner.size() - 1].end_contour;
} }
// draw hatch lines // draw hatch lines
// //
void CPolyLine::Hatch() void CPolyLine::Hatch()
...@@ -1019,47 +1134,51 @@ void CPolyLine::Hatch() ...@@ -1019,47 +1134,51 @@ void CPolyLine::Hatch()
if( corner[ic].y > max_y ) if( corner[ic].y > max_y )
max_y = corner[ic].y; max_y = corner[ic].y;
} }
int slope_flag = (layer & 1) ? 1 : -1; // 1 or -1 int slope_flag = (layer & 1) ? 1 : -1; // 1 or -1
double slope = 0.707106*slope_flag; double slope = 0.707106 * slope_flag;
int spacing; int spacing;
if( m_HatchStyle == DIAGONAL_EDGE ) if( m_HatchStyle == DIAGONAL_EDGE )
spacing = 10*PCBU_PER_MIL; spacing = 10 * PCBU_PER_MIL;
else else
spacing = 50*PCBU_PER_MIL; spacing = 50 * PCBU_PER_MIL;
int max_a, min_a; int max_a, min_a;
if( slope_flag == 1 ) if( slope_flag == 1 )
{ {
max_a = (int)(max_y - slope*min_x); max_a = (int) (max_y - slope * min_x);
min_a = (int)(min_y - slope*max_x); min_a = (int) (min_y - slope * max_x);
} }
else else
{ {
max_a = (int)(max_y - slope*max_x); max_a = (int) (max_y - slope * max_x);
min_a = (int)(min_y - slope*min_x); min_a = (int) (min_y - slope * min_x);
} }
min_a = (min_a/spacing)*spacing; min_a = (min_a / spacing) * spacing;
// calculate an offset depending on layer number, for a better display of hatches on a multilayer board // calculate an offset depending on layer number, for a better display of hatches on a multilayer board
int offset = (layer * 7) / 8; int offset = (layer * 7) / 8;
min_a += offset; min_a += offset;
// now calculate and draw hatch lines // now calculate and draw hatch lines
int nc = corner.size(); int nc = corner.size();
// loop through hatch lines // loop through hatch lines
for( int a=min_a; a<max_a; a+=spacing ) for( int a = min_a; a<max_a; a += spacing )
{ {
// get intersection points for this hatch line // get intersection points for this hatch line
int nloops = 0; int nloops = 0;
int npts; int npts;
// make this a loop in case my homebrew hatching algorithm screws up // make this a loop in case my homebrew hatching algorithm screws up
do do
{ {
npts = 0; npts = 0;
int i_start_contour = 0; int i_start_contour = 0;
for( int ic=0; ic<nc; ic++ ) for( int ic = 0; ic<nc; ic++ )
{ {
double x, y, x2, y2; double x, y, x2, y2;
int ok; int ok;
if( corner[ic].end_contour || (ic == (int)(corner.size()-1)) ) if( corner[ic].end_contour || ( ic == (int) (corner.size() - 1) ) )
{ {
ok = FindLineSegmentIntersection( a, slope, ok = FindLineSegmentIntersection( a, slope,
corner[ic].x, corner[ic].y, corner[ic].x, corner[ic].y,
...@@ -1072,42 +1191,43 @@ void CPolyLine::Hatch() ...@@ -1072,42 +1191,43 @@ void CPolyLine::Hatch()
{ {
ok = FindLineSegmentIntersection( a, slope, ok = FindLineSegmentIntersection( a, slope,
corner[ic].x, corner[ic].y, corner[ic].x, corner[ic].y,
corner[ic+1].x, corner[ic+1].y, corner[ic + 1].x, corner[ic + 1].y,
side_style[ic], side_style[ic],
&x, &y, &x2, &y2 ); &x, &y, &x2, &y2 );
} }
if( ok ) if( ok )
{ {
xx[npts] = (int)x; xx[npts] = (int) x;
yy[npts] = (int)y; yy[npts] = (int) y;
npts++; npts++;
wxASSERT( npts<MAXPTS ); // overflow wxASSERT( npts<MAXPTS ); // overflow
} }
if( ok == 2 ) if( ok == 2 )
{ {
xx[npts] = (int)x2; xx[npts] = (int) x2;
yy[npts] = (int)y2; yy[npts] = (int) y2;
npts++; npts++;
wxASSERT( npts<MAXPTS ); // overflow wxASSERT( npts<MAXPTS ); // overflow
} }
} }
nloops++; nloops++;
a += PCBU_PER_MIL/100; a += PCBU_PER_MIL / 100;
} while( npts%2 != 0 && nloops < 3 ); } while( npts % 2 != 0 && nloops < 3 );
/* DICK 1/22/08: this was firing repeatedly on me, needed to comment out to get /* DICK 1/22/08: this was firing repeatedly on me, needed to comment out to get
my work done: * my work done:
wxASSERT( npts%2==0 ); // odd number of intersection points, error * wxASSERT( npts%2==0 ); // odd number of intersection points, error
*/ */
// sort points in order of descending x (if more than 2) // sort points in order of descending x (if more than 2)
if( npts>2 ) if( npts>2 )
{ {
for( int istart=0; istart<(npts-1); istart++ ) for( int istart = 0; istart<(npts - 1); istart++ )
{ {
int max_x = INT_MIN; int max_x = INT_MIN;
int imax = INT_MIN; int imax = INT_MIN;
for( int i=istart; i<npts; i++ ) for( int i = istart; i<npts; i++ )
{ {
if( xx[i] > max_x ) if( xx[i] > max_x )
{ {
...@@ -1115,6 +1235,7 @@ void CPolyLine::Hatch() ...@@ -1115,6 +1235,7 @@ void CPolyLine::Hatch()
imax = i; imax = i;
} }
} }
int temp = xx[istart]; int temp = xx[istart];
xx[istart] = xx[imax]; xx[istart] = xx[imax];
xx[imax] = temp; xx[imax] = temp;
...@@ -1125,58 +1246,64 @@ void CPolyLine::Hatch() ...@@ -1125,58 +1246,64 @@ void CPolyLine::Hatch()
} }
// draw lines // draw lines
for( int ip=0; ip<npts; ip+=2 ) for( int ip = 0; ip<npts; ip += 2 )
{ {
double dx = xx[ip+1] - xx[ip]; double dx = xx[ip + 1] - xx[ip];
if( m_HatchStyle == DIAGONAL_FULL || fabs(dx) < 40*NM_PER_MIL ) if( m_HatchStyle == DIAGONAL_FULL || fabs( dx ) < 40 * NM_PER_MIL )
{ {
m_HatchLines.push_back(CSegment(xx[ip], yy[ip], xx[ip+1], yy[ip+1]) ); m_HatchLines.push_back( CSegment( xx[ip], yy[ip], xx[ip + 1], yy[ip + 1] ) );
} }
else else
{ {
double dy = yy[ip+1] - yy[ip]; double dy = yy[ip + 1] - yy[ip];
double slope = dy/dx; double slope = dy / dx;
if( dx > 0 ) if( dx > 0 )
dx = 20*NM_PER_MIL; dx = 20 * NM_PER_MIL;
else else
dx = -20*NM_PER_MIL; dx = -20 * NM_PER_MIL;
double x1 = xx[ip] + dx; double x1 = xx[ip] + dx;
double x2 = xx[ip+1] - dx; double x2 = xx[ip + 1] - dx;
double y1 = yy[ip] + dx*slope; double y1 = yy[ip] + dx * slope;
double y2 = yy[ip+1] - dx*slope; double y2 = yy[ip + 1] - dx * slope;
m_HatchLines.push_back(CSegment(xx[ip], yy[ip], to_int(x1), to_int(y1)) ); m_HatchLines.push_back( CSegment( xx[ip], yy[ip], to_int( x1 ), to_int( y1 ) ) );
m_HatchLines.push_back(CSegment(xx[ip+1], yy[ip+1], to_int(x2), to_int(y2)) ); m_HatchLines.push_back( CSegment( xx[ip + 1], yy[ip + 1], to_int( x2 ),
to_int( y2 ) ) );
} }
} }
} // end for } // end for
} }
} }
// test to see if a point is inside polyline // test to see if a point is inside polyline
// //
bool CPolyLine::TestPointInside( int x, int y ) bool CPolyLine::TestPointInside( int x, int y )
{ {
enum { MAXPTS = 100 }; enum {
MAXPTS = 100
};
if( !GetClosed() ) if( !GetClosed() )
wxASSERT(0); wxASSERT( 0 );
// define line passing through (x,y), with slope = 2/3; // define line passing through (x,y), with slope = 2/3;
// get intersection points // get intersection points
double xx[MAXPTS], yy[MAXPTS]; double xx[MAXPTS], yy[MAXPTS];
double slope = (double)2.0/3.0; double slope = (double) 2.0 / 3.0;
double a = y - slope*x; double a = y - slope * x;
int nloops = 0; int nloops = 0;
int npts; int npts;
// make this a loop so if my homebrew algorithm screws up, we try it again // make this a loop so if my homebrew algorithm screws up, we try it again
do do
{ {
// now find all intersection points of line with polyline sides // now find all intersection points of line with polyline sides
npts = 0; npts = 0;
for( int icont=0; icont<GetNumContours(); icont++ ) for( int icont = 0; icont<GetNumContours(); icont++ )
{ {
int istart = GetContourStart( icont ); int istart = GetContourStart( icont );
int iend = GetContourEnd( icont ); int iend = GetContourEnd( icont );
for( int ic=istart; ic<=iend; ic++ ) for( int ic = istart; ic<=iend; ic++ )
{ {
double x, y, x2, y2; double x, y, x2, y2;
int ok; int ok;
...@@ -1184,50 +1311,54 @@ bool CPolyLine::TestPointInside( int x, int y ) ...@@ -1184,50 +1311,54 @@ bool CPolyLine::TestPointInside( int x, int y )
ok = FindLineSegmentIntersection( a, slope, ok = FindLineSegmentIntersection( a, slope,
corner[iend].x, corner[iend].y, corner[iend].x, corner[iend].y,
corner[istart].x, corner[istart].y, corner[istart].x, corner[istart].y,
side_style[corner.size()-1], side_style[corner.size() - 1],
&x, &y, &x2, &y2 ); &x, &y, &x2, &y2 );
else else
ok = FindLineSegmentIntersection( a, slope, ok = FindLineSegmentIntersection( a, slope,
corner[ic-1].x, corner[ic-1].y, corner[ic - 1].x, corner[ic - 1].y,
corner[ic].x, corner[ic].y, corner[ic].x, corner[ic].y,
side_style[ic-1], side_style[ic - 1],
&x, &y, &x2, &y2 ); &x, &y, &x2, &y2 );
if( ok ) if( ok )
{ {
xx[npts] = (int)x; xx[npts] = (int) x;
yy[npts] = (int)y; yy[npts] = (int) y;
npts++; npts++;
wxASSERT( npts<MAXPTS ); // overflow wxASSERT( npts<MAXPTS ); // overflow
} }
if( ok == 2 ) if( ok == 2 )
{ {
xx[npts] = (int)x2; xx[npts] = (int) x2;
yy[npts] = (int)y2; yy[npts] = (int) y2;
npts++; npts++;
wxASSERT( npts<MAXPTS ); // overflow wxASSERT( npts<MAXPTS ); // overflow
} }
} }
} }
nloops++; nloops++;
a += PCBU_PER_MIL/100; a += PCBU_PER_MIL / 100;
} while( npts%2 != 0 && nloops < 3 ); } while( npts % 2 != 0 && nloops < 3 );
wxASSERT( npts%2==0 ); // odd number of intersection points, error
wxASSERT( npts % 2==0 ); // odd number of intersection points, error
// count intersection points to right of (x,y), if odd (x,y) is inside polyline // count intersection points to right of (x,y), if odd (x,y) is inside polyline
int ncount = 0; int ncount = 0;
for( int ip=0; ip<npts; ip++ ) for( int ip = 0; ip<npts; ip++ )
{ {
if( xx[ip] == x && yy[ip] == y ) if( xx[ip] == x && yy[ip] == y )
return FALSE; // (x,y) is on a side, call it outside return FALSE; // (x,y) is on a side, call it outside
else if( xx[ip] > x ) else if( xx[ip] > x )
ncount++; ncount++;
} }
if( ncount%2 )
if( ncount % 2 )
return TRUE; return TRUE;
else else
return FALSE; return FALSE;
} }
// test to see if a point is inside polyline contour // test to see if a point is inside polyline contour
// //
bool CPolyLine::TestPointInsideContour( int icont, int x, int y ) bool CPolyLine::TestPointInsideContour( int icont, int x, int y )
...@@ -1235,17 +1366,20 @@ bool CPolyLine::TestPointInsideContour( int icont, int x, int y ) ...@@ -1235,17 +1366,20 @@ bool CPolyLine::TestPointInsideContour( int icont, int x, int y )
if( icont >= GetNumContours() ) if( icont >= GetNumContours() )
return FALSE; return FALSE;
enum { MAXPTS = 100 }; enum {
MAXPTS = 100
};
if( !GetClosed() ) if( !GetClosed() )
wxASSERT(0); wxASSERT( 0 );
// define line passing through (x,y), with slope = 2/3; // define line passing through (x,y), with slope = 2/3;
// get intersection points // get intersection points
double xx[MAXPTS], yy[MAXPTS]; double xx[MAXPTS], yy[MAXPTS];
double slope = (double)2.0/3.0; double slope = (double) 2.0 / 3.0;
double a = y - slope*x; double a = y - slope * x;
int nloops = 0; int nloops = 0;
int npts; int npts;
// make this a loop so if my homebrew algorithm screws up, we try it again // make this a loop so if my homebrew algorithm screws up, we try it again
do do
{ {
...@@ -1253,7 +1387,7 @@ bool CPolyLine::TestPointInsideContour( int icont, int x, int y ) ...@@ -1253,7 +1387,7 @@ bool CPolyLine::TestPointInsideContour( int icont, int x, int y )
npts = 0; npts = 0;
int istart = GetContourStart( icont ); int istart = GetContourStart( icont );
int iend = GetContourEnd( icont ); int iend = GetContourEnd( icont );
for( int ic=istart; ic<=iend; ic++ ) for( int ic = istart; ic<=iend; ic++ )
{ {
double x, y, x2, y2; double x, y, x2, y2;
int ok; int ok;
...@@ -1261,44 +1395,47 @@ bool CPolyLine::TestPointInsideContour( int icont, int x, int y ) ...@@ -1261,44 +1395,47 @@ bool CPolyLine::TestPointInsideContour( int icont, int x, int y )
ok = FindLineSegmentIntersection( a, slope, ok = FindLineSegmentIntersection( a, slope,
corner[iend].x, corner[iend].y, corner[iend].x, corner[iend].y,
corner[istart].x, corner[istart].y, corner[istart].x, corner[istart].y,
side_style[corner.size()-1], side_style[corner.size() - 1],
&x, &y, &x2, &y2 ); &x, &y, &x2, &y2 );
else else
ok = FindLineSegmentIntersection( a, slope, ok = FindLineSegmentIntersection( a, slope,
corner[ic-1].x, corner[ic-1].y, corner[ic - 1].x, corner[ic - 1].y,
corner[ic].x, corner[ic].y, corner[ic].x, corner[ic].y,
side_style[ic-1], side_style[ic - 1],
&x, &y, &x2, &y2 ); &x, &y, &x2, &y2 );
if( ok ) if( ok )
{ {
xx[npts] = (int)x; xx[npts] = (int) x;
yy[npts] = (int)y; yy[npts] = (int) y;
npts++; npts++;
wxASSERT( npts<MAXPTS ); // overflow wxASSERT( npts<MAXPTS ); // overflow
} }
if( ok == 2 ) if( ok == 2 )
{ {
xx[npts] = (int)x2; xx[npts] = (int) x2;
yy[npts] = (int)y2; yy[npts] = (int) y2;
npts++; npts++;
wxASSERT( npts<MAXPTS ); // overflow wxASSERT( npts<MAXPTS ); // overflow
} }
} }
nloops++; nloops++;
a += PCBU_PER_MIL/100; a += PCBU_PER_MIL / 100;
} while( npts%2 != 0 && nloops < 3 ); } while( npts % 2 != 0 && nloops < 3 );
wxASSERT( npts%2==0 ); // odd number of intersection points, error
wxASSERT( npts % 2==0 ); // odd number of intersection points, error
// count intersection points to right of (x,y), if odd (x,y) is inside polyline // count intersection points to right of (x,y), if odd (x,y) is inside polyline
int ncount = 0; int ncount = 0;
for( int ip=0; ip<npts; ip++ ) for( int ip = 0; ip<npts; ip++ )
{ {
if( xx[ip] == x && yy[ip] == y ) if( xx[ip] == x && yy[ip] == y )
return FALSE; // (x,y) is on a side, call it outside return FALSE; // (x,y) is on a side, call it outside
else if( xx[ip] > x ) else if( xx[ip] > x )
ncount++; ncount++;
} }
if( ncount%2 )
if( ncount % 2 )
return TRUE; return TRUE;
else else
return FALSE; return FALSE;
...@@ -1307,42 +1444,51 @@ bool CPolyLine::TestPointInsideContour( int icont, int x, int y ) ...@@ -1307,42 +1444,51 @@ bool CPolyLine::TestPointInsideContour( int icont, int x, int y )
// copy data from another poly, but don't draw it // copy data from another poly, but don't draw it
// //
void CPolyLine::Copy( CPolyLine * src ) void CPolyLine::Copy( CPolyLine* src )
{ {
Undraw(); Undraw();
// copy corners // copy corners
for( unsigned ii=0; ii < src->corner.size(); ii++ ) for( unsigned ii = 0; ii < src->corner.size(); ii++ )
corner.push_back(src->corner[ii]); corner.push_back( src->corner[ii] );
// copy side styles // copy side styles
for( unsigned ii=0; ii < src->side_style.size(); ii++ ) for( unsigned ii = 0; ii < src->side_style.size(); ii++ )
side_style.push_back(src->side_style[ii]); side_style.push_back( src->side_style[ii] );
#ifdef USE_GPC_POLY_LIB
// don't copy the Gpc_poly, just clear the old one // don't copy the Gpc_poly, just clear the old one
FreeGpcPoly(); FreeGpcPoly();
#endif
} }
/*******************************************/ /*******************************************/
bool CPolyLine::IsCutoutContour( int icont ) bool CPolyLine::IsCutoutContour( int icont )
/*******************************************/ /*******************************************/
/* /*
* return true if the corner icont is inside the outline (i.e it is a hole) * return true if the corner icont is inside the outline (i.e it is a hole)
*/ */
{ {
int ncont = GetContour( icont ); int ncont = GetContour( icont );
if ( ncont == 0 ) // the first contour is the main outline, not an hole
if( ncont == 0 ) // the first contour is the main outline, not an hole
return false; return false;
return true; return true;
} }
void CPolyLine::MoveOrigin( int x_off, int y_off ) void CPolyLine::MoveOrigin( int x_off, int y_off )
{ {
Undraw(); Undraw();
for( int ic=0; ic < GetNumCorners(); ic++ ) for( int ic = 0; ic < GetNumCorners(); ic++ )
{ {
SetX( ic, GetX(ic) + x_off ); SetX( ic, GetX( ic ) + x_off );
SetY( ic, GetY(ic) + y_off ); SetY( ic, GetY( ic ) + y_off );
} }
Draw(); Draw();
} }
...@@ -1351,54 +1497,76 @@ void CPolyLine::MoveOrigin( int x_off, int y_off ) ...@@ -1351,54 +1497,76 @@ void CPolyLine::MoveOrigin( int x_off, int y_off )
// the calling function should Undraw() before calling them, // the calling function should Undraw() before calling them,
// and Draw() after // and Draw() after
// //
void CPolyLine::SetX( int ic, int x ) { corner[ic].x = x; } void CPolyLine::SetX( int ic, int x )
void CPolyLine::SetY( int ic, int y ) { corner[ic].y = y; } {
corner[ic].x = x;
}
void CPolyLine::SetY( int ic, int y )
{
corner[ic].y = y;
}
void CPolyLine::SetEndContour( int ic, bool end_contour ) void CPolyLine::SetEndContour( int ic, bool end_contour )
{ {
corner[ic].end_contour = end_contour; corner[ic].end_contour = end_contour;
} }
// Create CPolyLine for a pad // Create CPolyLine for a pad
// //
CPolyLine * CPolyLine::MakePolylineForPad( int type, int x, int y, int w, int l, int r, int angle ) CPolyLine* CPolyLine::MakePolylineForPad( int type, int x, int y, int w, int l, int r, int angle )
{ {
CPolyLine * poly = new CPolyLine; CPolyLine* poly = new CPolyLine;
int dx = l/2; int dx = l / 2;
int dy = w/2; int dy = w / 2;
if( angle%180 == 90 )
if( angle % 180 == 90 )
{ {
dx = w/2; dx = w / 2;
dy = l/2; dy = l / 2;
} }
if( type == PAD_ROUND ) if( type == PAD_ROUND )
{ {
poly->Start( 0, x-dx, y, 0 ); poly->Start( 0, x - dx, y, 0 );
poly->AppendCorner( x, y+dy, ARC_CW, 0 ); poly->AppendCorner( x, y + dy, ARC_CW, 0 );
poly->AppendCorner( x+dx, y, ARC_CW, 0 ); poly->AppendCorner( x + dx, y, ARC_CW, 0 );
poly->AppendCorner( x, y-dy, ARC_CW, 0 ); poly->AppendCorner( x, y - dy, ARC_CW, 0 );
poly->Close( ARC_CW ); poly->Close( ARC_CW );
} }
return poly; return poly;
} }
// Add cutout for a pad // Add cutout for a pad
// Convert arcs to multiple straight lines // Convert arcs to multiple straight lines
// Do NOT draw or undraw // Do NOT draw or undraw
// //
void CPolyLine::AddContourForPadClearance( int type, int x, int y, int w, void CPolyLine::AddContourForPadClearance( int type,
int l, int r, int angle, int fill_clearance, int x,
int hole_w, int hole_clearance, bool bThermal, int spoke_w ) int y,
int w,
int l,
int r,
int angle,
int fill_clearance,
int hole_w,
int hole_clearance,
bool bThermal,
int spoke_w )
{ {
int dx = l/2; int dx = l / 2;
int dy = w/2; int dy = w / 2;
if( angle%180 == 90 )
if( angle % 180 == 90 )
{ {
dx = w/2; dx = w / 2;
dy = l/2; dy = l / 2;
} }
int x_clearance = max( fill_clearance, hole_clearance+hole_w/2-dx); int x_clearance = max( fill_clearance, hole_clearance + hole_w / 2 - dx );
int y_clearance = max( fill_clearance, hole_clearance+hole_w/2-dy); int y_clearance = max( fill_clearance, hole_clearance + hole_w / 2 - dy );
dx += x_clearance; dx += x_clearance;
dy += y_clearance; dy += y_clearance;
if( !bThermal ) if( !bThermal )
...@@ -1406,19 +1574,19 @@ void CPolyLine::AddContourForPadClearance( int type, int x, int y, int w, ...@@ -1406,19 +1574,19 @@ void CPolyLine::AddContourForPadClearance( int type, int x, int y, int w,
// normal clearance // normal clearance
if( type == PAD_ROUND || (type == PAD_NONE && hole_w > 0) ) if( type == PAD_ROUND || (type == PAD_NONE && hole_w > 0) )
{ {
AppendCorner( x-dx, y, ARC_CW, 0 ); AppendCorner( x - dx, y, ARC_CW, 0 );
AppendCorner( x, y+dy, ARC_CW, 0 ); AppendCorner( x, y + dy, ARC_CW, 0 );
AppendCorner( x+dx, y, ARC_CW, 0 ); AppendCorner( x + dx, y, ARC_CW, 0 );
AppendCorner( x, y-dy, ARC_CW, 0 ); AppendCorner( x, y - dy, ARC_CW, 0 );
Close( ARC_CW ); Close( ARC_CW );
} }
else if( type == PAD_SQUARE || type == PAD_RECT else if( type == PAD_SQUARE || type == PAD_RECT
|| type == PAD_RRECT || type == PAD_OVAL ) || type == PAD_RRECT || type == PAD_OVAL )
{ {
AppendCorner( x-dx, y-dy, STRAIGHT, 0 ); AppendCorner( x - dx, y - dy, STRAIGHT, 0 );
AppendCorner( x+dx, y-dy, STRAIGHT, 0 ); AppendCorner( x + dx, y - dy, STRAIGHT, 0 );
AppendCorner( x+dx, y+dy, STRAIGHT, 0 ); AppendCorner( x + dx, y + dy, STRAIGHT, 0 );
AppendCorner( x-dx, y+dy, STRAIGHT, 0 ); AppendCorner( x - dx, y + dy, STRAIGHT, 0 );
Close( STRAIGHT ); Close( STRAIGHT );
} }
} }
...@@ -1428,43 +1596,45 @@ void CPolyLine::AddContourForPadClearance( int type, int x, int y, int w, ...@@ -1428,43 +1596,45 @@ void CPolyLine::AddContourForPadClearance( int type, int x, int y, int w,
if( type == PAD_ROUND || (type == PAD_NONE && hole_w > 0) ) if( type == PAD_ROUND || (type == PAD_NONE && hole_w > 0) )
{ {
// draw 4 "wedges" // draw 4 "wedges"
double r = max(w/2 + fill_clearance, hole_w/2 + hole_clearance); double r = max( w / 2 + fill_clearance, hole_w / 2 + hole_clearance );
double start_angle = asin( spoke_w/(2.0*r) ); double start_angle = asin( spoke_w / (2.0 * r) );
double th1, th2, corner_x, corner_y; double th1, th2, corner_x, corner_y;
th1 = th2 = corner_x = corner_y = 0; // gcc warning fix th1 = th2 = corner_x = corner_y = 0; // gcc warning fix
for( int i=0; i<4; i++ ) for( int i = 0; i<4; i++ )
{ {
if( i == 0 ) if( i == 0 )
{ {
corner_x = spoke_w/2; corner_x = spoke_w / 2;
corner_y = spoke_w/2; corner_y = spoke_w / 2;
th1 = start_angle; th1 = start_angle;
th2 = pi/2.0 - start_angle; th2 = pi / 2.0 - start_angle;
} }
else if( i == 1 ) else if( i == 1 )
{ {
corner_x = -spoke_w/2; corner_x = -spoke_w / 2;
corner_y = spoke_w/2; corner_y = spoke_w / 2;
th1 = pi/2.0 + start_angle; th1 = pi / 2.0 + start_angle;
th2 = pi - start_angle; th2 = pi - start_angle;
} }
else if( i == 2 ) else if( i == 2 )
{ {
corner_x = -spoke_w/2; corner_x = -spoke_w / 2;
corner_y = -spoke_w/2; corner_y = -spoke_w / 2;
th1 = -pi + start_angle; th1 = -pi + start_angle;
th2 = -pi/2.0 - start_angle; th2 = -pi / 2.0 - start_angle;
} }
else if( i == 3 ) else if( i == 3 )
{ {
corner_x = spoke_w/2; corner_x = spoke_w / 2;
corner_y = -spoke_w/2; corner_y = -spoke_w / 2;
th1 = -pi/2.0 + start_angle; th1 = -pi / 2.0 + start_angle;
th2 = -start_angle; th2 = -start_angle;
} }
AppendCorner( to_int(x+corner_x), to_int(y+corner_y), STRAIGHT, 0 ); AppendCorner( to_int( x + corner_x ), to_int( y + corner_y ), STRAIGHT, 0 );
AppendCorner( to_int(x+r*cos(th1)), to_int(y+r*sin(th1)), STRAIGHT, 0 ); AppendCorner( to_int( x + r * cos( th1 ) ), to_int( y + r * sin(
AppendCorner( to_int(x+r*cos(th2)), to_int(y+r*sin(th2)), ARC_CCW, 0 ); th1 ) ), STRAIGHT, 0 );
AppendCorner( to_int( x + r * cos( th2 ) ), to_int( y + r * sin(
th2 ) ), ARC_CCW, 0 );
Close( STRAIGHT ); Close( STRAIGHT );
} }
} }
...@@ -1473,15 +1643,15 @@ void CPolyLine::AddContourForPadClearance( int type, int x, int y, int w, ...@@ -1473,15 +1643,15 @@ void CPolyLine::AddContourForPadClearance( int type, int x, int y, int w,
{ {
// draw 4 rectangles // draw 4 rectangles
int xL = x - dx; int xL = x - dx;
int xR = x - spoke_w/2; int xR = x - spoke_w / 2;
int yB = y - dy; int yB = y - dy;
int yT = y - spoke_w/2; int yT = y - spoke_w / 2;
AppendCorner( xL, yB, STRAIGHT, 0 ); AppendCorner( xL, yB, STRAIGHT, 0 );
AppendCorner( xR, yB, STRAIGHT, 0 ); AppendCorner( xR, yB, STRAIGHT, 0 );
AppendCorner( xR, yT, STRAIGHT, 0 ); AppendCorner( xR, yT, STRAIGHT, 0 );
AppendCorner( xL, yT, STRAIGHT, 0 ); AppendCorner( xL, yT, STRAIGHT, 0 );
Close( STRAIGHT ); Close( STRAIGHT );
xL = x + spoke_w/2; xL = x + spoke_w / 2;
xR = x + dx; xR = x + dx;
AppendCorner( xL, yB, STRAIGHT, 0 ); AppendCorner( xL, yB, STRAIGHT, 0 );
AppendCorner( xR, yB, STRAIGHT, 0 ); AppendCorner( xR, yB, STRAIGHT, 0 );
...@@ -1489,15 +1659,15 @@ void CPolyLine::AddContourForPadClearance( int type, int x, int y, int w, ...@@ -1489,15 +1659,15 @@ void CPolyLine::AddContourForPadClearance( int type, int x, int y, int w,
AppendCorner( xL, yT, STRAIGHT, 0 ); AppendCorner( xL, yT, STRAIGHT, 0 );
Close( STRAIGHT ); Close( STRAIGHT );
xL = x - dx; xL = x - dx;
xR = x - spoke_w/2; xR = x - spoke_w / 2;
yB = y + spoke_w/2; yB = y + spoke_w / 2;
yT = y + dy; yT = y + dy;
AppendCorner( xL, yB, STRAIGHT, 0 ); AppendCorner( xL, yB, STRAIGHT, 0 );
AppendCorner( xR, yB, STRAIGHT, 0 ); AppendCorner( xR, yB, STRAIGHT, 0 );
AppendCorner( xR, yT, STRAIGHT, 0 ); AppendCorner( xR, yT, STRAIGHT, 0 );
AppendCorner( xL, yT, STRAIGHT, 0 ); AppendCorner( xL, yT, STRAIGHT, 0 );
Close( STRAIGHT ); Close( STRAIGHT );
xL = x + spoke_w/2; xL = x + spoke_w / 2;
xR = x + dx; xR = x + dx;
AppendCorner( xL, yB, STRAIGHT, 0 ); AppendCorner( xL, yB, STRAIGHT, 0 );
AppendCorner( xR, yB, STRAIGHT, 0 ); AppendCorner( xR, yB, STRAIGHT, 0 );
...@@ -1509,33 +1679,26 @@ void CPolyLine::AddContourForPadClearance( int type, int x, int y, int w, ...@@ -1509,33 +1679,26 @@ void CPolyLine::AddContourForPadClearance( int type, int x, int y, int w,
return; return;
} }
void CPolyLine::AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num ) void CPolyLine::AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num )
{ {
// get radius // get radius
double r = sqrt( (double)(xi-xc)*(xi-xc) + (double)(yi-yc)*(yi-yc) ); double r = sqrt( (double) (xi - xc) * (xi - xc) + (double) (yi - yc) * (yi - yc) );
// get angles of start and finish // get angles of start and finish
double th_i = atan2( (double)yi-yc, (double)xi-xc ); double th_i = atan2( (double) yi - yc, (double) xi - xc );
double th_f = atan2( (double)yf-yc, (double)xf-xc ); double th_f = atan2( (double) yf - yc, (double) xf - xc );
double th_d = (th_f - th_i)/(num-1); double th_d = (th_f - th_i) / (num - 1);
double theta = th_i; double theta = th_i;
// generate arc // generate arc
for( int ic=0; ic<num; ic++ ) for( int ic = 0; ic<num; ic++ )
{ {
int x = to_int(xc + r*cos(theta)); int x = to_int( xc + r * cos( theta ) );
int y = to_int(yc + r*sin(theta)); int y = to_int( yc + r * sin( theta ) );
AppendCorner( x, y, STRAIGHT, 0 ); AppendCorner( x, y, STRAIGHT, 0 );
theta += th_d; theta += th_d;
} }
Close( STRAIGHT );
}
void CPolyLine::ClipGpcPolygon( gpc_op op, CPolyLine * clip_poly ) Close( STRAIGHT );
{
gpc_polygon * result = new gpc_polygon;
gpc_polygon_clip( op, m_gpc_poly, clip_poly->GetGpcPoly(), result );
gpc_free_polygon( m_gpc_poly );
delete m_gpc_poly;
m_gpc_poly = result;
} }
...@@ -16,6 +16,9 @@ ...@@ -16,6 +16,9 @@
#include <vector> #include <vector>
#define USE_GPC_POLY_LIB
//#define USE_GPL_POLY_LIB
#include "defs-macros.h" #include "defs-macros.h"
#include "GenericPolygonClipperLibrary.h" #include "GenericPolygonClipperLibrary.h"
...@@ -117,22 +120,32 @@ public: ...@@ -117,22 +120,32 @@ public:
void SetEndContour( int ic, bool end_contour ); void SetEndContour( int ic, bool end_contour );
void SetSideStyle( int is, int style ); void SetSideStyle( int is, int style );
// GPC functions
int MakeGpcPoly( int icontour=0, std::vector<CArc> * arc_array=NULL );
int FreeGpcPoly();
gpc_polygon * GetGpcPoly(){ return m_gpc_poly; };
int NormalizeWithGpc( std::vector<CPolyLine*> * pa=NULL, bool bRetainArcs=FALSE );
int RestoreArcs( std::vector<CArc> * arc_array, std::vector<CPolyLine*> * pa=NULL ); int RestoreArcs( std::vector<CArc> * arc_array, std::vector<CPolyLine*> * pa=NULL );
CPolyLine * MakePolylineForPad( int type, int x, int y, int w, int l, int r, int angle ); CPolyLine * MakePolylineForPad( int type, int x, int y, int w, int l, int r, int angle );
void AddContourForPadClearance( int type, int x, int y, int w, void AddContourForPadClearance( int type, int x, int y, int w,
int l, int r, int angle, int fill_clearance, int l, int r, int angle, int fill_clearance,
int hole_w, int hole_clearance, bool bThermal=FALSE, int spoke_w=0 ); int hole_w, int hole_clearance, bool bThermal=FALSE, int spoke_w=0 );
void ClipGpcPolygon( gpc_op op, CPolyLine * poly );
int MakePolygonFromAreaOutlines( int icontour, std::vector<CArc> * arc_array );
void FreePolygon();
int NormalizeAreaOutlines( std::vector<CPolyLine*> * pa=NULL, bool bRetainArcs=FALSE );
#ifdef USE_GPC_POLY_LIB
// GPC functions
int MakeGpcPoly( int icontour=0, std::vector<CArc> * arc_array=NULL );
void FreeGpcPoly();
gpc_polygon * GetGpcPoly(){ return m_gpc_poly; };
int NormalizeWithGpc( std::vector<CPolyLine*> * pa=NULL, bool bRetainArcs=FALSE );
#endif
// PHP functions // PHP functions
#ifdef USE_GPL_POLY_LIB
int MakePhpPoly(); int MakePhpPoly();
void FreePhpPoly(); void FreePhpPoly();
void ClipPhpPolygon( int php_op, CPolyLine * poly ); void ClipPhpPolygon( int php_op, CPolyLine * poly );
polygon * GetPhpPoly(){ return m_php_poly; };
#endif
private: private:
int m_layer; // layer to draw on int m_layer; // layer to draw on
......
// file php_polygon.cpp // file php_polygon.cpp
// This is a port of a php class written by Brenor Brophy (see below) // This is a port of a php class written by Brenor Brophy (see below)
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
...@@ -44,6 +45,7 @@ ...@@ -44,6 +45,7 @@
** 1.1 09/04/2005 Added Move(), Rotate(), isPolyInside() and bRect() methods. ** 1.1 09/04/2005 Added Move(), Rotate(), isPolyInside() and bRect() methods.
** Added software license language to header comments ** Added software license language to header comments
*/ */
//#include "stdafx.h" //#include "stdafx.h"
#include <stdio.h> #include <stdio.h>
...@@ -57,99 +59,109 @@ ...@@ -57,99 +59,109 @@
#include "php_polygon.h" #include "php_polygon.h"
const double PT = 0.99999; const double PT = 0.99999;
//const double eps = (1.0 - PT)/10.0; //const double eps = (1.0 - PT)/10.0;
const double eps = 0.0; const double eps = 0.0;
polygon::polygon( vertex * first ) polygon::polygon( vertex* first )
{ {
m_first = first; m_first = first;
m_cnt = 0; m_cnt = 0;
} }
polygon::~polygon() polygon::~polygon()
{ {
while( m_cnt > 1 ) while( m_cnt > 1 )
{ {
vertex * v = getFirst(); vertex* v = getFirst();
del( v->m_nextV ); del( v->m_nextV );
} }
if( m_first ) if( m_first )
{ {
delete m_first; delete m_first;
} }
} }
vertex * polygon::getFirst()
vertex* polygon::getFirst()
{ {
return m_first; return m_first;
} }
polygon * polygon::NextPoly()
polygon* polygon::NextPoly()
{ {
return m_first->NextPoly(); return m_first->NextPoly();
} }
/* /*
** Add a vertex object to the polygon (vertex is added at the "end" of the list) ** Add a vertex object to the polygon (vertex is added at the "end" of the list)
** Which because polygons are closed lists means it is added just before the first ** Which because polygons are closed lists means it is added just before the first
** vertex. ** vertex.
*/ */
void polygon::add( vertex * nv ) void polygon::add( vertex* nv )
{ {
if ( m_cnt == 0 ) // If this is the first vertex in the polygon if( m_cnt == 0 ) // If this is the first vertex in the polygon
{ {
m_first = nv; // Save a reference to it in the polygon m_first = nv; // Save a reference to it in the polygon
m_first->setNext(nv); // Set its pointer to point to itself m_first->setNext( nv ); // Set its pointer to point to itself
m_first->setPrev(nv); // because it is the only vertex in the list m_first->setPrev( nv ); // because it is the only vertex in the list
segment * ps = m_first->Nseg(); // Get ref to the Next segment object segment* ps = m_first->Nseg(); // Get ref to the Next segment object
m_first->setPseg(ps); // and save it as Prev segment as well m_first->setPseg( ps ); // and save it as Prev segment as well
} }
else // At least one other vertex already exists else // At least one other vertex already exists
{ {
// p <-> nv <-> n // p <-> nv <-> n
// ps ns // ps ns
vertex * n = m_first; // Get a ref to the first vertex in the list vertex* n = m_first; // Get a ref to the first vertex in the list
vertex * p = n->Prev(); // Get ref to previous vertex vertex* p = n->Prev(); // Get ref to previous vertex
n->setPrev(nv); // Add at end of list (just before first) n->setPrev( nv ); // Add at end of list (just before first)
nv->setNext(n); // link the new vertex to it nv->setNext( n ); // link the new vertex to it
nv->setPrev(p); // link to the pervious EOL vertex nv->setPrev( p ); // link to the pervious EOL vertex
p->setNext(nv); // And finally link the previous EOL vertex p->setNext( nv ); // And finally link the previous EOL vertex
// Segments // Segments
segment * ns = nv->Nseg(); // Get ref to the new next segment segment* ns = nv->Nseg(); // Get ref to the new next segment
segment * ps = p->Nseg(); // Get ref to the previous segment segment* ps = p->Nseg(); // Get ref to the previous segment
n->setPseg(ns); // Set new previous seg for m_first n->setPseg( ns ); // Set new previous seg for m_first
nv->setPseg(ps); // Set previous seg of the new vertex nv->setPseg( ps ); // Set previous seg of the new vertex
} }
m_cnt++; // Increment the count of vertices m_cnt++; // Increment the count of vertices
} }
/* /*
** Create a vertex and then add it to the polygon ** Create a vertex and then add it to the polygon
*/ */
void polygon::addv ( double x, double y, void polygon::addv( double x, double y,
double xc, double yc, int d ) double xc, double yc, int d )
{ {
vertex * nv = new vertex( x, y, xc, yc, d ); vertex* nv = new vertex( x, y, xc, yc, d );
add( nv ); add( nv );
} }
/* /*
** Delete a vertex object from the polygon. This is not used by the main algorithm ** Delete a vertex object from the polygon. This is not used by the main algorithm
** but instead is used to clean-up a polygon so that a second boolean operation can ** but instead is used to clean-up a polygon so that a second boolean operation can
** be performed. ** be performed.
*/ */
vertex * polygon::del( vertex * v ) vertex* polygon::del( vertex* v )
{ {
// p <-> v <-> n Will delete v and ns // p <-> v <-> n Will delete v and ns
// ps ns // ps ns
vertex * p = v->Prev(); // Get ref to previous vertex vertex* p = v->Prev(); // Get ref to previous vertex
vertex * n = v->Next(); // Get ref to next vertex vertex* n = v->Next(); // Get ref to next vertex
p->setNext(n); // Link previous forward to next
n->setPrev(p); // Link next back to previous p->setNext( n ); // Link previous forward to next
n->setPrev( p ); // Link next back to previous
// Segments // Segments
segment * ps = p->Nseg(); // Get ref to previous segment segment* ps = p->Nseg(); // Get ref to previous segment
segment * ns = v->Nseg(); // Get ref to next segment segment* ns = v->Nseg(); // Get ref to next segment
n->setPseg(ps); // Link next back to previous segment n->setPseg( ps ); // Link next back to previous segment
delete ns; //AMW delete ns; //AMW
v->m_nSeg = NULL; // AMW v->m_nSeg = NULL; // AMW
delete v; //AMW delete v; //AMW
...@@ -159,6 +171,7 @@ vertex * polygon::del( vertex * v ) ...@@ -159,6 +171,7 @@ vertex * polygon::del( vertex * v )
return n; // Return a ref to the next valid vertex return n; // Return a ref to the next valid vertex
} }
/* /*
** Reset Polygon - Deletes all intersection vertices. This is used to ** Reset Polygon - Deletes all intersection vertices. This is used to
** restore a polygon that has been processed by the boolean method ** restore a polygon that has been processed by the boolean method
...@@ -166,33 +179,36 @@ vertex * polygon::del( vertex * v ) ...@@ -166,33 +179,36 @@ vertex * polygon::del( vertex * v )
*/ */
void polygon::res() void polygon::res()
{ {
vertex * v = getFirst(); // Get the first vertex vertex* v = getFirst(); // Get the first vertex
do do
{ {
v = v->Next(); // Get the next vertex in the polygon v = v->Next(); // Get the next vertex in the polygon
while (v->isIntersect()) // Delete all intersection vertices while( v->isIntersect() ) // Delete all intersection vertices
v = del(v); v = del( v );
} } while( v->id() != m_first->id() );
while (v->id() != m_first->id());
} }
/* /*
** Copy Polygon - Returns a reference to a new copy of the poly object ** Copy Polygon - Returns a reference to a new copy of the poly object
** including all its vertices & their segments ** including all its vertices & their segments
*/ */
polygon * polygon::copy_poly() polygon* polygon::copy_poly()
{ {
polygon * n = new polygon; // Create a new instance of this class polygon* n = new polygon; // Create a new instance of this class
vertex * v = getFirst(); vertex* v = getFirst();
do do
{ {
n->addv(v->X(),v->Y(),v->Xc(),v->Yc(), (int) v->d()); n->addv( v->X(), v->Y(), v->Xc(), v->Yc(), (int) v->d() );
v = v->Next(); v = v->Next();
} } while( v->id() != m_first->id() );
while (v->id() != m_first->id());
return n; return n;
} }
/* /*
** Insert and Sort a vertex between a specified pair of vertices (start and end) ** Insert and Sort a vertex between a specified pair of vertices (start and end)
** **
...@@ -202,39 +218,45 @@ polygon * polygon::copy_poly() ...@@ -202,39 +218,45 @@ polygon * polygon::copy_poly()
** points between the two vertices then the new vertex is inserted based on its ** points between the two vertices then the new vertex is inserted based on its
** alpha value. ** alpha value.
*/ */
void polygon::insertSort( vertex * nv, vertex * s, vertex * e ) void polygon::insertSort( vertex* nv, vertex* s, vertex* e )
{ {
vertex * c = s; // Set current to the starting vertex vertex* c = s; // Set current to the starting vertex
// Move current past any intersections // Move current past any intersections
// whose alpha is lower but don't go past // whose alpha is lower but don't go past
// the end vertex // the end vertex
while( c->id() != e->id() && c->Alpha() < nv->Alpha() ) while( c->id() != e->id() && c->Alpha() < nv->Alpha() )
c = c->Next(); c = c->Next();
// p <-> nv <-> c // p <-> nv <-> c
nv->setNext(c); // Link new vertex forward to curent one nv->setNext( c ); // Link new vertex forward to curent one
vertex * p = c->Prev(); // Get a link to the previous vertex vertex* p = c->Prev(); // Get a link to the previous vertex
nv->setPrev(p); // Link the new vertex back to the previous one nv->setPrev( p ); // Link the new vertex back to the previous one
p->setNext(nv); // Link previous vertex forward to new vertex p->setNext( nv ); // Link previous vertex forward to new vertex
c->setPrev(nv); // Link current vertex back to the new vertex c->setPrev( nv ); // Link current vertex back to the new vertex
// Segments // Segments
segment * ps = p->Nseg(); segment* ps = p->Nseg();
nv->setPseg(ps); nv->setPseg( ps );
segment * ns = nv->Nseg(); segment* ns = nv->Nseg();
c->setPseg(ns); c->setPseg( ns );
m_cnt++; // Just added a new vertex m_cnt++; // Just added a new vertex
} }
/* /*
** return the next non intersecting vertex after the one specified ** return the next non intersecting vertex after the one specified
*/ */
vertex * polygon::nxt( vertex * v ) vertex* polygon::nxt( vertex* v )
{ {
vertex * c = v; // Initialize current vertex vertex* c = v; // Initialize current vertex
while (c && c->isIntersect()) // Move until a non-intersection
while( c && c->isIntersect() ) // Move until a non-intersection
c = c->Next(); // vertex if found c = c->Next(); // vertex if found
return c; // return that vertex return c; // return that vertex
} }
/* /*
** Check if any unchecked intersections remain in the polygon. The boolean ** Check if any unchecked intersections remain in the polygon. The boolean
** method is complete when all intersections have been checked. ** method is complete when all intersections have been checked.
...@@ -242,38 +264,46 @@ vertex * polygon::nxt( vertex * v ) ...@@ -242,38 +264,46 @@ vertex * polygon::nxt( vertex * v )
BOOL polygon::unckd_remain() BOOL polygon::unckd_remain()
{ {
BOOL remain = FALSE; BOOL remain = FALSE;
vertex * v = m_first; vertex* v = m_first;
do do
{ {
if (v->isIntersect() && !v->isChecked()) if( v->isIntersect() && !v->isChecked() )
remain = TRUE; // Set if an unchecked intersection is found remain = TRUE; // Set if an unchecked intersection is found
v = v->Next(); v = v->Next();
} } while( v->id() != m_first->id() );
while (v->id() != m_first->id());
return remain; return remain;
} }
/* /*
** Return a ref to the first unchecked intersection point in the polygon. ** Return a ref to the first unchecked intersection point in the polygon.
** If none are found then just the first vertex is returned. ** If none are found then just the first vertex is returned.
*/ */
vertex * polygon::first_unckd_intersect() vertex* polygon::first_unckd_intersect()
{ {
vertex * v = m_first; vertex* v = m_first;
do // Do-While do // Do-While
{ // Not yet reached end of the polygon { // Not yet reached end of the polygon
v = v->Next(); // AND the vertex if NOT an intersection v = v->Next(); // AND the vertex if NOT an intersection
} // OR it IS an intersection, but has been checked already } // OR it IS an intersection, but has been checked already
while(v->id() != m_first->id() && ( !v->isIntersect() || ( v->isIntersect() && v->isChecked() ) ) ); while( v->id() != m_first->id() && ( !v->isIntersect() || ( v->isIntersect() && v->isChecked() ) ) );
return v; return v;
} }
/* /*
** Return the distance between two points ** Return the distance between two points
*/ */
double polygon::dist( double x1, double y1, double x2, double y2 ) double polygon::dist( double x1, double y1, double x2, double y2 )
{ {
return sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)); return sqrt( (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) );
} }
/* /*
** Calculate the angle between 2 points, where Xc,Yc is the center of a circle ** Calculate the angle between 2 points, where Xc,Yc is the center of a circle
** and x,y is a point on its circumference. All angles are relative to ** and x,y is a point on its circumference. All angles are relative to
...@@ -281,15 +311,17 @@ double polygon::dist( double x1, double y1, double x2, double y2 ) ...@@ -281,15 +311,17 @@ double polygon::dist( double x1, double y1, double x2, double y2 )
*/ */
double polygon::angle( double xc, double yc, double x1, double y1 ) double polygon::angle( double xc, double yc, double x1, double y1 )
{ {
double d = dist(xc, yc, x1, y1); // calc distance between two points double d = dist( xc, yc, x1, y1 ); // calc distance between two points
double a1; double a1;
if ( asin( (y1-yc)/d ) >= 0 )
a1 = acos( (x1-xc)/d ); if( asin( (y1 - yc) / d ) >= 0 )
a1 = acos( (x1 - xc) / d );
else else
a1 = 2*PI - acos( (x1-xc)/d ); a1 = 2 * PI - acos( (x1 - xc) / d );
return a1; return a1;
} }
/* /*
** Return Alpha value for an Arc ** Return Alpha value for an Arc
** **
...@@ -299,11 +331,12 @@ double polygon::angle( double xc, double yc, double x1, double y1 ) ...@@ -299,11 +331,12 @@ double polygon::angle( double xc, double yc, double x1, double y1 )
double polygon::aAlpha( double x1, double y1, double x2, double y2, double polygon::aAlpha( double x1, double y1, double x2, double y2,
double xc, double yc, double xi, double yi, double d ) double xc, double yc, double xi, double yi, double d )
{ {
double sa = angle(xc, yc, x1, y1); // Start Angle double sa = angle( xc, yc, x1, y1 ); // Start Angle
double ea = angle(xc, yc, x2, y2); // End Angle double ea = angle( xc, yc, x2, y2 ); // End Angle
double ia = angle(xc, yc, xi, yi); // Intersection Angle double ia = angle( xc, yc, xi, yi ); // Intersection Angle
double arc, aint; double arc, aint;
if (d == 1) // Anti-Clockwise
if( d == 1 ) // Anti-Clockwise
{ {
arc = ea - sa; arc = ea - sa;
aint = ia - sa; aint = ia - sa;
...@@ -313,14 +346,15 @@ double polygon::aAlpha( double x1, double y1, double x2, double y2, ...@@ -313,14 +346,15 @@ double polygon::aAlpha( double x1, double y1, double x2, double y2,
arc = sa - ea; arc = sa - ea;
aint = sa - ia; aint = sa - ia;
} }
if (arc < 0) if( arc < 0 )
arc += 2*PI; arc += 2 * PI;
if (aint < 0) if( aint < 0 )
aint += 2*PI; aint += 2 * PI;
double a = aint/arc; double a = aint / arc;
return a; return a;
} }
/* /*
** This function handles the degenerate case where a vertex of one ** This function handles the degenerate case where a vertex of one
** polygon lies directly on an edge of the other. This case can ** polygon lies directly on an edge of the other. This case can
...@@ -328,35 +362,37 @@ double polygon::aAlpha( double x1, double y1, double x2, double y2, ...@@ -328,35 +362,37 @@ double polygon::aAlpha( double x1, double y1, double x2, double y2,
** line exactly intersects with a vertex. The function works ** line exactly intersects with a vertex. The function works
** by shortening the line by a tiny amount. ** by shortening the line by a tiny amount.
*/ */
void polygon::perturb( vertex * p1, vertex * p2, vertex * q1, vertex * q2, void polygon::perturb( vertex* p1, vertex* p2, vertex* q1, vertex* q2,
double aP, double aQ ) double aP, double aQ )
{ {
// if (aP == 0) // Move vertex p1 closer to p2 // if (aP == 0) // Move vertex p1 closer to p2
if( abs(aP) <= eps ) // Move vertex p1 closer to p2 if( abs( aP ) <= eps ) // Move vertex p1 closer to p2
{ {
p1->setX(p1->X() + (1-PT) * (p2->X() - p1->X())); p1->setX( p1->X() + (1 - PT) * ( p2->X() - p1->X() ) );
p1->setY(p1->Y() + (1-PT) * (p2->Y() - p1->Y())); p1->setY( p1->Y() + (1 - PT) * ( p2->Y() - p1->Y() ) );
} }
// else if (aP == 1) // Move vertex p2 closer to p1 // else if (aP == 1) // Move vertex p2 closer to p1
else if( abs(1-aP) <= eps ) // Move vertex p2 closer to p1 else if( abs( 1 - aP ) <= eps ) // Move vertex p2 closer to p1
{ {
p2->setX(p1->X() + PT * (p2->X() - p1->X())); p2->setX( p1->X() + PT * ( p2->X() - p1->X() ) );
p2->setY(p1->Y() + PT * (p2->Y() - p1->Y())); p2->setY( p1->Y() + PT * ( p2->Y() - p1->Y() ) );
} }
//** else if (aQ == 0) // Move vertex q1 closer to q2 //** else if (aQ == 0) // Move vertex q1 closer to q2
if( abs(aQ) <= eps ) // Move vertex q1 closer to q2 if( abs( aQ ) <= eps ) // Move vertex q1 closer to q2
{ {
q1->setX(q1->X() + (1-PT) * (q2->X() - q1->X())); q1->setX( q1->X() + (1 - PT) * ( q2->X() - q1->X() ) );
q1->setY(q1->Y() + (1-PT) * (q2->Y() - q1->Y())); q1->setY( q1->Y() + (1 - PT) * ( q2->Y() - q1->Y() ) );
} }
//** else if (aQ == 1) // Move vertex q2 closer to q1 //** else if (aQ == 1) // Move vertex q2 closer to q1
else if( abs(1-aQ) <= eps ) // Move vertex q2 closer to q1 else if( abs( 1 - aQ ) <= eps ) // Move vertex q2 closer to q1
{ {
q2->setX(q1->X() + PT * (q2->X() - q1->X())); q2->setX( q1->X() + PT * ( q2->X() - q1->X() ) );
q2->setY(q1->Y() + PT * (q2->Y() - q1->Y())); q2->setY( q1->Y() + PT * ( q2->Y() - q1->Y() ) );
} }
} }
/* /*
** Determine the intersection between two pairs of vertices p1/p2, q1/q2 ** Determine the intersection between two pairs of vertices p1/p2, q1/q2
** **
...@@ -372,15 +408,16 @@ void polygon::perturb( vertex * p1, vertex * p2, vertex * q1, vertex * q2, ...@@ -372,15 +408,16 @@ void polygon::perturb( vertex * p1, vertex * p2, vertex * q1, vertex * q2,
** The arrays ix[], iy[], alphaP[] & alphaQ[] return the intersection points ** The arrays ix[], iy[], alphaP[] & alphaQ[] return the intersection points
** and their associated alpha values. ** and their associated alpha values.
*/ */
BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2, BOOL polygon::ints( vertex* p1, vertex* p2, vertex* q1, vertex* q2,
int * n, double ix[], double iy[], double alphaP[], double alphaQ[] ) int* n, double ix[], double iy[], double alphaP[], double alphaQ[] )
{ {
BOOL found = FALSE; BOOL found = FALSE;
*n = 0; // No intersections found yet *n = 0; // No intersections found yet
int pt = (int) p1->d(); int pt = (int) p1->d();
int qt = (int) q1->d(); // Do we have Arcs or Lines? int qt = (int) q1->d(); // Do we have Arcs or Lines?
if (pt == 0 && qt == 0) // Is it line/Line ? if( pt == 0 && qt == 0 ) // Is it line/Line ?
{ {
/* LINE/LINE /* LINE/LINE
** Algorithm from: http://astronomy.swin.edu.au/~pbourke/geometry/lineline2d/ ** Algorithm from: http://astronomy.swin.edu.au/~pbourke/geometry/lineline2d/
...@@ -393,12 +430,13 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2, ...@@ -393,12 +430,13 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2,
double y3 = q1->Y(); double y3 = q1->Y();
double x4 = q2->X(); double x4 = q2->X();
double y4 = q2->Y(); double y4 = q2->Y();
double d = ((y4-y3)*(x2-x1)-(x4-x3)*(y2-y1)); double d = ( (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1) );
if (d != 0) if( d != 0 )
{ // The lines intersect at a point somewhere { // The lines intersect at a point somewhere
double ua = ((x4-x3)*(y1-y3)-(y4-y3)*(x1-x3))/d; double ua = ( (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3) ) / d;
double ub = ((x2-x1)*(y1-y3)-(y2-y1)*(x1-x3))/d; double ub = ( (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3) ) / d;
TRACE( " ints: ua = %.17f, ub = %.17f\n", ua, ub ); // TRACE( " ints: ua = %.17f, ub = %.17f\n", ua, ub );
// The values of $ua and $ub tell us where the intersection occurred. // The values of $ua and $ub tell us where the intersection occurred.
// A value between 0 and 1 means the intersection occurred within the // A value between 0 and 1 means the intersection occurred within the
// line segment. // line segment.
...@@ -409,10 +447,11 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2, ...@@ -409,10 +447,11 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2,
// NOT to be an intersection and we will move the vertex a tiny distance // NOT to be an intersection and we will move the vertex a tiny distance
// away from the intersecting line. // away from the intersecting line.
// if( ua == 0 || ua == 1 || ub == 0 || ub == 1 ) // if( ua == 0 || ua == 1 || ub == 0 || ub == 1 )
if( abs(ua)<=eps || abs(1.0-ua)<=eps || abs(ub)<=eps || abs(1.0-ub)<=eps ) if( abs( ua )<=eps || abs( 1.0 - ua )<=eps || abs( ub )<=eps || abs( 1.0 - ub )<=eps )
{ {
// Degenerate case - vertex touches a line // Degenerate case - vertex touches a line
perturb(p1, p2, q1, q2, ua, ub); perturb( p1, p2, q1, q2, ua, ub );
//** for testing, see if we have successfully resolved the degeneracy //** for testing, see if we have successfully resolved the degeneracy
{ {
double tx1 = p1->X(); double tx1 = p1->X();
...@@ -423,28 +462,42 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2, ...@@ -423,28 +462,42 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2,
double ty3 = q1->Y(); double ty3 = q1->Y();
double tx4 = q2->X(); double tx4 = q2->X();
double ty4 = q2->Y(); double ty4 = q2->Y();
double td = ((ty4-ty3)*(tx2-tx1)-(tx4-tx3)*(ty2-ty1)); double td = ( (ty4 - ty3) * (tx2 - tx1) - (tx4 - tx3) * (ty2 - ty1) );
if (td != 0) if( td != 0 )
{ {
// The lines intersect at a point somewhere // The lines intersect at a point somewhere
double tua = ((tx4-tx3)*(ty1-ty3)-(ty4-ty3)*(tx1-tx3))/td; double tua =
double tub = ((tx2-tx1)*(ty1-ty3)-(ty2-ty1)*(tx1-tx3))/td; ( (tx4 - tx3) * (ty1 - ty3) - (ty4 - ty3) * (tx1 - tx3) ) / td;
if( abs(tua)<=eps || abs(1.0-tua)<=eps || abs(tub)<=eps || abs(1.0-tub)<=eps ) double tub =
wxASSERT(0); ( (tx2 - tx1) * (ty1 - ty3) - (ty2 - ty1) * (tx1 - tx3) ) / td;
if( abs( tua )<=eps || abs( 1.0 - tua )<=eps || abs( tub )<=eps ||
abs( 1.0 - tub )<=eps )
wxASSERT( 0 );
else if( (tua > 0 && tua < 1) && (tub > 0 && tub < 1) ) else if( (tua > 0 && tua < 1) && (tub > 0 && tub < 1) )
wxASSERT(0); wxASSERT( 0 );
TRACE( " perturb:\n new s = (%f,%f) to (%f,%f)\n new c = (%f,%f) to (%f,%f)\n new ua = %.17f, ub = %.17f\n", TRACE(
tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4, tua, tub ); " perturb:\n new s = (%f,%f) to (%f,%f)\n new c = (%f,%f) to (%f,%f)\n new ua = %.17f, ub = %.17f\n",
tx1,
ty1,
tx2,
ty2,
tx3,
ty3,
tx4,
ty4,
tua,
tub );
} }
} }
//** end test //** end test
found = FALSE; found = FALSE;
} }
else if ((ua > 0 && ua < 1) && (ub > 0 && ub < 1)) else if( (ua > 0 && ua < 1) && (ub > 0 && ub < 1) )
{ {
// Intersection occurs on both line segments // Intersection occurs on both line segments
double x = x1 + ua*(x2-x1); double x = x1 + ua * (x2 - x1);
double y = y1 + ua*(y2-y1); double y = y1 + ua * (y2 - y1);
iy[0] = y; iy[0] = y;
ix[0] = x; ix[0] = x;
alphaP[0] = ua; alphaP[0] = ua;
...@@ -464,27 +517,27 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2, ...@@ -464,27 +517,27 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2,
found = FALSE; found = FALSE;
} }
} // End of find Line/Line intersection } // End of find Line/Line intersection
else if (pt != 0 && qt != 0) // Is it Arc/Arc? else if( pt != 0 && qt != 0 ) // Is it Arc/Arc?
{ {
/* ARC/ARC /* ARC/ARC
** Algorithm from: http://astronomy.swin.edu.au/~pbourke/geometry/2circle/ ** Algorithm from: http://astronomy.swin.edu.au/~pbourke/geometry/2circle/
*/ */
double x0 = p1->Xc(); double x0 = p1->Xc();
double y0 = p1->Yc(); // Center of first Arc double y0 = p1->Yc(); // Center of first Arc
double r0 = dist(x0,y0,p1->X(),p1->Y()); // Calc the radius double r0 = dist( x0, y0, p1->X(), p1->Y() ); // Calc the radius
double x1 = q1->Xc(); double x1 = q1->Xc();
double y1 = q1->Yc(); // Center of second Arc double y1 = q1->Yc(); // Center of second Arc
double r1 = dist(x1,y1,q1->X(),q1->Y()); // Calc the radius double r1 = dist( x1, y1, q1->X(), q1->Y() ); // Calc the radius
double dx = x1 - x0; // dx and dy are the vertical and horizontal double dx = x1 - x0; // dx and dy are the vertical and horizontal
double dy = y1 - y0; // distances between the circle centers. double dy = y1 - y0; // distances between the circle centers.
double d = sqrt((dy*dy) + (dx*dx)); // Distance between the centers. double d = sqrt( (dy * dy) + (dx * dx) ); // Distance between the centers.
if(d > (r0 + r1)) // Check for solvability. if( d > (r0 + r1) ) // Check for solvability.
{ // no solution. circles do not intersect. { // no solution. circles do not intersect.
found = FALSE; found = FALSE;
} }
else if(d < abs(r0 - r1) ) else if( d < abs( r0 - r1 ) )
{ // no solution. one circle inside the other { // no solution. one circle inside the other
found = FALSE; found = FALSE;
} }
...@@ -494,14 +547,14 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2, ...@@ -494,14 +547,14 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2,
** 'xy2' is the point where the line through the circle intersection ** 'xy2' is the point where the line through the circle intersection
** points crosses the line between the circle centers. ** points crosses the line between the circle centers.
*/ */
double a = ((r0*r0)-(r1*r1)+(d*d))/(2.0*d); // Calc the distance from xy0 to xy2. double a = ( (r0 * r0) - (r1 * r1) + (d * d) ) / (2.0 * d); // Calc the distance from xy0 to xy2.
double x2 = x0 + (dx * a/d); // Determine the coordinates of xy2. double x2 = x0 + (dx * a / d); // Determine the coordinates of xy2.
double y2 = y0 + (dy * a/d); double y2 = y0 + (dy * a / d);
if (d == (r0 + r1)) // Arcs touch at xy2 exactly (unlikely) if( d == (r0 + r1) ) // Arcs touch at xy2 exactly (unlikely)
{ {
alphaP[0] = aAlpha(p1->X(), p1->Y(), p2->X(), p2->Y(), x0, y0, x2, y2, pt); alphaP[0] = aAlpha( p1->X(), p1->Y(), p2->X(), p2->Y(), x0, y0, x2, y2, pt );
alphaQ[0] = aAlpha(q1->X(), q1->Y(), q2->X(), q2->Y(), x1, y1, x2, y2, qt); alphaQ[0] = aAlpha( q1->X(), q1->Y(), q2->X(), q2->Y(), x1, y1, x2, y2, qt );
if ((alphaP[0] >0 && alphaP[0] < 1) && (alphaQ[0] >0 && alphaQ[0] < 1)) if( (alphaP[0] >0 && alphaP[0] < 1) && (alphaQ[0] >0 && alphaQ[0] < 1) )
{ {
ix[0] = x2; ix[0] = x2;
iy[0] = y2; iy[0] = y2;
...@@ -511,20 +564,21 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2, ...@@ -511,20 +564,21 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2,
else // Arcs intersect at two points else // Arcs intersect at two points
{ {
double alP[2], alQ[2]; double alP[2], alQ[2];
double h = sqrt((r0*r0) - (a*a)); // Calc the distance from xy2 to either double h = sqrt( (r0 * r0) - (a * a) ); // Calc the distance from xy2 to either
// of the intersection points. // of the intersection points.
double rx = -dy * (h/d); // Now determine the offsets of the double rx = -dy * (h / d); // Now determine the offsets of the
double ry = dx * (h/d); double ry = dx * (h / d);
// intersection points from xy2 // intersection points from xy2
double x[2], y[2]; double x[2], y[2];
x[0] = x2 + rx; x[1] = x2 - rx; // Calc the absolute intersection points. x[0] = x2 + rx; x[1] = x2 - rx; // Calc the absolute intersection points.
y[0] = y2 + ry; y[1] = y2 - ry; y[0] = y2 + ry; y[1] = y2 - ry;
alP[0] = aAlpha(p1->X(), p1->Y(), p2->X(), p2->Y(), x0, y0, x[0], y[0], pt); alP[0] = aAlpha( p1->X(), p1->Y(), p2->X(), p2->Y(), x0, y0, x[0], y[0], pt );
alQ[0] = aAlpha(q1->X(), q1->Y(), q2->X(), q2->Y(), x1, y1, x[0], y[0], qt); alQ[0] = aAlpha( q1->X(), q1->Y(), q2->X(), q2->Y(), x1, y1, x[0], y[0], qt );
alP[1] = aAlpha(p1->X(), p1->Y(), p2->X(), p2->Y(), x0, y0, x[1], y[1], pt); alP[1] = aAlpha( p1->X(), p1->Y(), p2->X(), p2->Y(), x0, y0, x[1], y[1], pt );
alQ[1] = aAlpha(q1->X(), q1->Y(), q2->X(), q2->Y(), x1, y1, x[1], y[1], qt); alQ[1] = aAlpha( q1->X(), q1->Y(), q2->X(), q2->Y(), x1, y1, x[1], y[1], qt );
for (int i=0; i<=1; i++) for( int i = 0; i<=1; i++ )
if ((alP[i] >0 && alP[i] < 1) && (alQ[i] >0 && alQ[i] < 1)) if( (alP[i] >0 && alP[i] < 1) && (alQ[i] >0 && alQ[i] < 1) )
{ {
ix[*n] = x[i]; ix[*n] = x[i];
iy[*n] = y[i]; iy[*n] = y[i];
...@@ -543,7 +597,7 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2, ...@@ -543,7 +597,7 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2,
*/ */
double d, x1, x2, xc, xs, xe; double d, x1, x2, xc, xs, xe;
double y1, y2, yc, ys, ye; double y1, y2, yc, ys, ye;
if (pt == 0) // Segment p1,p2 is the line if( pt == 0 ) // Segment p1,p2 is the line
{ // Segment q1,q2 is the arc { // Segment q1,q2 is the arc
x1 = p1->X(); x1 = p1->X();
y1 = p1->Y(); y1 = p1->Y();
...@@ -558,7 +612,8 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2, ...@@ -558,7 +612,8 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2,
d = qt; d = qt;
} }
else // Segment q1,q2 is the line else // Segment q1,q2 is the line
{ // Segment p1,p2 is the arc {
// Segment p1,p2 is the arc
x1 = q1->X(); y1 = q1->Y(); x1 = q1->X(); y1 = q1->Y();
x2 = q2->X(); y2 = q2->Y(); x2 = q2->X(); y2 = q2->Y();
xc = p1->Xc(); yc = p1->Yc(); xc = p1->Xc(); yc = p1->Yc();
...@@ -566,31 +621,31 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2, ...@@ -566,31 +621,31 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2,
xe = p2->X(); ye = p2->Y(); xe = p2->X(); ye = p2->Y();
d = pt; d = pt;
} }
double r = dist(xc,yc,xs,ys); double r = dist( xc, yc, xs, ys );
double a = pow((x2 - x1),2)+pow((y2 - y1),2); double a = pow( (x2 - x1), 2 ) + pow( (y2 - y1), 2 );
double b = 2* ( (x2 - x1)*(x1 - xc) double b = 2 * ( (x2 - x1) * (x1 - xc)
+ (y2 - y1)*(y1 - yc) ); + (y2 - y1) * (y1 - yc) );
double c = pow(xc,2) + pow(yc,2) + double c = pow( xc, 2 ) + pow( yc, 2 ) +
pow(x1,2) + pow(y1,2) - pow( x1, 2 ) + pow( y1, 2 ) -
2* ( xc*x1 + yc*y1) - pow(r,2); 2 * ( xc * x1 + yc * y1) - pow( r, 2 );
double i = b * b - 4 * a * c; double i = b * b - 4 * a * c;
if ( i < 0.0 ) // no intersection if( i < 0.0 ) // no intersection
{ {
found = FALSE; found = FALSE;
} }
else if ( i == 0.0 ) // one intersection else if( i == 0.0 ) // one intersection
{ {
double mu = -b/(2*a); double mu = -b / (2 * a);
double x = x1 + mu*(x2-x1); double x = x1 + mu * (x2 - x1);
double y = y1 + mu*(y2-y1); double y = y1 + mu * (y2 - y1);
double al = mu; // Line Alpha double al = mu; // Line Alpha
double aa = this->aAlpha(xs, ys, xe, ye, xc, yc, x, y, d); // Arc Alpha double aa = this->aAlpha( xs, ys, xe, ye, xc, yc, x, y, d ); // Arc Alpha
if ((al >0 && al <1)&&(aa >0 && aa <1)) if( (al >0 && al <1)&&(aa >0 && aa <1) )
{ {
ix[0] = x; iy[0] = y; ix[0] = x; iy[0] = y;
*n = 1; *n = 1;
found = TRUE; found = TRUE;
if (pt == 0) if( pt == 0 )
{ {
alphaP[0] = al; alphaQ[0] = aa; alphaP[0] = al; alphaQ[0] = aa;
} }
...@@ -600,25 +655,25 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2, ...@@ -600,25 +655,25 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2,
} }
} }
} }
else if ( i > 0.0 ) // two intersections else if( i > 0.0 ) // two intersections
{ {
double mu[2], x[2], y[2], al[2], aa[2]; double mu[2], x[2], y[2], al[2], aa[2];
mu[0] = (-b + sqrt( pow(b,2) - 4*a*c )) / (2*a); // first intersection mu[0] = ( -b + sqrt( pow( b, 2 ) - 4 * a * c ) ) / (2 * a); // first intersection
x[0] = x1 + mu[0]*(x2-x1); x[0] = x1 + mu[0] * (x2 - x1);
y[0] = y1 + mu[0]*(y2-y1); y[0] = y1 + mu[0] * (y2 - y1);
mu[1] = (-b - sqrt(pow(b,2) - 4*a*c )) / (2*a); // second intersection mu[1] = ( -b - sqrt( pow( b, 2 ) - 4 * a * c ) ) / (2 * a); // second intersection
x[1] = x1 + mu[1]*(x2-x1); x[1] = x1 + mu[1] * (x2 - x1);
y[1] = y1 + mu[1]*(y2-y1); y[1] = y1 + mu[1] * (y2 - y1);
al[0] = mu[0]; al[0] = mu[0];
aa[0] = aAlpha(xs, ys, xe, ye, xc, yc, x[0], y[0], d); aa[0] = aAlpha( xs, ys, xe, ye, xc, yc, x[0], y[0], d );
al[1] = mu[1]; al[1] = mu[1];
aa[1] = aAlpha(xs, ys, xe, ye, xc, yc, x[1], y[1], d); aa[1] = aAlpha( xs, ys, xe, ye, xc, yc, x[1], y[1], d );
for (int i=0; i<=1; i++) for( int i = 0; i<=1; i++ )
if ((al[i] >0 && al[i] < 1) && (aa[i] >0 && aa[i] < 1)) if( (al[i] >0 && al[i] < 1) && (aa[i] >0 && aa[i] < 1) )
{ {
ix[*n] = x[i]; ix[*n] = x[i];
iy[*n] = y[i]; iy[*n] = y[i];
if (pt == 0) if( pt == 0 )
{ {
alphaP[*n] = al[i]; alphaP[*n] = al[i];
alphaQ[*n] = aa[i]; alphaQ[*n] = aa[i];
...@@ -636,6 +691,7 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2, ...@@ -636,6 +691,7 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2,
return found; return found;
} // end of intersect function } // end of intersect function
/* /*
** Test if a vertex lies inside the polygon ** Test if a vertex lies inside the polygon
** **
...@@ -649,56 +705,60 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2, ...@@ -649,56 +705,60 @@ BOOL polygon::ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2,
** **
** Allan Wright 4/16/2006: I guess I have no life: I had to increase it to -1000000000 ** Allan Wright 4/16/2006: I guess I have no life: I had to increase it to -1000000000
*/ */
BOOL polygon::isInside( vertex * v ) BOOL polygon::isInside( vertex* v )
{ {
//** modified for testing //** modified for testing
if( v->isIntersect() ) if( v->isIntersect() )
wxASSERT(0); wxASSERT( 0 );
int winding_number = 0; int winding_number = 0;
int winding_number2 = 0; int winding_number2 = 0;
int winding_number3 = 0; int winding_number3 = 0;
int winding_number4 = 0; int winding_number4 = 0;
//** vertex * point_at_infinity = new vertex(-10000000,v->Y()); // Create point at infinity //** vertex * point_at_infinity = new vertex(-10000000,v->Y()); // Create point at infinity
/* vertex * point_at_infinity = new vertex(-1000000000,-50000000); // Create point at infinity /* vertex * point_at_infinity = new vertex(-1000000000,-50000000); // Create point at infinity
vertex * point_at_infinity2 = new vertex(1000000000,+50000000); // Create point at infinity * vertex * point_at_infinity2 = new vertex(1000000000,+50000000); // Create point at infinity
vertex * point_at_infinity3 = new vertex(500000000,1000000000); // Create point at infinity * vertex * point_at_infinity3 = new vertex(500000000,1000000000); // Create point at infinity
vertex * point_at_infinity4 = new vertex(-500000000,1000000000); // Create point at infinity * vertex * point_at_infinity4 = new vertex(-500000000,1000000000); // Create point at infinity
*/ */
vertex point_at_infinity(-1000000000,-50000000); // Create point at infinity vertex point_at_infinity( -1000000000, -50000000 ); // Create point at infinity
vertex point_at_infinity2(1000000000,+50000000); // Create point at infinity vertex point_at_infinity2( 1000000000, +50000000 ); // Create point at infinity
vertex point_at_infinity3(500000000,1000000000); // Create point at infinity vertex point_at_infinity3( 500000000, 1000000000 ); // Create point at infinity
vertex point_at_infinity4(-500000000,1000000000); // Create point at infinity vertex point_at_infinity4( -500000000, 1000000000 ); // Create point at infinity
vertex * q = m_first; // End vertex of a line segment in polygon vertex* q = m_first; // End vertex of a line segment in polygon
do do
{ {
if (!q->isIntersect()) if( !q->isIntersect() )
{ {
int n; int n;
double x[2], y[2], aP[2], aQ[2]; double x[2], y[2], aP[2], aQ[2];
if( ints( &point_at_infinity, v, q, nxt(q->Next()), &n, x, y, aP, aQ ) ) if( ints( &point_at_infinity, v, q, nxt( q->Next() ), &n, x, y, aP, aQ ) )
winding_number += n; // Add number of intersections found winding_number += n; // Add number of intersections found
if( ints( &point_at_infinity2, v, q, nxt(q->Next()), &n, x, y, aP, aQ ) ) if( ints( &point_at_infinity2, v, q, nxt( q->Next() ), &n, x, y, aP, aQ ) )
winding_number2 += n; // Add number of intersections found winding_number2 += n; // Add number of intersections found
if( ints( &point_at_infinity3, v, q, nxt(q->Next()), &n, x, y, aP, aQ ) ) if( ints( &point_at_infinity3, v, q, nxt( q->Next() ), &n, x, y, aP, aQ ) )
winding_number3 += n; // Add number of intersections found winding_number3 += n; // Add number of intersections found
if( ints( &point_at_infinity4, v, q, nxt(q->Next()), &n, x, y, aP, aQ ) ) if( ints( &point_at_infinity4, v, q, nxt( q->Next() ), &n, x, y, aP, aQ ) )
winding_number4 += n; // Add number of intersections found winding_number4 += n; // Add number of intersections found
} }
q = q->Next(); q = q->Next();
} } while( q->id() != m_first->id() );
while( q->id() != m_first->id() );
// delete point_at_infinity; // delete point_at_infinity;
// delete point_at_infinity2; // delete point_at_infinity2;
if( winding_number%2 != winding_number2%2 if( winding_number % 2 != winding_number2 % 2
|| winding_number3%2 != winding_number4%2 || winding_number3 % 2 != winding_number4 % 2
|| winding_number%2 != winding_number3%2 ) || winding_number % 2 != winding_number3 % 2 )
wxASSERT(0); wxASSERT( 0 );
if( winding_number%2 == 0 ) // Check even or odd if( winding_number % 2 == 0 ) // Check even or odd
return FALSE; // even == outside return FALSE; // even == outside
else else
return TRUE; // odd == inside return TRUE; // odd == inside
} }
/* /*
** Execute a Boolean operation on a polygon ** Execute a Boolean operation on a polygon
** **
...@@ -714,12 +774,13 @@ BOOL polygon::isInside( vertex * v ) ...@@ -714,12 +774,13 @@ BOOL polygon::isInside( vertex * v )
** **
** A is the object and B is the polygon passed to the method. ** A is the object and B is the polygon passed to the method.
*/ */
polygon * polygon::boolean( polygon * polyB, int oper ) polygon* polygon::boolean( polygon* polyB, int oper )
{ {
polygon * last = NULL; polygon* last = NULL;
vertex* s = m_first; // First vertex of the subject polygon
vertex* c = polyB->getFirst(); // First vertex of the "clip" polygon
vertex * s = m_first; // First vertex of the subject polygon
vertex * c = polyB->getFirst(); // First vertex of the "clip" polygon
/* /*
** Phase 1 of the algoritm is to find all intersection points between the two ** Phase 1 of the algoritm is to find all intersection points between the two
** polygons. A new vertex is created for each intersection and it is added to ** polygons. A new vertex is created for each intersection and it is added to
...@@ -727,65 +788,76 @@ polygon * polygon::boolean( polygon * polyB, int oper ) ...@@ -727,65 +788,76 @@ polygon * polygon::boolean( polygon * polyB, int oper )
** stores the link between the same intersection point in each polygon. ** stores the link between the same intersection point in each polygon.
*/ */
TRACE( "boolean...phase 1\n" ); TRACE( "boolean...phase 1\n" );
do do
{ {
TRACE( "s=(%f,%f) to (%f,%f) I=%d\n", TRACE( "s=(%f,%f) to (%f,%f) I=%d\n",
s->m_x, s->m_y, s->m_nextV->m_x, s->m_nextV->m_y, s->m_intersect ); s->m_x, s->m_y, s->m_nextV->m_x, s->m_nextV->m_y, s->m_intersect );
if (!s->isIntersect()) if( !s->isIntersect() )
{ {
do do
{ {
TRACE( " c=(%f,%f) to (%f,%f) I=%d\n", TRACE( " c=(%f,%f) to (%f,%f) I=%d\n",
c->m_x, c->m_y, c->m_nextV->m_x, c->m_nextV->m_y, c->m_intersect ); c->m_x, c->m_y, c->m_nextV->m_x, c->m_nextV->m_y, c->m_intersect );
if (!c->isIntersect()) if( !c->isIntersect() )
{ {
int n; int n;
double ix[2], iy[2], alphaS[2], alphaC[2]; double ix[2], iy[2], alphaS[2], alphaC[2];
BOOL bInt = ints(s, nxt(s->Next()),c, polyB->nxt(c->Next()), &n, ix, iy, alphaS, alphaC); BOOL bInt = ints( s, nxt( s->Next() ), c, polyB->nxt(
c->Next() ), &n, ix, iy, alphaS, alphaC );
if( bInt ) if( bInt )
{ {
TRACE( " int at (%f,%f) aS = %.17f, aC = %.17f\n", ix[0], iy[0], alphaS[0], alphaC[0] ); TRACE( " int at (%f,%f) aS = %.17f, aC = %.17f\n",
for (int i=0; i<n; i++) ix[0],
iy[0],
alphaS[0],
alphaC[0] );
for( int i = 0; i<n; i++ )
{ {
vertex * is = new vertex(ix[i], iy[i], s->Xc(), s->Yc(), s->d(), NULL, NULL, NULL, TRUE, NULL, alphaS[i], FALSE, FALSE); vertex* is = new vertex( ix[i], iy[i], s->Xc(), s->Yc(),
vertex * ic = new vertex(ix[i], iy[i], c->Xc(), c->Yc(), c->d(), NULL, NULL, NULL, TRUE, NULL, alphaC[i], FALSE, FALSE); s->d(), NULL, NULL, NULL, TRUE, NULL, alphaS[i], FALSE, FALSE );
is->setNeighbor(ic); vertex* ic = new vertex( ix[i], iy[i], c->Xc(), c->Yc(),
ic->setNeighbor(is); c->d(), NULL, NULL, NULL, TRUE, NULL, alphaC[i], FALSE, FALSE );
insertSort(is, s, this->nxt(s->Next())); is->setNeighbor( ic );
polyB->insertSort(ic, c, polyB->nxt(c->Next())); ic->setNeighbor( is );
insertSort( is, s, this->nxt( s->Next() ) );
polyB->insertSort( ic, c, polyB->nxt( c->Next() ) );
} }
} }
} // end if c is not an intersect point } // end if c is not an intersect point
c = c->Next(); c = c->Next();
} } while( c->id() != polyB->m_first->id() );
while (c->id() != polyB->m_first->id());
} // end if s not an intersect point } // end if s not an intersect point
s = s->Next(); s = s->Next();
} } while( s->id() != m_first->id() );
while(s->id() != m_first->id());
//** for testing...check number of intersections in each poly //** for testing...check number of intersections in each poly
TRACE( "boolean...phase 1 testing\n" ); TRACE( "boolean...phase 1 testing\n" );
int n_ints = 0; int n_ints = 0;
s = m_first; s = m_first;
do do
{ {
if( s->isIntersect() ) if( s->isIntersect() )
n_ints++; n_ints++;
s = s->Next(); s = s->Next();
} while( s->id() != m_first->id() ); } while( s->id() != m_first->id() );
int n_polyB_ints = 0; int n_polyB_ints = 0;
s = polyB->m_first; s = polyB->m_first;
do do
{ {
if( s->isIntersect() ) if( s->isIntersect() )
n_polyB_ints++; n_polyB_ints++;
s = s->Next(); s = s->Next();
} while( s->id() != polyB->m_first->id() ); } while( s->id() != polyB->m_first->id() );
if( n_ints != n_polyB_ints ) if( n_ints != n_polyB_ints )
wxASSERT(0); wxASSERT( 0 );
if( n_ints%2 != 0 ) if( n_ints % 2 != 0 )
wxASSERT(0); wxASSERT( 0 );
//** end test //** end test
/* /*
...@@ -807,54 +879,70 @@ polygon * polygon::boolean( polygon * polyB, int oper ) ...@@ -807,54 +879,70 @@ polygon * polygon::boolean( polygon * polyB, int oper )
** **
** f = TRUE, b = FALSE when stored in the entry record ** f = TRUE, b = FALSE when stored in the entry record
*/ */
TRACE( "boolean...phase 2\n" );
BOOL A, B; BOOL A, B;
switch (oper) switch( oper )
{ {
case A_OR_B: A = FALSE; B = FALSE; break; case A_OR_B:
case A_AND_B: A = TRUE; B = TRUE; break; A = FALSE; B = FALSE; break;
case A_MINUS_B: A = FALSE; B = TRUE; break;
case B_MINUS_A: A = TRUE; B = FALSE; break; case A_AND_B:
default: A = TRUE; B = TRUE; break; A = TRUE; B = TRUE; break;
case A_MINUS_B:
A = FALSE; B = TRUE; break;
case B_MINUS_A:
A = TRUE; B = FALSE; break;
default:
A = TRUE; B = TRUE; break;
} }
s = m_first; s = m_first;
//** testing //** testing
if( s->isIntersect() ) if( s->isIntersect() )
wxASSERT(0); wxASSERT( 0 );
//** end test //** end test
BOOL entry; BOOL entry;
if (polyB->isInside(s)) // if we are already inside if( polyB->isInside( s ) ) // if we are already inside
entry = !A; // next intersection must be an exit entry = !A; // next intersection must be an exit
else // otherwise else // otherwise
entry = A; // next intersection must be an entry entry = A; // next intersection must be an entry
do do
{ {
if (s->isIntersect()) if( s->isIntersect() )
{ {
s->setEntry(entry); s->setEntry( entry );
entry = !entry; entry = !entry;
} }
s = s->Next(); s = s->Next();
} } while( s->id() != m_first->id() );
while (s->id() != m_first->id());
/* /*
** Repeat for other polygon ** Repeat for other polygon
*/ */
c = polyB->m_first; c = polyB->m_first;
if (this->isInside(c)) // if we are already inside if( this->isInside( c ) ) // if we are already inside
entry = !B; // next intersection must be an exit entry = !B; // next intersection must be an exit
else // otherwise else // otherwise
entry = B; // next intersection must be an entry entry = B; // next intersection must be an entry
do do
{ {
if (c->isIntersect()) if( c->isIntersect() )
{ {
c->setEntry(entry); c->setEntry( entry );
entry = !entry; entry = !entry;
} }
c = c->Next(); c = c->Next();
} } while( c->id() != polyB->m_first->id() );
while (c->id() != polyB->m_first->id());
/* /*
** Phase 3 of the algorithm is to scan the linked lists of the ** Phase 3 of the algorithm is to scan the linked lists of the
** two input polygons an construct a linked list of result ** two input polygons an construct a linked list of result
...@@ -863,46 +951,49 @@ polygon * polygon::boolean( polygon * polyB, int oper ) ...@@ -863,46 +951,49 @@ polygon * polygon::boolean( polygon * polyB, int oper )
** our result polygon by following the source or clip polygon ** our result polygon by following the source or clip polygon
** either forwards or backwards. ** either forwards or backwards.
*/ */
while (this->unckd_remain()) // Loop while unchecked intersections remain TRACE( "boolean...phase 3\n" );
while( this->unckd_remain() ) // Loop while unchecked intersections remain
{ {
vertex * v = first_unckd_intersect(); // Get the first unchecked intersect point vertex* v = first_unckd_intersect(); // Get the first unchecked intersect point
polygon * r = new polygon; // Create a new instance of that class polygon* r = new polygon; // Create a new instance of that class
do do
{ {
v->setChecked(); // Set checked flag true for this intersection v->setChecked(); // Set checked flag true for this intersection
if (v->isEntry()) if( v->isEntry() )
{ {
do do
{ {
v = v->Next(); v = v->Next();
vertex * nv = new vertex(v->X(),v->Y(),v->Xc(),v->Yc(),v->d()); vertex* nv = new vertex( v->X(), v->Y(), v->Xc(), v->Yc(), v->d() );
r->add(nv); r->add( nv );
} } while( !v->isIntersect() );
while (!v->isIntersect());
} }
else else
{ {
do do
{ {
v = v->Prev(); v = v->Prev();
vertex * nv = new vertex(v->X(),v->Y(),v->Xc(FALSE),v->Yc(FALSE),v->d(FALSE)); vertex* nv =
r->add(nv); new vertex( v->X(), v->Y(), v->Xc( FALSE ), v->Yc( FALSE ), v->d( FALSE ) );
} r->add( nv );
while (!v->isIntersect()); } while( !v->isIntersect() );
} }
v = v->Neighbor(); v = v->Neighbor();
} } while( !v->isChecked() ); // until polygon closed
while (!v->isChecked()); // until polygon closed
if (last) // Check in case first time thru the loop if( last ) // Check in case first time thru the loop
r->m_first->setNextPoly(last); // Save ref to the last poly in the first vertex r->m_first->setNextPoly( last ); // Save ref to the last poly in the first vertex
// of this poly // of this poly
last = r; // Save this polygon last = r; // Save this polygon
} // end of while there is another intersection to check } // end of while there is another intersection to check
/* /*
** Clean up the input polygons by deleting the intersection points ** Clean up the input polygons by deleting the intersection points
*/ */
res(); res();
polyB->res(); polyB->res();
/* /*
** It is possible that no intersection between the polygons was found and ** It is possible that no intersection between the polygons was found and
** there is no result to return. In this case we make function fail ** there is no result to return. In this case we make function fail
...@@ -913,37 +1004,54 @@ polygon * polygon::boolean( polygon * polyB, int oper ) ...@@ -913,37 +1004,54 @@ polygon * polygon::boolean( polygon * polyB, int oper )
** A\B : Return this ** A\B : Return this
** B\A : return polyB ** B\A : return polyB
*/ */
polygon * p; polygon* p;
if (!last) if( !last )
{ {
switch (oper) TRACE( "boolean...end with no intersection\n" );
switch( oper )
{ {
case A_OR_B: case A_OR_B:
last = copy_poly(); last = copy_poly();
p = polyB->copy_poly(); p = polyB->copy_poly();
last->m_first->setNextPoly(p); last->m_first->setNextPoly( p );
break; break;
case A_AND_B: case A_AND_B:
last = copy_poly(); last = copy_poly();
break; break;
case A_MINUS_B: case A_MINUS_B:
last = copy_poly(); last = copy_poly();
break; break;
case B_MINUS_A: case B_MINUS_A:
last = polyB->copy_poly(); last = polyB->copy_poly();
break; break;
default: default:
last = copy_poly(); last = copy_poly();
break; break;
} }
} }
else if (m_first->m_nextPoly) else if( m_first->m_nextPoly )
{ {
TRACE( "boolean...end with nextPoly\n" );
last->m_first->m_nextPoly = m_first->NextPoly(); last->m_first->m_nextPoly = m_first->NextPoly();
} }
vertex * curr_vertex = last->getFirst();
for( int ii = 0; ii < last->m_cnt; ii++ )
{
int x = (int) curr_vertex->X();
int y = (int) curr_vertex->Y();
TRACE( "point %d @ %.4f %.4f\n", ii, (float)x/10000, (float)y/10000 );
curr_vertex = curr_vertex->Next();
}
return last; return last;
} // end of boolean function } // end of boolean function
/* /*
** Test if a polygon lies entirly inside this polygon ** Test if a polygon lies entirly inside this polygon
** **
...@@ -955,155 +1063,164 @@ polygon * polygon::boolean( polygon * polyB, int oper ) ...@@ -955,155 +1063,164 @@ polygon * polygon::boolean( polygon * polyB, int oper )
*/ */
#if 0 #if 0
function polygon::isPolyInside (p) function polygon::isPolyInside( p )
{ {
inside = TRUE; inside = TRUE;
c = p->getFirst(); // Get the first vertex in polygon p c = p->getFirst(); // Get the first vertex in polygon p
do do
{ {
if (!this->isInside(c)) // If vertex is NOT inside this polygon if( !this->isInside( c ) ) // If vertex is NOT inside this polygon
inside = FALSE; // then set flag to false inside = FALSE; // then set flag to false
c = c->Next(); // Get the next vertex in polygon p c = c->Next(); // Get the next vertex in polygon p
} } while( c->id() != p->first->id() );
while (c->id() != p->first->id());
if (inside) if( inside )
{ {
c = p->getFirst(); // Get the first vertex in polygon p c = p->getFirst(); // Get the first vertex in polygon p
s = getFirst(); // Get the first vertex in this polygon s = getFirst(); // Get the first vertex in this polygon
do do
{ {
do do
{ {
if (this->ints(s, s->Next(),c, c->Next(), n, x, y, aS, aC)) if( this->ints( s, s->Next(), c, c->Next(), n, x, y, aS, aC ) )
inside = FALSE; inside = FALSE;
c = c->Next(); c = c->Next();
} } while( c->id() != p->first->id() );
while (c->id() != p->first->id());
s = s->Next(); s = s->Next();
} } while( s->id() != m_first->id() );
while (s->id() != m_first->id());
} }
return inside; return inside;
} // end of isPolyInside } // end of isPolyInside
/* /*
** Move Polygon ** Move Polygon
** **
** Translates polygon by delta X and delta Y ** Translates polygon by delta X and delta Y
*/ */
function polygon::move (dx, dy) function polygon::move( dx, dy )
{ {
v = getFirst(); v = getFirst();
do do
{ {
v->setX(v->X() + dx); v->setX( v->X() + dx );
v->setY(v->Y() + dy); v->setY( v->Y() + dy );
if (v->d() != 0) if( v->d() != 0 )
{ {
v->setXc(v->Xc() + dx); v->setXc( v->Xc() + dx );
v->setYc(v->Yc() + dy); v->setYc( v->Yc() + dy );
} }
v = v->Next(); v = v->Next();
} } while( v->id() != m_first->id() );
while(v->id() != m_first->id());
} // end of move polygon } // end of move polygon
/* /*
** Rotate Polygon ** Rotate Polygon
** **
** Rotates a polgon about point xr/yr by a radians ** Rotates a polgon about point xr/yr by a radians
*/ */
function polygon::rotate (xr, yr, a) function polygon::rotate( xr, yr, a )
{ {
this->move(-xr,-yr); // Move the polygon so that the point of this->move( -xr, -yr ); // Move the polygon so that the point of
// rotation is at the origin (0,0) // rotation is at the origin (0,0)
if (a < 0) // We might be passed a negitive angle if( a < 0 ) // We might be passed a negitive angle
a += 2*pi(); // make it positive a += 2 * pi(); // make it positive
v = m_first; v = m_first;
do do
{ {
x=v->X(); y=v->Y(); x = v->X(); y = v->Y();
v->setX(x*cos(a) - y*sin(a)); // x' = xCos(a)-ySin(a) v->setX( x * cos( a ) - y * sin( a ) ); // x' = xCos(a)-ySin(a)
v->setY(x*sin(a) + y*cos(a)); // y' = xSin(a)+yCos(a) v->setY( x * sin( a ) + y * cos( a ) ); // y' = xSin(a)+yCos(a)
if (v->d() != 0) if( v->d() != 0 )
{ {
x=v->Xc(); y=v->Yc(); x = v->Xc(); y = v->Yc();
v->setXc(x*cos(a) - y*sin(a)); v->setXc( x * cos( a ) - y * sin( a ) );
v->setYc(x*sin(a) + y*cos(a)); v->setYc( x * sin( a ) + y * cos( a ) );
} }
v = v->Next(); v = v->Next();
} } while( v->id() != m_first->id() );
while(v->id() != m_first->id());
this->move(xr,yr); // Move the rotated polygon back this->move( xr, yr ); // Move the rotated polygon back
} // end of rotate polygon } // end of rotate polygon
/* /*
** Return Bounding Rectangle for a Polygon ** Return Bounding Rectangle for a Polygon
** **
** returns a polygon object that represents the bounding rectangle ** returns a polygon object that represents the bounding rectangle
** for this polygon. Arc segments are correctly handled. ** for this polygon. Arc segments are correctly handled.
*/ */
function polygon::&bRect () function polygon::& bRect()
{ {
minX = INF; minY = INF; maxX = -INF; maxY = -INF; minX = INF; minY = INF; maxX = -INF; maxY = -INF;
v = m_first; v = m_first;
do do
{ {
if (v->d() != 0) // Is it an arc segment if( v->d() != 0 ) // Is it an arc segment
{ {
vn = v->Next(); // end vertex of the arc segment vn = v->Next(); // end vertex of the arc segment
v1 = new vertex(v->Xc(), -infinity); // bottom point of vertical line thru arc center v1 = new vertex( v->Xc(), -infinity ); // bottom point of vertical line thru arc center
v2 = new vertex(v->Xc(), +infinity); // top point of vertical line thru arc center v2 = new vertex( v->Xc(), +infinity ); // top point of vertical line thru arc center
if (this->ints(v, vn, v1, v2, n, x, y, aS, aC)) // Does line intersect the arc ? if( this->ints( v, vn, v1, v2, n, x, y, aS, aC ) ) // Does line intersect the arc ?
{ {
for (i=0; i<n; i++) // check y portion of all intersections for( i = 0; i<n; i++ ) // check y portion of all intersections
{ {
minY = min(minY, y[i], v->Y()); minY = min( minY, y[i], v->Y() );
maxY = max(maxY, y[i], v->Y()); maxY = max( maxY, y[i], v->Y() );
} }
} }
else // There was no intersection so bounding rect is determined else // There was no intersection so bounding rect is determined
{ // by the start point only, not teh edge of the arc {
minY = min(minY, v->Y()); // by the start point only, not teh edge of the arc
maxY = max(maxY, v->Y()); minY = min( minY, v->Y() );
maxY = max( maxY, v->Y() );
} }
v1 = NULL; v2 = NULL; // Free the memory used v1 = NULL; v2 = NULL; // Free the memory used
h1 = new vertex(-infinity, v->Yc()); // left point of horozontal line thru arc center h1 = new vertex( -infinity, v->Yc() ); // left point of horozontal line thru arc center
h2 = new vertex(+infinity, v->Yc()); // right point of horozontal line thru arc center h2 = new vertex( +infinity, v->Yc() ); // right point of horozontal line thru arc center
if (this->ints(v, vn, h1, h2, n, x, y, aS, aC)) // Does line intersect the arc ? if( this->ints( v, vn, h1, h2, n, x, y, aS, aC ) ) // Does line intersect the arc ?
{ {
for (i=0; i<n; i++) // check x portion of all intersections for( i = 0; i<n; i++ ) // check x portion of all intersections
{ {
minX = min(minX, x[i], v->X()); minX = min( minX, x[i], v->X() );
maxX = max(maxX, x[i], v->X()); maxX = max( maxX, x[i], v->X() );
} }
} }
else else
{ {
minX = min(minX, v->X()); minX = min( minX, v->X() );
maxX = max(maxX, v->X()); maxX = max( maxX, v->X() );
} }
h1 = NULL; h2 = NULL; h1 = NULL; h2 = NULL;
} }
else // Straight segment so just check the vertex else // Straight segment so just check the vertex
{ {
minX = min(minX, v->X()); minX = min( minX, v->X() );
minY = min(minY, v->Y()); minY = min( minY, v->Y() );
maxX = max(maxX, v->X()); maxX = max( maxX, v->X() );
maxY = max(maxY, v->Y()); maxY = max( maxY, v->Y() );
} }
v = v->Next(); v = v->Next();
} } while( v->id() != m_first->id() );
while(v->id() != m_first->id());
// //
// Now create an return a polygon with the bounding rectangle // Now create an return a polygon with the bounding rectangle
// //
this_class = get_class(this); // Findout the class I'm in (might be an extension of polygon) this_class = get_class( this ); // Findout the class I'm in (might be an extension of polygon)
p = new this_class; // Create a new instance of that class p = new this_class; // Create a new instance of that class
p->addv(minX,minY); p->addv( minX, minY );
p->addv(minX,maxY); p->addv( minX, maxY );
p->addv(maxX,maxY); p->addv( maxX, maxY );
p->addv(maxX,minY); p->addv( maxX, minY );
return p; return p;
} // end of bounding rectangle } // end of bounding rectangle
#endif #endif
// file php_polygon.h // file php_polygon.h
// See comments in php_polygon.cpp // See comments in php_polygon.cpp
#ifndef PHP_POLYGON_H #ifndef PHP_POLYGON_H
...@@ -10,50 +11,60 @@ class segment; ...@@ -10,50 +11,60 @@ class segment;
#define infinity 100000000 // for places that are far far away #define infinity 100000000 // for places that are far far away
#define PI 3.14159265359 #define PI 3.14159265359
enum{ A_OR_B, A_AND_B, A_MINUS_B, B_MINUS_A }; enum {
A_OR_B,
A_AND_B,
A_MINUS_B,
B_MINUS_A
};
class polygon
{
public:
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
** This class manages a doubly linked list of vertex objects that represents ** This class manages a doubly linked list of vertex objects that represents
** a polygon. The class consists of basic methods to manage the list ** a polygon. The class consists of basic methods to manage the list
** and methods to implement boolean operations between polygon objects. ** and methods to implement boolean operations between polygon objects.
*/ */
vertex * m_first; // Reference to first vertex in the linked list
class polygon
{
public:
vertex* m_first; // Reference to first vertex in the linked list
int m_cnt; // Tracks number of vertices in the polygon int m_cnt; // Tracks number of vertices in the polygon
polygon( vertex * first = NULL ); public:
polygon( vertex* first = NULL );
~polygon(); ~polygon();
vertex * getFirst(); vertex* getFirst();
polygon * NextPoly(); polygon* NextPoly();
void add( vertex * nv ); void add( vertex* nv );
void addv( double x, double y, void addv( double x, double y,
double xc=0, double yc=0, int d=0); double xc = 0, double yc = 0, int d = 0 );
vertex * del( vertex * v ); vertex* del( vertex* v );
void res(); void res();
polygon * copy_poly(); polygon* copy_poly();
void insertSort( vertex * nv, vertex * s, vertex * e ); void insertSort( vertex* nv, vertex* s, vertex* e );
vertex * nxt( vertex * v ); vertex* nxt( vertex* v );
BOOL unckd_remain(); BOOL unckd_remain();
vertex * first_unckd_intersect(); vertex* first_unckd_intersect();
double dist( double x1, double y1, double x2, double y2 ); double dist( double x1, double y1, double x2, double y2 );
double angle( double xc, double yc, double x1, double y1 ); double angle( double xc, double yc, double x1, double y1 );
double aAlpha( double x1, double y1, double x2, double y2, double aAlpha( double x1, double y1, double x2, double y2,
double xc, double yc, double xi, double yi, double d ); double xc, double yc, double xi, double yi, double d );
void perturb( vertex * p1, vertex * p2, vertex * q1, vertex * q2, void perturb( vertex* p1, vertex* p2, vertex* q1, vertex* q2,
double aP, double aQ ); double aP, double aQ );
BOOL ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2, BOOL ints( vertex * p1, vertex * p2, vertex * q1, vertex * q2,
int * n, double ix[], double iy[], double alphaP[], double alphaQ[] ); int* n, double ix[], double iy[], double alphaP[], double alphaQ[] );
BOOL isInside ( vertex * v ); BOOL isInside( vertex* v );
polygon * boolean( polygon * polyB, int oper ); polygon* boolean( polygon* polyB, int oper );
#if 0 #if 0
function isPolyInside (p); function isPolyInside( p );
function move (dx, dy); function move( dx, dy );
function rotate (xr, yr, a); function rotate( xr, yr, a );
function &bRect (); function& bRect();
#endif #endif
}; //end of class polygon }; //end of class polygon
......
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