Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
K
kicad-source-mirror
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
kicad-source-mirror
Commits
0d4b71ef
Commit
0d4b71ef
authored
Sep 18, 2013
by
tomasz.wlostowski@cern.ch
Browse files
Options
Browse Files
Download
Plain Diff
Merged Orson's latest changes.
parents
87dccc9f
9ec4520c
Changes
34
Hide whitespace changes
Inline
Side-by-side
Showing
34 changed files
with
1808 additions
and
1532 deletions
+1808
-1532
opengl_gal.cpp
common/gal/opengl/opengl_gal.cpp
+2
-4
painter.cpp
common/painter.cpp
+0
-22
jump_x86_64_sysv_elf_gas.S
common/system/jump_x86_64_sysv_elf_gas.S
+1
-1
make_x86_64_sysv_elf_gas.S
common/system/make_x86_64_sysv_elf_gas.S
+8
-1
tool_dispatcher.cpp
common/tool/tool_dispatcher.cpp
+3
-11
view.cpp
common/view/view.cpp
+23
-7
wx_view_controls.cpp
common/view/wx_view_controls.cpp
+41
-18
worksheet_item.cpp
common/worksheet_item.cpp
+3
-4
base_struct.h
include/base_struct.h
+3
-106
painter.h
include/painter.h
+30
-7
tool_dispatcher.h
include/tool/tool_dispatcher.h
+0
-2
view.h
include/view/view.h
+29
-0
view_controls.h
include/view/view_controls.h
+9
-14
view_group.h
include/view/view_group.h
+1
-1
view_item.h
include/view/view_item.h
+109
-0
wx_view_controls.h
include/view/wx_view_controls.h
+6
-0
CMakeLists.txt
pcbnew/CMakeLists.txt
+1
-0
basepcbframe.cpp
pcbnew/basepcbframe.cpp
+10
-0
class_dimension.cpp
pcbnew/class_dimension.cpp
+19
-0
class_dimension.h
pcbnew/class_dimension.h
+3
-0
class_module.cpp
pcbnew/class_module.cpp
+2
-1
pcb_painter.cpp
pcbnew/pcb_painter.cpp
+27
-21
pcb_painter.h
pcbnew/pcb_painter.h
+1
-1
pcbframe.cpp
pcbnew/pcbframe.cpp
+1
-2
bright_box.cpp
pcbnew/tools/bright_box.cpp
+72
-0
bright_box.h
pcbnew/tools/bright_box.h
+62
-0
selection_area.cpp
pcbnew/tools/selection_area.cpp
+3
-5
selection_area.h
pcbnew/tools/selection_area.h
+6
-7
selection_tool.cpp
pcbnew/tools/selection_tool.cpp
+48
-12
utils.h
polygon/poly2tri/common/utils.h
+123
-123
cdt.cc
polygon/poly2tri/sweep/cdt.cc
+72
-72
cdt.h
polygon/poly2tri/sweep/cdt.h
+105
-105
sweep.cc
polygon/poly2tri/sweep/sweep.cc
+800
-800
sweep_context.h
polygon/poly2tri/sweep/sweep_context.h
+185
-185
No files found.
common/gal/opengl/opengl_gal.cpp
View file @
0d4b71ef
...
...
@@ -278,10 +278,8 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP
VECTOR2D
(
lineLength
,
-
aWidth
/
2.0
)
);
// Draw line caps
drawStrokedSemiCircle
(
VECTOR2D
(
0.0
,
0.0
),
(
aWidth
+
lineWidth
)
/
2
,
M_PI
/
2
);
drawStrokedSemiCircle
(
VECTOR2D
(
lineLength
,
0.0
),
(
aWidth
+
lineWidth
)
/
2
,
-
M_PI
/
2
);
drawStrokedSemiCircle
(
VECTOR2D
(
0.0
,
0.0
),
aWidth
/
2
,
M_PI
/
2
);
drawStrokedSemiCircle
(
VECTOR2D
(
lineLength
,
0.0
),
aWidth
/
2
,
-
M_PI
/
2
);
Restore
();
}
...
...
common/painter.cpp
View file @
0d4b71ef
...
...
@@ -79,25 +79,3 @@ void PAINTER::SetGAL( GAL* aGal )
{
m_gal
=
aGal
;
}
void
PAINTER
::
DrawBrightened
(
const
VIEW_ITEM
*
aItem
)
{
BOX2I
box
=
aItem
->
ViewBBox
();
RenderTarget
oldTarget
=
m_gal
->
GetTarget
();
m_gal
->
SetTarget
(
TARGET_OVERLAY
);
m_gal
->
PushDepth
();
m_gal
->
SetLayerDepth
(
-
1.0
);
// Draw an outline that marks items as brightened
m_gal
->
SetIsStroke
(
true
);
m_gal
->
SetLineWidth
(
100000.0
);
m_gal
->
SetStrokeColor
(
m_brightenedColor
);
m_gal
->
DrawRectangle
(
box
.
GetOrigin
(),
box
.
GetOrigin
()
+
box
.
GetSize
()
);
m_gal
->
PopDepth
();
m_gal
->
SetTarget
(
oldTarget
);
}
common/system/jump_x86_64_sysv_elf_gas.S
View file @
0d4b71ef
...
...
@@ -41,7 +41,7 @@
.text
.globl jump_fcontext
.type jump_fcontext,@function
.align
16
.align
8
jump_fcontext:
movq %rbx, (%rdi) /* save RBX */
movq %r12, 0x8(%rdi) /* save R12 */
...
...
common/system/make_x86_64_sysv_elf_gas.S
View file @
0d4b71ef
...
...
@@ -40,8 +40,12 @@
.text
.globl make_fcontext
#ifndef __APPLE__
.type make_fcontext,@function
.align 16
#endif
.align 8
make_fcontext:
leaq -0x58(%rdi), %rax /* reserve space for fcontext_t at top of context stack */
...
...
@@ -70,5 +74,8 @@ finish:
xorq %rdi, %rdi /* exit code is zero */
call _exit@PLT /* exit application */
hlt
#ifndef __APPLE__
.size make_fcontext,.-make_fcontext
#endif
common/tool/tool_dispatcher.cpp
View file @
0d4b71ef
...
...
@@ -31,6 +31,7 @@
#include <tool/tool_manager.h>
#include <tool/tool_dispatcher.h>
#include <view/view.h>
#include <view/view_controls.h>
#include <class_drawpanel_gal.h>
...
...
@@ -122,15 +123,6 @@ int TOOL_DISPATCHER::decodeModifiers( const wxKeyboardState* aState ) const
}
wxPoint
TOOL_DISPATCHER
::
getCurrentMousePos
()
const
{
wxPoint
msp
=
wxGetMousePosition
();
wxPoint
winp
=
m_editFrame
->
GetGalCanvas
()
->
GetScreenPosition
();
return
wxPoint
(
msp
.
x
-
winp
.
x
,
msp
.
y
-
winp
.
y
);
}
bool
TOOL_DISPATCHER
::
handleMouseButton
(
wxEvent
&
aEvent
,
int
aIndex
,
bool
aMotion
)
{
ButtonState
*
st
=
m_buttons
[
aIndex
];
...
...
@@ -208,7 +200,6 @@ bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMoti
void
TOOL_DISPATCHER
::
DispatchWxEvent
(
wxEvent
&
aEvent
)
{
bool
motion
=
false
,
buttonEvents
=
false
;
VECTOR2D
pos
;
optional
<
TOOL_EVENT
>
evt
;
int
type
=
aEvent
.
GetEventType
();
...
...
@@ -220,7 +211,8 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
type
==
wxEVT_RIGHT_DOWN
||
type
==
wxEVT_RIGHT_UP
||
type
==
EVT_REFRESH_MOUSE
)
{
pos
=
getView
()
->
ToWorld
(
getCurrentMousePos
()
);
VECTOR2D
screenPos
=
m_toolMgr
->
GetViewControls
()
->
GetCursorPosition
();
VECTOR2D
pos
=
getView
()
->
ToWorld
(
screenPos
);
if
(
pos
!=
m_lastMousePos
||
type
==
EVT_REFRESH_MOUSE
)
{
motion
=
true
;
...
...
common/view/view.cpp
View file @
0d4b71ef
...
...
@@ -45,8 +45,11 @@ VIEW::VIEW( bool aIsDynamic ) :
m_scale
(
1.0
),
m_painter
(
NULL
),
m_gal
(
NULL
),
m_dynamic
(
aIsDynamic
)
m_dynamic
(
aIsDynamic
),
m_scaleLimits
(
15000.0
,
1.0
)
{
m_panBoundary
.
SetMaximum
();
// Redraw everything at the beginning
for
(
int
i
=
0
;
i
<
TARGETS_NUMBER
;
++
i
)
MarkTargetDirty
(
i
);
...
...
@@ -290,6 +293,11 @@ void VIEW::SetScale( double aScale )
void
VIEW
::
SetScale
(
double
aScale
,
const
VECTOR2D
&
aAnchor
)
{
if
(
aScale
>
m_scaleLimits
.
x
)
aScale
=
m_scaleLimits
.
x
;
else
if
(
aScale
<
m_scaleLimits
.
y
)
aScale
=
m_scaleLimits
.
y
;
VECTOR2D
a
=
ToScreen
(
aAnchor
);
m_gal
->
SetZoomFactor
(
aScale
);
...
...
@@ -308,6 +316,20 @@ void VIEW::SetScale( double aScale, const VECTOR2D& aAnchor )
void
VIEW
::
SetCenter
(
const
VECTOR2D
&
aCenter
)
{
m_center
=
aCenter
;
if
(
!
m_panBoundary
.
Contains
(
aCenter
)
)
{
if
(
aCenter
.
x
<
m_panBoundary
.
GetLeft
()
)
m_center
.
x
=
m_panBoundary
.
GetLeft
();
else
if
(
aCenter
.
x
>
m_panBoundary
.
GetRight
()
)
m_center
.
x
=
m_panBoundary
.
GetRight
();
if
(
aCenter
.
y
<
m_panBoundary
.
GetTop
()
)
m_center
.
y
=
m_panBoundary
.
GetTop
();
else
if
(
aCenter
.
y
>
m_panBoundary
.
GetBottom
()
)
m_center
.
y
=
m_panBoundary
.
GetBottom
();
}
m_gal
->
SetLookAtPoint
(
m_center
);
m_gal
->
ComputeWorldScreenMatrix
();
...
...
@@ -604,12 +626,6 @@ void VIEW::draw( VIEW_ITEM* aItem, int aLayer, bool aImmediate ) const
if
(
!
m_painter
->
Draw
(
aItem
,
aLayer
)
)
aItem
->
ViewDraw
(
aLayer
,
m_gal
);
// Alternative drawing method
}
// Draws a bright contour around the item
if
(
static_cast
<
const
EDA_ITEM
*>
(
aItem
)
->
IsBrightened
()
)
{
m_painter
->
DrawBrightened
(
aItem
);
}
}
...
...
common/view/wx_view_controls.cpp
View file @
0d4b71ef
...
...
@@ -28,6 +28,7 @@
#include <view/view.h>
#include <view/wx_view_controls.h>
#include <gal/graphics_abstraction_layer.h>
#include <tool/tool_dispatcher.h>
using
namespace
KiGfx
;
...
...
@@ -58,18 +59,20 @@ WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxWindow* aParentPanel ) :
WX_VIEW_CONTROLS
::
onTimer
),
NULL
,
this
);
}
void
VIEW_CONTROLS
::
ShowCursor
(
bool
aEnabled
)
void
VIEW_CONTROLS
::
ShowCursor
(
bool
aEnabled
)
{
m_view
->
GetGAL
()
->
SetCursorEnabled
(
aEnabled
);
}
void
WX_VIEW_CONTROLS
::
onMotion
(
wxMouseEvent
&
aEvent
)
{
m_mousePosition
.
x
=
aEvent
.
GetX
();
m_mousePosition
.
y
=
aEvent
.
GetY
();
if
(
m_forceCursorPosition
)
m_cursorPosition
=
m_view
->
ToScreen
(
m_forcedPosition
);
m_cursorPosition
=
m_view
->
ToScreen
(
m_forcedPosition
);
else
if
(
m_snappingEnabled
)
m_cursorPosition
=
m_view
->
GetGAL
()
->
GetGridPoint
(
m_mousePosition
);
else
...
...
@@ -190,26 +193,28 @@ void WX_VIEW_CONTROLS::onTimer( wxTimerEvent& aEvent )
{
switch
(
m_state
)
{
case
AUTO_PANNING
:
{
double
borderSize
=
std
::
min
(
m_autoPanMargin
*
m_view
->
GetScreenPixelSize
().
x
,
m_autoPanMargin
*
m_view
->
GetScreenPixelSize
().
y
);
case
AUTO_PANNING
:
{
double
borderSize
=
std
::
min
(
m_autoPanMargin
*
m_view
->
GetScreenPixelSize
().
x
,
m_autoPanMargin
*
m_view
->
GetScreenPixelSize
().
y
);
VECTOR2D
dir
(
m_panDirection
);
VECTOR2D
dir
(
m_panDirection
);
if
(
dir
.
EuclideanNorm
()
>
borderSize
)
dir
=
dir
.
Resize
(
borderSize
);
if
(
dir
.
EuclideanNorm
()
>
borderSize
)
dir
=
dir
.
Resize
(
borderSize
);
dir
=
m_view
->
ToWorld
(
dir
,
false
);
m_view
->
SetCenter
(
m_view
->
GetCenter
()
+
dir
*
m_autoPanSpeed
);
m_parentPanel
->
Refresh
();
}
break
;
dir
=
m_view
->
ToWorld
(
dir
,
false
);
m_view
->
SetCenter
(
m_view
->
GetCenter
()
+
dir
*
m_autoPanSpeed
);
// Notify tools that the cursor position has changed in the world coordinates
wxCommandEvent
moveEvent
(
TOOL_DISPATCHER
::
EVT_REFRESH_MOUSE
);
wxPostEvent
(
m_parentPanel
,
moveEvent
);
}
break
;
case
IDLE
:
// Just remove unnecessary warnings
case
DRAG_PANNING
:
break
;
case
IDLE
:
// Just remove unnecessary warnings
case
DRAG_PANNING
:
break
;
}
}
...
...
@@ -225,6 +230,24 @@ void WX_VIEW_CONTROLS::SetGrabMouse( bool aEnabled )
}
const
VECTOR2D
WX_VIEW_CONTROLS
::
GetMousePosition
()
const
{
wxPoint
msp
=
wxGetMousePosition
();
wxPoint
winp
=
m_parentPanel
->
GetScreenPosition
();
return
VECTOR2D
(
msp
.
x
-
winp
.
x
,
msp
.
y
-
winp
.
y
);
}
const
VECTOR2D
WX_VIEW_CONTROLS
::
GetCursorPosition
()
const
{
if
(
m_snappingEnabled
)
return
m_view
->
GetGAL
()
->
GetGridPoint
(
GetMousePosition
()
);
else
return
GetMousePosition
();
}
bool
WX_VIEW_CONTROLS
::
handleAutoPanning
(
const
wxMouseEvent
&
aEvent
)
{
VECTOR2D
p
(
aEvent
.
GetX
(),
aEvent
.
GetY
()
);
...
...
common/worksheet_item.cpp
View file @
0d4b71ef
...
...
@@ -97,9 +97,6 @@ void WORKSHEET_ITEM::ViewDraw( int aLayer, GAL* aGal ) const
EDA_COLOR_T
edaColor
=
ColorFindNearest
(
color
.
r
*
255
,
color
.
g
*
255
,
color
.
b
*
255
);
drawList
.
BuildWorkSheetGraphicList
(
*
m_pageInfo
,
*
m_titleBlock
,
edaColor
,
edaColor
);
// Draw gray line that outlines the sheet size
drawBorder
(
aGal
);
// Draw all the components that make the page layout
WS_DRAW_ITEM_BASE
*
item
=
drawList
.
GetFirst
();
while
(
item
)
...
...
@@ -125,6 +122,9 @@ void WORKSHEET_ITEM::ViewDraw( int aLayer, GAL* aGal ) const
item
=
drawList
.
GetNext
();
}
// Draw gray line that outlines the sheet size
drawBorder
(
aGal
);
}
...
...
@@ -200,6 +200,5 @@ void WORKSHEET_ITEM::drawBorder( GAL* aGal ) const
aGal
->
SetIsStroke
(
true
);
aGal
->
SetIsFill
(
false
);
aGal
->
SetStrokeColor
(
COLOR4D
(
0.5
,
0.5
,
0.5
,
1.0
)
);
aGal
->
DrawRectangle
(
origin
,
end
);
}
include/base_struct.h
View file @
0d4b71ef
...
...
@@ -47,104 +47,6 @@ extern std::ostream& operator <<( std::ostream& out, const wxPoint& pt );
#endif
/**
* Enum KICAD_T
* is the set of class identification values, stored in EDA_ITEM::m_StructType
*/
enum
KICAD_T
{
NOT_USED
=
-
1
,
///< the 3d code uses this value
EOT
=
0
,
///< search types array terminator (End Of Types)
TYPE_NOT_INIT
=
0
,
PCB_T
,
SCREEN_T
,
///< not really an item, used to identify a screen
// Items in pcb
PCB_MODULE_T
,
///< class MODULE, a footprint
PCB_PAD_T
,
///< class D_PAD, a pad in a footprint
PCB_LINE_T
,
///< class DRAWSEGMENT, a segment not on copper layers
PCB_TEXT_T
,
///< class TEXTE_PCB, text on a layer
PCB_MODULE_TEXT_T
,
///< class TEXTE_MODULE, text in a footprint
PCB_MODULE_EDGE_T
,
///< class EDGE_MODULE, a footprint edge
PCB_TRACE_T
,
///< class TRACKE, a track segment (segment on a copper layer)
PCB_VIA_T
,
///< class SEGVIA, a via (like a track segment on a copper layer)
PCB_ZONE_T
,
///< class SEGZONE, a segment used to fill a zone area (segment on a
///< copper layer)
PCB_MARKER_T
,
///< class MARKER_PCB, a marker used to show something
PCB_DIMENSION_T
,
///< class DIMENSION, a dimension (graphic item)
PCB_TARGET_T
,
///< class PCB_TARGET, a target (graphic item)
PCB_ZONE_AREA_T
,
///< class ZONE_CONTAINER, a zone area
PCB_ITEM_LIST_T
,
///< class BOARD_ITEM_LIST, a list of board items
// Schematic draw Items. The order of these items effects the sort order.
// It is currently ordered to mimic the old Eeschema locate behavior where
// the smallest item is the selected item.
SCH_MARKER_T
,
SCH_JUNCTION_T
,
SCH_NO_CONNECT_T
,
SCH_BUS_WIRE_ENTRY_T
,
SCH_BUS_BUS_ENTRY_T
,
SCH_LINE_T
,
SCH_BITMAP_T
,
SCH_TEXT_T
,
SCH_LABEL_T
,
SCH_GLOBAL_LABEL_T
,
SCH_HIERARCHICAL_LABEL_T
,
SCH_FIELD_T
,
SCH_COMPONENT_T
,
SCH_SHEET_PIN_T
,
SCH_SHEET_T
,
// Be prudent with these 3 types:
// they should be used only to locate a specific field type
// among SCH_FIELD_T items types
SCH_FIELD_LOCATE_REFERENCE_T
,
SCH_FIELD_LOCATE_VALUE_T
,
SCH_FIELD_LOCATE_FOOTPRINT_T
,
// General
SCH_SCREEN_T
,
/*
* Draw items in library component.
*
* The order of these items effects the sort order for items inside the
* "DRAW/ENDDRAW" section of the component definition in a library file.
* If you add a new draw item, type, please make sure you add it so the
* sort order is logical.
*/
LIB_COMPONENT_T
,
LIB_ALIAS_T
,
LIB_ARC_T
,
LIB_CIRCLE_T
,
LIB_TEXT_T
,
LIB_RECTANGLE_T
,
LIB_POLYLINE_T
,
LIB_BEZIER_T
,
LIB_PIN_T
,
/*
* Fields are not saved inside the "DRAW/ENDDRAW". Add new draw item
* types before this line.
*/
LIB_FIELD_T
,
/*
* For GerbView: items type:
*/
TYPE_GERBER_DRAW_ITEM
,
/*
* for Pl_Editor, in undo/redo commands
*/
TYPE_PL_EDITOR_LAYOUT
,
// End value
MAX_STRUCT_TYPE_ID
};
/**
* Enum FILL_T
* is the set of fill types used in plotting or drawing enclosed areas.
...
...
@@ -440,12 +342,7 @@ public:
EDA_ITEM
(
const
EDA_ITEM
&
base
);
virtual
~
EDA_ITEM
()
{
};
/**
* Function Type
* returns the type of object. This attribute should never be changed
* after a constructor sets it, so there is no public "setter" method.
* @return KICAD_T - the type of object.
*/
/// @copydoc VIEW_ITEM::Type()
KICAD_T
Type
()
const
{
return
m_StructType
;
}
void
SetTimeStamp
(
time_t
aNewTimeStamp
)
{
m_TimeStamp
=
aNewTimeStamp
;
}
...
...
@@ -474,11 +371,11 @@ public:
inline
void
SetSelected
()
{
SetFlags
(
SELECTED
);
ViewUpdate
(
COLOR
);
}
inline
void
SetHighlighted
()
{
SetFlags
(
HIGHLIGHTED
);
ViewUpdate
(
COLOR
);
}
inline
void
SetBrightened
()
{
SetFlags
(
BRIGHTENED
);
ViewUpdate
(
COLOR
);
}
inline
void
SetBrightened
()
{
SetFlags
(
BRIGHTENED
);
}
inline
void
ClearSelected
()
{
ClearFlags
(
SELECTED
);
ViewUpdate
(
COLOR
);
}
inline
void
ClearHighlighted
()
{
ClearFlags
(
HIGHLIGHTED
);
ViewUpdate
(
COLOR
);
}
inline
void
ClearBrightened
()
{
ClearFlags
(
BRIGHTENED
);
ViewUpdate
(
COLOR
);
}
inline
void
ClearBrightened
()
{
ClearFlags
(
BRIGHTENED
);
}
void
SetModified
();
...
...
include/painter.h
View file @
0d4b71ef
...
...
@@ -80,6 +80,16 @@ public:
m_activeLayers
.
erase
(
aLayerId
);
}
/**
* Function GetActiveLayers()
* Returns the set of currently active layers.
* @return The set of currently active layers.
*/
const
std
::
set
<
unsigned
int
>
GetActiveLayers
()
{
return
m_activeLayers
;
}
/**
* Function ClearActiveLayers
* Clears the list of active layers.
...
...
@@ -89,6 +99,16 @@ public:
m_activeLayers
.
clear
();
}
/**
* Function IsActiveLayer
* Returns information whether the queried layer is marked as active.
* @return True if the queried layer is marked as active.
*/
inline
bool
IsActiveLayer
(
int
aLayerId
)
const
{
return
(
m_activeLayers
.
count
(
aLayerId
)
>
0
);
}
/**
* Function SetHighlight
* Turns on/off highlighting - it may be done for the active layer or the specified net.
...
...
@@ -114,6 +134,16 @@ public:
m_hiContrastEnabled
=
aEnabled
;
}
/**
* Function GetHighContrast
* Returns information about high contrast display mode.
* @return True if the high contrast mode is on, false otherwise.
*/
inline
bool
GetHighContrast
()
const
{
return
m_hiContrastEnabled
;
}
/**
* Function GetColor
* Returns the color that should be used to draw the specific VIEW_ITEM on the specific layer
...
...
@@ -224,13 +254,6 @@ public:
*/
virtual
bool
Draw
(
const
VIEW_ITEM
*
aItem
,
int
aLayer
)
=
0
;
/**
* Function DrawBrightened
* Draws a special marking for the item.
* @param aItem is the item that is going to be marked.
*/
virtual
void
DrawBrightened
(
const
VIEW_ITEM
*
aItem
);
protected
:
/// Instance of graphic abstraction layer that gives an interface to call
/// commands used to draw (eg. DrawLine, DrawCircle, etc.)
...
...
include/tool/tool_dispatcher.h
View file @
0d4b71ef
...
...
@@ -76,8 +76,6 @@ private:
bool
handleMouseButton
(
wxEvent
&
aEvent
,
int
aIndex
,
bool
aMotion
);
bool
handlePopupMenu
(
wxEvent
&
aEvent
);
wxPoint
getCurrentMousePos
()
const
;
int
decodeModifiers
(
const
wxKeyboardState
*
aState
)
const
;
struct
ButtonState
;
...
...
include/view/view.h
View file @
0d4b71ef
...
...
@@ -455,6 +455,29 @@ public:
m_dirtyTargets
[
i
]
=
true
;
}
/**
* Function SetPanBoundary()
* Sets limits for panning area.
* @param aBoundary is the box that limits panning area.
*/
void
SetPanBoundary
(
const
BOX2I
&
aBoundary
)
{
m_panBoundary
=
aBoundary
;
}
/**
* Function SetScaleLimits()
* Sets minimum and maximum values for scale.
* @param aMaximum is the maximum value for scale..
* @param aMinimum is the minimum value for scale.
*/
void
SetScaleLimits
(
double
aMaximum
,
double
aMinimum
)
{
wxASSERT_MSG
(
aMaximum
>
aMinimum
,
wxT
(
"I guess you passed parameters in wrong order"
)
);
m_scaleLimits
=
VECTOR2D
(
aMaximum
,
aMinimum
);
}
static
const
int
VIEW_MAX_LAYERS
=
128
;
///* maximum number of layers that may be shown
private
:
...
...
@@ -588,6 +611,12 @@ private:
/// Rendering order modifier for layers that are marked as top layers
static
const
int
TOP_LAYER_MODIFIER
=
-
VIEW_MAX_LAYERS
;
/// Panning boundaries
BOX2I
m_panBoundary
;
/// Zoom limits
VECTOR2D
m_scaleLimits
;
};
}
// namespace KiGfx
...
...
include/view/view_controls.h
View file @
0d4b71ef
...
...
@@ -46,9 +46,9 @@ class VIEW;
class
VIEW_CONTROLS
{
public
:
VIEW_CONTROLS
(
VIEW
*
aView
)
:
m_view
(
aView
),
m_
snappingEnabled
(
false
),
m_
grabMouse
(
false
),
m_autoPanEnabled
(
false
),
m_autoPanMargin
(
0
.
1
),
m_autoPanSpeed
(
0
.
15
)
{};
VIEW_CONTROLS
(
VIEW
*
aView
)
:
m_view
(
aView
),
m_
forceCursorPosition
(
false
),
m_
snappingEnabled
(
false
),
m_grabMouse
(
false
),
m_autoPanEnabled
(
false
),
m_autoPan
Margin
(
0
.
1
),
m_autoPan
Speed
(
0
.
15
)
{};
virtual
~
VIEW_CONTROLS
()
{};
/**
...
...
@@ -110,10 +110,7 @@ public:
*
* @return The current mouse pointer position.
*/
virtual
const
VECTOR2D
&
GetMousePosition
()
const
{
return
m_mousePosition
;
}
virtual
const
VECTOR2D
GetMousePosition
()
const
=
0
;
/**
* Function GetCursorPosition()
...
...
@@ -122,10 +119,7 @@ public:
*
* @return The current cursor position in screen coordinates.
*/
virtual
const
VECTOR2D
&
GetCursorPosition
()
const
{
return
m_cursorPosition
;
}
virtual
const
VECTOR2D
GetCursorPosition
()
const
=
0
;
/**
...
...
@@ -140,7 +134,7 @@ public:
m_forceCursorPosition
=
aEnabled
;
}
virtual
void
ShowCursor
(
bool
aEnabled
);
virtual
void
ShowCursor
(
bool
aEnabled
);
protected
:
/// Pointer to controlled VIEW.
...
...
@@ -155,6 +149,9 @@ protected:
/// Forced cursor position
VECTOR2D
m_forcedPosition
;
/// Is the forced cursor position enabled
bool
m_forceCursorPosition
;
/// Should the cursor snap to grid or move freely
bool
m_snappingEnabled
;
...
...
@@ -164,8 +161,6 @@ protected:
/// Flag for turning on autopanning
bool
m_autoPanEnabled
;
bool
m_forceCursorPosition
;
/// Distance from cursor to VIEW edge when panning is active
float
m_autoPanMargin
;
...
...
include/view/view_group.h
View file @
0d4b71ef
...
...
@@ -142,7 +142,7 @@ public:
*
* @return Pointer to the VIEW instance.
*/
KiGfx
::
VIEW
*
GetView
()
const
KiGfx
::
VIEW
*
GetView
()
const
{
return
m_view
;
}
...
...
include/view/view_item.h
View file @
0d4b71ef
...
...
@@ -36,6 +36,104 @@
#include <view/view.h>
#include <gal/definitions.h>
/**
* Enum KICAD_T
* is the set of class identification values, stored in EDA_ITEM::m_StructType
*/
enum
KICAD_T
{
NOT_USED
=
-
1
,
///< the 3d code uses this value
EOT
=
0
,
///< search types array terminator (End Of Types)
TYPE_NOT_INIT
=
0
,
PCB_T
,
SCREEN_T
,
///< not really an item, used to identify a screen
// Items in pcb
PCB_MODULE_T
,
///< class MODULE, a footprint
PCB_PAD_T
,
///< class D_PAD, a pad in a footprint
PCB_LINE_T
,
///< class DRAWSEGMENT, a segment not on copper layers
PCB_TEXT_T
,
///< class TEXTE_PCB, text on a layer
PCB_MODULE_TEXT_T
,
///< class TEXTE_MODULE, text in a footprint
PCB_MODULE_EDGE_T
,
///< class EDGE_MODULE, a footprint edge
PCB_TRACE_T
,
///< class TRACKE, a track segment (segment on a copper layer)
PCB_VIA_T
,
///< class SEGVIA, a via (like a track segment on a copper layer)
PCB_ZONE_T
,
///< class SEGZONE, a segment used to fill a zone area (segment on a
///< copper layer)
PCB_MARKER_T
,
///< class MARKER_PCB, a marker used to show something
PCB_DIMENSION_T
,
///< class DIMENSION, a dimension (graphic item)
PCB_TARGET_T
,
///< class PCB_TARGET, a target (graphic item)
PCB_ZONE_AREA_T
,
///< class ZONE_CONTAINER, a zone area
PCB_ITEM_LIST_T
,
///< class BOARD_ITEM_LIST, a list of board items
// Schematic draw Items. The order of these items effects the sort order.
// It is currently ordered to mimic the old Eeschema locate behavior where
// the smallest item is the selected item.
SCH_MARKER_T
,
SCH_JUNCTION_T
,
SCH_NO_CONNECT_T
,
SCH_BUS_WIRE_ENTRY_T
,
SCH_BUS_BUS_ENTRY_T
,
SCH_LINE_T
,
SCH_BITMAP_T
,
SCH_TEXT_T
,
SCH_LABEL_T
,
SCH_GLOBAL_LABEL_T
,
SCH_HIERARCHICAL_LABEL_T
,
SCH_FIELD_T
,
SCH_COMPONENT_T
,
SCH_SHEET_PIN_T
,
SCH_SHEET_T
,
// Be prudent with these 3 types:
// they should be used only to locate a specific field type
// among SCH_FIELD_T items types
SCH_FIELD_LOCATE_REFERENCE_T
,
SCH_FIELD_LOCATE_VALUE_T
,
SCH_FIELD_LOCATE_FOOTPRINT_T
,
// General
SCH_SCREEN_T
,
/*
* Draw items in library component.
*
* The order of these items effects the sort order for items inside the
* "DRAW/ENDDRAW" section of the component definition in a library file.
* If you add a new draw item, type, please make sure you add it so the
* sort order is logical.
*/
LIB_COMPONENT_T
,
LIB_ALIAS_T
,
LIB_ARC_T
,
LIB_CIRCLE_T
,
LIB_TEXT_T
,
LIB_RECTANGLE_T
,
LIB_POLYLINE_T
,
LIB_BEZIER_T
,
LIB_PIN_T
,
/*
* Fields are not saved inside the "DRAW/ENDDRAW". Add new draw item
* types before this line.
*/
LIB_FIELD_T
,
/*
* For GerbView: items type:
*/
TYPE_GERBER_DRAW_ITEM
,
/*
* for Pl_Editor, in undo/redo commands
*/
TYPE_PL_EDITOR_LAYOUT
,
// End value
MAX_STRUCT_TYPE_ID
};
namespace
KiGfx
{
// Forward declarations
...
...
@@ -81,6 +179,17 @@ public:
delete
[]
m_groups
;
};
/**
* Function Type
* returns the type of object. This attribute should never be changed
* after a constructor sets it, so there is no public "setter" method.
* @return KICAD_T - the type of object.
*/
virtual
KICAD_T
Type
()
const
{
return
NOT_USED
;
}
/**
* Function ViewBBox()
* returns the bounding box of the item covering all its layers.
...
...
include/view/wx_view_controls.h
View file @
0d4b71ef
...
...
@@ -78,6 +78,12 @@ public:
m_state
=
IDLE
;
}
/// @copydoc VIEW_CONTROLS::GetMousePosition()
virtual
const
VECTOR2D
GetMousePosition
()
const
;
/// @copydoc VIEW_CONTROLS::GetCursorPosition()
virtual
const
VECTOR2D
GetCursorPosition
()
const
;
private
:
/// Possible states for WX_VIEW_CONTROLS
enum
State
{
...
...
pcbnew/CMakeLists.txt
View file @
0d4b71ef
...
...
@@ -221,6 +221,7 @@ set(PCBNEW_CLASS_SRCS
tools/selection_tool.cpp
tools/selection_area.cpp
tools/bright_box.cpp
tools/move_tool.cpp
tools/pcb_tools.cpp
)
...
...
pcbnew/basepcbframe.cpp
View file @
0d4b71ef
...
...
@@ -217,6 +217,7 @@ void PCB_BASE_FRAME::ViewReloadBoard( const BOARD* aBoard ) const
view
->
Add
(
worksheet
);
view
->
SetPanBoundary
(
worksheet
->
ViewBBox
()
);
view
->
RecacheAllItems
(
true
);
if
(
m_galCanvasActive
)
...
...
@@ -857,8 +858,17 @@ void PCB_BASE_FRAME::LoadSettings()
view
->
SetRequired
(
ITEM_GAL_LAYER
(
VIAS_HOLES_VISIBLE
),
ITEM_GAL_LAYER
(
VIAS_VISIBLE
)
);
view
->
SetRequired
(
ITEM_GAL_LAYER
(
PADS_HOLES_VISIBLE
),
ITEM_GAL_LAYER
(
PADS_VISIBLE
)
);
view
->
SetRequired
(
ITEM_GAL_LAYER
(
PADS_NETNAMES_VISIBLE
),
ITEM_GAL_LAYER
(
PADS_VISIBLE
)
);
view
->
SetRequired
(
ITEM_GAL_LAYER
(
PAD_FR_NETNAMES_VISIBLE
),
ITEM_GAL_LAYER
(
PAD_FR_VISIBLE
)
);
view
->
SetRequired
(
ADHESIVE_N_FRONT
,
ITEM_GAL_LAYER
(
PAD_FR_VISIBLE
)
);
view
->
SetRequired
(
SOLDERPASTE_N_FRONT
,
ITEM_GAL_LAYER
(
PAD_FR_VISIBLE
)
);
view
->
SetRequired
(
SOLDERMASK_N_FRONT
,
ITEM_GAL_LAYER
(
PAD_FR_VISIBLE
)
);
view
->
SetRequired
(
ITEM_GAL_LAYER
(
PAD_BK_NETNAMES_VISIBLE
),
ITEM_GAL_LAYER
(
PAD_BK_VISIBLE
)
);
view
->
SetRequired
(
ADHESIVE_N_BACK
,
ITEM_GAL_LAYER
(
PAD_BK_VISIBLE
)
);
view
->
SetRequired
(
SOLDERPASTE_N_BACK
,
ITEM_GAL_LAYER
(
PAD_BK_VISIBLE
)
);
view
->
SetRequired
(
SOLDERMASK_N_BACK
,
ITEM_GAL_LAYER
(
PAD_BK_VISIBLE
)
);
view
->
SetLayerTarget
(
ITEM_GAL_LAYER
(
SELECTION
),
KiGfx
::
TARGET_OVERLAY
);
view
->
SetLayerTarget
(
ITEM_GAL_LAYER
(
GP_OVERLAY
),
KiGfx
::
TARGET_OVERLAY
);
...
...
pcbnew/class_dimension.cpp
View file @
0d4b71ef
...
...
@@ -468,6 +468,15 @@ EDA_RECT DIMENSION::GetBoundingBox() const
ymax
=
std
::
max
(
ymax
,
m_featureLineGO
.
y
);
ymax
=
std
::
max
(
ymax
,
m_featureLineGF
.
y
);
xmin
=
std
::
min
(
xmin
,
m_featureLineDO
.
x
);
xmin
=
std
::
min
(
xmin
,
m_featureLineDF
.
x
);
ymin
=
std
::
min
(
ymin
,
m_featureLineDO
.
y
);
ymin
=
std
::
min
(
ymin
,
m_featureLineDF
.
y
);
xmax
=
std
::
max
(
xmax
,
m_featureLineDO
.
x
);
xmax
=
std
::
max
(
xmax
,
m_featureLineDF
.
x
);
ymax
=
std
::
max
(
ymax
,
m_featureLineDO
.
y
);
ymax
=
std
::
max
(
ymax
,
m_featureLineDF
.
y
);
bBox
.
SetX
(
xmin
);
bBox
.
SetY
(
ymin
);
bBox
.
SetWidth
(
xmax
-
xmin
+
1
);
...
...
@@ -489,6 +498,16 @@ wxString DIMENSION::GetSelectMenuText() const
}
const
BOX2I
DIMENSION
::
ViewBBox
()
const
{
BOX2I
dimBBox
=
BOX2I
(
VECTOR2I
(
GetBoundingBox
().
GetPosition
()
),
VECTOR2I
(
GetBoundingBox
().
GetSize
()
)
);
dimBBox
.
Merge
(
m_Text
.
ViewBBox
()
);
return
dimBBox
;
}
void
DIMENSION
::
ViewGetLayers
(
int
aLayers
[],
int
&
aCount
)
const
{
// Layer that simply displays the text
...
...
pcbnew/class_dimension.h
View file @
0d4b71ef
...
...
@@ -144,6 +144,9 @@ public:
EDA_ITEM
*
Clone
()
const
;
/// @copydoc VIEW_ITEM::ViewBBox()
virtual
const
BOX2I
ViewBBox
()
const
;
/// @copydoc VIEW_ITEM::ViewGetLayers()
virtual
void
ViewGetLayers
(
int
aLayers
[],
int
&
aCount
)
const
;
...
...
pcbnew/class_module.cpp
View file @
0d4b71ef
...
...
@@ -1027,6 +1027,7 @@ void MODULE::SetOrientation( double newangle )
void
MODULE
::
ViewGetLayers
(
int
aLayers
[],
int
&
aCount
)
const
{
aCount
=
1
;
aCount
=
2
;
aLayers
[
0
]
=
ITEM_GAL_LAYER
(
SELECTION
);
// Selection box
aLayers
[
1
]
=
m_Layer
;
}
pcbnew/pcb_painter.cpp
View file @
0d4b71ef
...
...
@@ -76,6 +76,7 @@ void PCB_RENDER_SETTINGS::ImportLegacyColors( COLORS_DESIGN_SETTINGS* aSettings
m_layerColors
[
ITEM_GAL_LAYER
(
PAD_FR_NETNAMES_VISIBLE
)]
=
COLOR4D
(
0.8
,
0.8
,
0.8
,
0.7
);
m_layerColors
[
ITEM_GAL_LAYER
(
PAD_BK_NETNAMES_VISIBLE
)]
=
COLOR4D
(
0.8
,
0.8
,
0.8
,
0.7
);
m_layerColors
[
ITEM_GAL_LAYER
(
WORKSHEET
)]
=
COLOR4D
(
0.5
,
0.0
,
0.0
,
1.0
);
m_layerColors
[
ITEM_GAL_LAYER
(
SELECTION
)]
=
COLOR4D
(
1.0
,
1.0
,
1.0
,
0.5
);
// Netnames for copper layers
for
(
LAYER_NUM
layer
=
FIRST_COPPER_LAYER
;
layer
<=
LAST_COPPER_LAYER
;
++
layer
)
...
...
@@ -205,10 +206,8 @@ PCB_PAINTER::PCB_PAINTER( GAL* aGal ) :
bool
PCB_PAINTER
::
Draw
(
const
VIEW_ITEM
*
aItem
,
int
aLayer
)
{
const
BOARD_ITEM
*
item
=
static_cast
<
const
BOARD_ITEM
*>
(
aItem
);
// the "cast" applied in here clarifies which overloaded draw() is called
switch
(
i
tem
->
Type
()
)
switch
(
aI
tem
->
Type
()
)
{
case
PCB_ZONE_T
:
case
PCB_TRACE_T
:
...
...
@@ -229,7 +228,7 @@ bool PCB_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer )
break
;
case
PCB_MODULE_T
:
draw
(
(
MODULE
*
)
aItem
);
draw
(
(
MODULE
*
)
aItem
,
aLayer
);
break
;
case
PCB_TEXT_T
:
...
...
@@ -273,7 +272,7 @@ void PCB_PAINTER::draw( const TRACK* aTrack, int aLayer )
if
(
m_pcbSettings
->
m_netNamesOnTracks
&&
IsNetnameLayer
(
aLayer
)
)
{
// If there is a net name - display it on the track
if
(
netNumber
!=
0
)
if
(
netNumber
>
0
)
{
VECTOR2D
line
=
(
end
-
start
);
double
length
=
line
.
EuclideanNorm
();
...
...
@@ -283,7 +282,7 @@ void PCB_PAINTER::draw( const TRACK* aTrack, int aLayer )
return
;
NETINFO_ITEM
*
net
=
(
(
BOARD
*
)
aTrack
->
GetParent
()
)
->
FindNet
(
netNumber
);
if
(
!
net
)
if
(
!
net
)
return
;
std
::
string
netName
=
std
::
string
(
net
->
GetShortNetname
().
mb_str
()
);
...
...
@@ -631,7 +630,7 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer )
void
PCB_PAINTER
::
draw
(
const
DRAWSEGMENT
*
aSegment
)
{
COLOR4D
color
=
m_pcbSettings
->
GetColor
(
NULL
,
aSegment
->
GetLayer
()
);
COLOR4D
color
=
m_pcbSettings
->
GetColor
(
aSegment
,
aSegment
->
GetLayer
()
);
m_gal
->
SetIsFill
(
false
);
m_gal
->
SetIsStroke
(
true
);
...
...
@@ -700,11 +699,14 @@ void PCB_PAINTER::draw( const DRAWSEGMENT* aSegment )
}
void
PCB_PAINTER
::
draw
(
const
MODULE
*
aModule
)
void
PCB_PAINTER
::
draw
(
const
MODULE
*
aModule
,
int
aLayer
)
{
// For modules we have to draw a selection box if needed
if
(
aModule
->
IsSelected
()
)
drawSelectionBox
(
aModule
);
if
(
aLayer
==
ITEM_GAL_LAYER
(
SELECTION
)
)
{
if
(
aModule
->
IsSelected
()
)
drawSelectionBox
(
aModule
);
}
}
...
...
@@ -720,7 +722,7 @@ void PCB_PAINTER::draw( const TEXTE_PCB* aText, int aLayer )
if
(
aText
->
GetText
().
Length
()
==
0
)
return
;
COLOR4D
strokeColor
=
m_pcbSettings
->
GetColor
(
NULL
,
aText
->
GetLayer
()
);
COLOR4D
strokeColor
=
m_pcbSettings
->
GetColor
(
aText
,
aText
->
GetLayer
()
);
VECTOR2D
position
(
aText
->
GetTextPosition
().
x
,
aText
->
GetTextPosition
().
y
);
double
orientation
=
aText
->
GetOrientation
()
*
M_PI
/
1800.0
;
...
...
@@ -744,7 +746,7 @@ void PCB_PAINTER::draw( const TEXTE_MODULE* aText, int aLayer )
if
(
aText
->
GetLength
()
==
0
)
return
;
COLOR4D
strokeColor
=
m_pcbSettings
->
GetColor
(
NULL
,
aLayer
);
COLOR4D
strokeColor
=
m_pcbSettings
->
GetColor
(
aText
,
aLayer
);
VECTOR2D
position
(
aText
->
GetTextPosition
().
x
,
aText
->
GetTextPosition
().
y
);
double
orientation
=
aText
->
GetDrawRotation
()
*
M_PI
/
1800.0
;
...
...
@@ -759,7 +761,7 @@ void PCB_PAINTER::draw( const TEXTE_MODULE* aText, int aLayer )
void
PCB_PAINTER
::
draw
(
const
ZONE_CONTAINER
*
aZone
)
{
COLOR4D
color
=
m_pcbSettings
->
GetColor
(
NULL
,
aZone
->
GetLayer
()
);
COLOR4D
color
=
m_pcbSettings
->
GetColor
(
aZone
,
aZone
->
GetLayer
()
);
std
::
deque
<
VECTOR2D
>
corners
;
PCB_RENDER_SETTINGS
::
DisplayZonesMode
displayMode
=
m_pcbSettings
->
m_displayZoneMode
;
...
...
@@ -836,7 +838,7 @@ void PCB_PAINTER::draw( const DIMENSION* aDimension, int aLayer )
else
{
int
layer
=
aDimension
->
GetLayer
();
COLOR4D
strokeColor
=
m_pcbSettings
->
GetColor
(
NULL
,
layer
);
COLOR4D
strokeColor
=
m_pcbSettings
->
GetColor
(
aDimension
,
layer
);
m_gal
->
SetStrokeColor
(
strokeColor
);
m_gal
->
SetIsFill
(
false
);
...
...
@@ -855,14 +857,20 @@ void PCB_PAINTER::draw( const DIMENSION* aDimension, int aLayer )
m_gal
->
DrawLine
(
VECTOR2D
(
aDimension
->
m_arrowG2O
),
VECTOR2D
(
aDimension
->
m_arrowG2F
)
);
// Draw text
draw
(
&
aDimension
->
Text
(),
layer
);
TEXTE_PCB
&
text
=
aDimension
->
Text
();
VECTOR2D
position
(
text
.
GetTextPosition
().
x
,
text
.
GetTextPosition
().
y
);
double
orientation
=
text
.
GetOrientation
()
*
M_PI
/
1800.0
;
m_gal
->
SetLineWidth
(
text
.
GetThickness
()
);
m_gal
->
SetTextAttributes
(
&
text
);
m_gal
->
StrokeText
(
std
::
string
(
text
.
GetText
().
mb_str
()
),
position
,
orientation
);
}
}
void
PCB_PAINTER
::
draw
(
const
PCB_TARGET
*
aTarget
)
{
COLOR4D
strokeColor
=
m_pcbSettings
->
GetColor
(
NULL
,
aTarget
->
GetLayer
()
);
COLOR4D
strokeColor
=
m_pcbSettings
->
GetColor
(
aTarget
,
aTarget
->
GetLayer
()
);
VECTOR2D
position
(
aTarget
->
GetPosition
()
);
double
size
,
radius
;
...
...
@@ -888,10 +896,8 @@ void PCB_PAINTER::draw( const PCB_TARGET* aTarget )
radius
=
aTarget
->
GetSize
()
/
3.0
;
}
m_gal
->
DrawLine
(
VECTOR2D
(
-
size
,
0.0
),
VECTOR2D
(
size
,
0.0
)
);
m_gal
->
DrawLine
(
VECTOR2D
(
0.0
,
-
size
),
VECTOR2D
(
0.0
,
size
)
);
m_gal
->
DrawLine
(
VECTOR2D
(
-
size
,
0.0
),
VECTOR2D
(
size
,
0.0
)
);
m_gal
->
DrawLine
(
VECTOR2D
(
0.0
,
-
size
),
VECTOR2D
(
0.0
,
size
)
);
m_gal
->
DrawCircle
(
VECTOR2D
(
0.0
,
0.0
),
radius
);
m_gal
->
Restore
();
...
...
@@ -904,6 +910,6 @@ void PCB_PAINTER::drawSelectionBox( const VIEW_ITEM* aItem ) const
m_gal
->
SetIsStroke
(
false
);
m_gal
->
SetIsFill
(
true
);
m_gal
->
SetFillColor
(
COLOR4D
(
1.0
,
1.0
,
1.0
,
0.5
)
);
m_gal
->
SetFillColor
(
m_pcbSettings
->
GetLayerColor
(
ITEM_GAL_LAYER
(
SELECTION
)
)
);
m_gal
->
DrawRectangle
(
boundingBox
.
GetOrigin
(),
boundingBox
.
GetEnd
()
);
}
pcbnew/pcb_painter.h
View file @
0d4b71ef
...
...
@@ -145,7 +145,7 @@ protected:
void
draw
(
const
SEGVIA
*
,
int
);
void
draw
(
const
D_PAD
*
,
int
);
void
draw
(
const
DRAWSEGMENT
*
);
void
draw
(
const
MODULE
*
);
void
draw
(
const
MODULE
*
,
int
);
void
draw
(
const
TEXTE_PCB
*
,
int
);
void
draw
(
const
TEXTE_MODULE
*
,
int
);
void
draw
(
const
ZONE_CONTAINER
*
);
...
...
pcbnew/pcbframe.cpp
View file @
0d4b71ef
...
...
@@ -767,8 +767,7 @@ void PCB_EDIT_FRAME::setHighContrastLayer( LAYER_NUM aLayer )
LAYER_NUM
layers
[]
=
{
GetNetnameLayer
(
aLayer
),
ITEM_GAL_LAYER
(
VIAS_VISIBLE
),
ITEM_GAL_LAYER
(
VIAS_HOLES_VISIBLE
),
ITEM_GAL_LAYER
(
PADS_VISIBLE
),
ITEM_GAL_LAYER
(
PADS_HOLES_VISIBLE
),
ITEM_GAL_LAYER
(
PADS_NETNAMES_VISIBLE
),
ITEM_GAL_LAYER
(
SELECTION
)
ITEM_GAL_LAYER
(
PADS_HOLES_VISIBLE
),
ITEM_GAL_LAYER
(
PADS_NETNAMES_VISIBLE
)
};
for
(
unsigned
int
i
=
0
;
i
<
sizeof
(
layers
)
/
sizeof
(
LAYER_NUM
);
++
i
)
...
...
pcbnew/tools/bright_box.cpp
0 → 100644
View file @
0d4b71ef
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "bright_box.h"
#include <gal/graphics_abstraction_layer.h>
#include <class_track.h>
using
namespace
KiGfx
;
BRIGHT_BOX
::
BRIGHT_BOX
(
BOARD_ITEM
*
aItem
)
:
EDA_ITEM
(
NOT_USED
),
// this item is never added to a BOARD so it needs no type
item
(
aItem
)
{
}
const
BOX2I
BRIGHT_BOX
::
ViewBBox
()
const
{
return
item
->
ViewBBox
();
}
void
BRIGHT_BOX
::
ViewGetLayers
(
int
aLayers
[],
int
&
aCount
)
const
{
aLayers
[
0
]
=
BrightBoxLayer
;
aCount
=
1
;
}
void
BRIGHT_BOX
::
ViewDraw
(
int
aLayer
,
GAL
*
aGal
)
const
{
aGal
->
SetIsStroke
(
true
);
aGal
->
SetIsFill
(
false
);
aGal
->
SetLineWidth
(
LineWidth
);
aGal
->
SetStrokeColor
(
BrightColor
);
if
(
item
->
Type
()
==
PCB_TRACE_T
)
{
const
TRACK
*
track
=
static_cast
<
const
TRACK
*>
(
item
);
aGal
->
DrawSegment
(
track
->
GetStart
(),
track
->
GetEnd
(),
track
->
GetWidth
()
);
}
else
{
BOX2I
box
=
item
->
ViewBBox
();
aGal
->
DrawRectangle
(
box
.
GetOrigin
(),
box
.
GetOrigin
()
+
box
.
GetSize
()
);
}
}
const
COLOR4D
BRIGHT_BOX
::
BrightColor
=
KiGfx
::
COLOR4D
(
0.0
,
1.0
,
0.0
,
1.0
);
pcbnew/tools/bright_box.h
0 → 100644
View file @
0d4b71ef
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __BRIGHT_BOX_H
#define __BRIGHT_BOX_H
#include <math/box2.h>
#include <view/view.h>
#include <class_board_item.h>
#include <layers_id_colors_and_visibility.h>
#include <gal/color4d.h>
/**
* Class BRIGHT_BOX
*
* Draws a decoration to indicate a brightened item.
*/
class
BRIGHT_BOX
:
public
EDA_ITEM
{
public
:
BRIGHT_BOX
(
BOARD_ITEM
*
aItem
);
~
BRIGHT_BOX
()
{};
virtual
const
BOX2I
ViewBBox
()
const
;
void
ViewDraw
(
int
aLayer
,
KiGfx
::
GAL
*
aGal
)
const
;
void
ViewGetLayers
(
int
aLayers
[],
int
&
aCount
)
const
;
void
Show
(
int
x
,
std
::
ostream
&
st
)
const
{
}
private
:
static
const
int
BrightBoxLayer
=
ITEM_GAL_LAYER
(
SELECTION
);
static
const
KiGfx
::
COLOR4D
BrightColor
;
static
const
double
LineWidth
=
100000
.
0
;
BOARD_ITEM
*
item
;
};
#endif
pcbnew/tools/selection_area.cpp
View file @
0d4b71ef
...
...
@@ -22,11 +22,9 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <wx/wx.h>
#include <layers_id_colors_and_visibility.h>
#include "selection_area.h"
#include <gal/graphics_abstraction_layer.h>
#include <gal/color4d.h>
using
namespace
KiGfx
;
...
...
@@ -47,7 +45,7 @@ void SELECTION_AREA::ViewGetLayers( int aLayers[], int& aCount ) const
}
void
SELECTION_AREA
::
ViewDraw
(
int
aLayer
,
GAL
*
aGal
)
const
void
SELECTION_AREA
::
ViewDraw
(
int
aLayer
,
KiGfx
::
GAL
*
aGal
)
const
{
aGal
->
SetLineWidth
(
1.0
);
aGal
->
SetStrokeColor
(
COLOR4D
(
1.0
,
1.0
,
0.4
,
1.0
)
);
...
...
pcbnew/tools/selection_area.h
View file @
0d4b71ef
...
...
@@ -25,15 +25,14 @@
#ifndef __SELECTION_AREA_H
#define __SELECTION_AREA_H
#include <tool/tool_event.h>
#include <tool/tool_manager.h>
#include <math/box2.h>
#include <view/view.h>
#include <gal/graphics_abstraction_layer.h>
#include <base_struct.h>
#include <layers_id_colors_and_visibility.h>
#include <math/box2.h>
namespace
KiGfx
{
class
GAL
;
}
/**
* Class SELECTION_AREA
...
...
pcbnew/tools/selection_tool.cpp
View file @
0d4b71ef
...
...
@@ -34,11 +34,15 @@
#include <wxPcbStruct.h>
#include <collectors.h>
#include <view/view_controls.h>
#include <painter.h>
#include <tool/context_menu.h>
#include <tool/tool_event.h>
#include <tool/tool_manager.h>
#include "selection_tool.h"
#include "selection_area.h"
#include "bright_box.h"
using
namespace
KiGfx
;
using
boost
::
optional
;
...
...
@@ -115,7 +119,8 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent )
// Check if dragging event started within the currently selected items bounding box
std
::
set
<
BOARD_ITEM
*>::
iterator
it
,
it_end
;
for
(
it
=
m_selectedItems
.
begin
(),
it_end
=
m_selectedItems
.
end
();
it
!=
it_end
;
++
it
)
for
(
it
=
m_selectedItems
.
begin
(),
it_end
=
m_selectedItems
.
end
();
it
!=
it_end
;
++
it
)
{
BOX2I
itemBox
=
(
*
it
)
->
ViewBBox
();
itemBox
.
Inflate
(
500000
);
// Give some margin for gripping an item
...
...
@@ -204,12 +209,12 @@ void SELECTION_TOOL::selectSingle( const VECTOR2I& aWhere )
break
;
default
:
// Remove
footprint
s, they have to be selected by clicking on area that does not
// contain anything but
footprint
for
(
int
i
=
0
;
i
<
collector
.
GetCount
();
++
i
)
// Remove
module
s, they have to be selected by clicking on area that does not
// contain anything but
module footprint and not selectable items
for
(
int
i
=
collector
.
GetCount
()
-
1
;
i
>=
0
;
--
i
)
{
BOARD_ITEM
*
boardItem
=
(
collector
)[
i
];
if
(
boardItem
->
Type
()
==
PCB_MODULE_T
)
if
(
boardItem
->
Type
()
==
PCB_MODULE_T
||
!
selectable
(
boardItem
)
)
collector
.
Remove
(
i
);
}
...
...
@@ -218,7 +223,7 @@ void SELECTION_TOOL::selectSingle( const VECTOR2I& aWhere )
{
toggleSelection
(
collector
[
0
]
);
}
else
else
if
(
collector
.
GetCount
()
>
1
)
{
item
=
disambiguationMenu
(
&
collector
);
if
(
item
)
...
...
@@ -332,8 +337,8 @@ bool SELECTION_TOOL::selectMultiple()
BOARD_ITEM
*
SELECTION_TOOL
::
disambiguationMenu
(
GENERAL_COLLECTOR
*
aCollector
)
{
OPT_TOOL_EVENT
evt
;
BOARD_ITEM
*
current
=
NULL
;
boost
::
shared_ptr
<
BRIGHT_BOX
>
brightBox
;
m_menu
.
reset
(
new
CONTEXT_MENU
()
);
m_menu
->
SetTitle
(
_
(
"Clarify selection"
)
);
...
...
@@ -350,10 +355,11 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector )
SetContextMenu
(
m_menu
.
get
(),
CMENU_NOW
);
while
(
evt
=
Wait
()
)
while
(
OPT_TOOL_EVENT
evt
=
Wait
()
)
{
if
(
evt
->
Action
()
==
TA_ContextMenuUpdate
)
{
// User has pointed an item, so show it in a different way
if
(
current
)
current
->
ClearBrightened
();
...
...
@@ -378,21 +384,51 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector )
{
current
=
(
*
aCollector
)[
*
id
];
current
->
SetSelected
();
return
current
;
}
return
NULL
;
break
;
}
if
(
current
&&
current
->
IsBrightened
()
)
{
brightBox
.
reset
(
new
BRIGHT_BOX
(
current
)
);
getView
()
->
Add
(
brightBox
.
get
()
);
}
}
return
NULL
;
getView
()
->
MarkTargetDirty
(
TARGET_OVERLAY
);
return
current
;
}
bool
SELECTION_TOOL
::
selectable
(
const
BOARD_ITEM
*
aItem
)
{
BOARD
*
board
=
getModel
<
BOARD
>
(
PCB_T
);
bool
highContrast
=
getView
()
->
GetPainter
()
->
GetSettings
()
->
GetHighContrast
();
if
(
highContrast
)
{
bool
onActive
=
false
;
int
layers
[
KiGfx
::
VIEW
::
VIEW_MAX_LAYERS
],
layers_count
;
// Filter out items that do not belong to active layers
std
::
set
<
unsigned
int
>
activeLayers
=
getView
()
->
GetPainter
()
->
GetSettings
()
->
GetActiveLayers
();
aItem
->
ViewGetLayers
(
layers
,
layers_count
);
for
(
int
i
=
0
;
i
<
layers_count
;
++
i
)
{
if
(
activeLayers
.
count
(
layers
[
i
]
)
>
0
)
// Item is on at least one active layer
{
onActive
=
true
;
break
;
}
}
if
(
!
onActive
)
return
false
;
}
BOARD
*
board
=
getModel
<
BOARD
>
(
PCB_T
);
switch
(
aItem
->
Type
()
)
{
case
PCB_VIA_T
:
...
...
polygon/poly2tri/common/utils.h
View file @
0d4b71ef
/*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UTILS_H
#define UTILS_H
// Otherwise #defines like M_PI are undeclared under Visual Studio
#define _USE_MATH_DEFINES
#include <exception>
#include <math.h>
namespace
p2t
{
const
double
PI_3div4
=
3
*
M_PI
/
4
;
const
double
PI_div2
=
1
.
57079632679489661923
;
const
double
EPSILON
=
1e-12
;
enum
Orientation
{
CW
,
CCW
,
COLLINEAR
};
/**
* Forumla to calculate signed area<br>
* Positive if CCW<br>
* Negative if CW<br>
* 0 if collinear<br>
* <pre>
* A[P1,P2,P3] = (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)
* = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
* </pre>
*/
Orientation
Orient2d
(
Point
&
pa
,
Point
&
pb
,
Point
&
pc
)
{
double
detleft
=
(
pa
.
x
-
pc
.
x
)
*
(
pb
.
y
-
pc
.
y
);
double
detright
=
(
pa
.
y
-
pc
.
y
)
*
(
pb
.
x
-
pc
.
x
);
double
val
=
detleft
-
detright
;
if
(
val
>
-
EPSILON
&&
val
<
EPSILON
)
{
return
COLLINEAR
;
}
else
if
(
val
>
0
)
{
return
CCW
;
}
return
CW
;
}
/*
bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
{
double pdx = pd.x;
double pdy = pd.y;
double adx = pa.x - pdx;
double ady = pa.y - pdy;
double bdx = pb.x - pdx;
double bdy = pb.y - pdy;
double adxbdy = adx * bdy;
double bdxady = bdx * ady;
double oabd = adxbdy - bdxady;
if (oabd <= EPSILON) {
return false;
}
double cdx = pc.x - pdx;
double cdy = pc.y - pdy;
double cdxady = cdx * ady;
double adxcdy = adx * cdy;
double ocad = cdxady - adxcdy;
if (ocad <= EPSILON) {
return false;
}
return true;
}
*/
bool
InScanArea
(
Point
&
pa
,
Point
&
pb
,
Point
&
pc
,
Point
&
pd
)
{
double
oadb
=
(
pa
.
x
-
pb
.
x
)
*
(
pd
.
y
-
pb
.
y
)
-
(
pd
.
x
-
pb
.
x
)
*
(
pa
.
y
-
pb
.
y
);
if
(
oadb
>=
-
EPSILON
)
{
return
false
;
}
double
oadc
=
(
pa
.
x
-
pc
.
x
)
*
(
pd
.
y
-
pc
.
y
)
-
(
pd
.
x
-
pc
.
x
)
*
(
pa
.
y
-
pc
.
y
);
if
(
oadc
<=
EPSILON
)
{
return
false
;
}
return
true
;
}
}
#endif
/*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UTILS_H
#define UTILS_H
// Otherwise #defines like M_PI are undeclared under Visual Studio
#define _USE_MATH_DEFINES
#include <exception>
#include <math.h>
namespace
p2t
{
const
double
PI_3div4
=
3
*
M_PI
/
4
;
const
double
PI_div2
=
1
.
57079632679489661923
;
const
double
EPSILON
=
1e-12
;
enum
Orientation
{
CW
,
CCW
,
COLLINEAR
};
/**
* Forumla to calculate signed area<br>
* Positive if CCW<br>
* Negative if CW<br>
* 0 if collinear<br>
* <pre>
* A[P1,P2,P3] = (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)
* = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
* </pre>
*/
Orientation
Orient2d
(
Point
&
pa
,
Point
&
pb
,
Point
&
pc
)
{
double
detleft
=
(
pa
.
x
-
pc
.
x
)
*
(
pb
.
y
-
pc
.
y
);
double
detright
=
(
pa
.
y
-
pc
.
y
)
*
(
pb
.
x
-
pc
.
x
);
double
val
=
detleft
-
detright
;
if
(
val
>
-
EPSILON
&&
val
<
EPSILON
)
{
return
COLLINEAR
;
}
else
if
(
val
>
0
)
{
return
CCW
;
}
return
CW
;
}
/*
bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
{
double pdx = pd.x;
double pdy = pd.y;
double adx = pa.x - pdx;
double ady = pa.y - pdy;
double bdx = pb.x - pdx;
double bdy = pb.y - pdy;
double adxbdy = adx * bdy;
double bdxady = bdx * ady;
double oabd = adxbdy - bdxady;
if (oabd <= EPSILON) {
return false;
}
double cdx = pc.x - pdx;
double cdy = pc.y - pdy;
double cdxady = cdx * ady;
double adxcdy = adx * cdy;
double ocad = cdxady - adxcdy;
if (ocad <= EPSILON) {
return false;
}
return true;
}
*/
bool
InScanArea
(
Point
&
pa
,
Point
&
pb
,
Point
&
pc
,
Point
&
pd
)
{
double
oadb
=
(
pa
.
x
-
pb
.
x
)
*
(
pd
.
y
-
pb
.
y
)
-
(
pd
.
x
-
pb
.
x
)
*
(
pa
.
y
-
pb
.
y
);
if
(
oadb
>=
-
EPSILON
)
{
return
false
;
}
double
oadc
=
(
pa
.
x
-
pc
.
x
)
*
(
pd
.
y
-
pc
.
y
)
-
(
pd
.
x
-
pc
.
x
)
*
(
pa
.
y
-
pc
.
y
);
if
(
oadc
<=
EPSILON
)
{
return
false
;
}
return
true
;
}
}
#endif
polygon/poly2tri/sweep/cdt.cc
View file @
0d4b71ef
/*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "cdt.h"
namespace
p2t
{
CDT
::
CDT
(
std
::
vector
<
Point
*>
polyline
)
{
sweep_context_
=
new
SweepContext
(
polyline
);
sweep_
=
new
Sweep
;
}
void
CDT
::
AddHole
(
std
::
vector
<
Point
*>
polyline
)
{
sweep_context_
->
AddHole
(
polyline
);
}
void
CDT
::
AddPoint
(
Point
*
point
)
{
sweep_context_
->
AddPoint
(
point
);
}
void
CDT
::
Triangulate
()
{
sweep_
->
Triangulate
(
*
sweep_context_
);
}
std
::
vector
<
p2t
::
Triangle
*>
CDT
::
GetTriangles
()
{
return
sweep_context_
->
GetTriangles
();
}
std
::
list
<
p2t
::
Triangle
*>
CDT
::
GetMap
()
{
return
sweep_context_
->
GetMap
();
}
CDT
::~
CDT
()
{
delete
sweep_context_
;
delete
sweep_
;
}
}
/*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "cdt.h"
namespace
p2t
{
CDT
::
CDT
(
std
::
vector
<
Point
*>
polyline
)
{
sweep_context_
=
new
SweepContext
(
polyline
);
sweep_
=
new
Sweep
;
}
void
CDT
::
AddHole
(
std
::
vector
<
Point
*>
polyline
)
{
sweep_context_
->
AddHole
(
polyline
);
}
void
CDT
::
AddPoint
(
Point
*
point
)
{
sweep_context_
->
AddPoint
(
point
);
}
void
CDT
::
Triangulate
()
{
sweep_
->
Triangulate
(
*
sweep_context_
);
}
std
::
vector
<
p2t
::
Triangle
*>
CDT
::
GetTriangles
()
{
return
sweep_context_
->
GetTriangles
();
}
std
::
list
<
p2t
::
Triangle
*>
CDT
::
GetMap
()
{
return
sweep_context_
->
GetMap
();
}
CDT
::~
CDT
()
{
delete
sweep_context_
;
delete
sweep_
;
}
}
polygon/poly2tri/sweep/cdt.h
View file @
0d4b71ef
/*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CDT_H
#define CDT_H
#include "advancing_front.h"
#include "sweep_context.h"
#include "sweep.h"
/**
*
* @author Mason Green <mason.green@gmail.com>
*
*/
namespace
p2t
{
class
CDT
{
public
:
/**
* Constructor - add polyline with non repeating points
*
* @param polyline
*/
CDT
(
std
::
vector
<
Point
*>
polyline
);
/**
* Destructor - clean up memory
*/
~
CDT
();
/**
* Add a hole
*
* @param polyline
*/
void
AddHole
(
std
::
vector
<
Point
*>
polyline
);
/**
* Add a steiner point
*
* @param point
*/
void
AddPoint
(
Point
*
point
);
/**
* Triangulate - do this AFTER you've added the polyline, holes, and Steiner points
*/
void
Triangulate
();
/**
* Get CDT triangles
*/
std
::
vector
<
Triangle
*>
GetTriangles
();
/**
* Get triangle map
*/
std
::
list
<
Triangle
*>
GetMap
();
private
:
/**
* Internals
*/
SweepContext
*
sweep_context_
;
Sweep
*
sweep_
;
};
}
#endif
/*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CDT_H
#define CDT_H
#include "advancing_front.h"
#include "sweep_context.h"
#include "sweep.h"
/**
*
* @author Mason Green <mason.green@gmail.com>
*
*/
namespace
p2t
{
class
CDT
{
public
:
/**
* Constructor - add polyline with non repeating points
*
* @param polyline
*/
CDT
(
std
::
vector
<
Point
*>
polyline
);
/**
* Destructor - clean up memory
*/
~
CDT
();
/**
* Add a hole
*
* @param polyline
*/
void
AddHole
(
std
::
vector
<
Point
*>
polyline
);
/**
* Add a steiner point
*
* @param point
*/
void
AddPoint
(
Point
*
point
);
/**
* Triangulate - do this AFTER you've added the polyline, holes, and Steiner points
*/
void
Triangulate
();
/**
* Get CDT triangles
*/
std
::
vector
<
Triangle
*>
GetTriangles
();
/**
* Get triangle map
*/
std
::
list
<
Triangle
*>
GetMap
();
private
:
/**
* Internals
*/
SweepContext
*
sweep_context_
;
Sweep
*
sweep_
;
};
}
#endif
polygon/poly2tri/sweep/sweep.cc
View file @
0d4b71ef
/*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdexcept>
#include "sweep.h"
#include "sweep_context.h"
#include "advancing_front.h"
#include "../common/utils.h"
namespace
p2t
{
// Triangulate simple polygon with holes
void
Sweep
::
Triangulate
(
SweepContext
&
tcx
)
{
tcx
.
InitTriangulation
();
tcx
.
CreateAdvancingFront
(
nodes_
);
// Sweep points; build mesh
SweepPoints
(
tcx
);
// Clean up
FinalizationPolygon
(
tcx
);
}
void
Sweep
::
SweepPoints
(
SweepContext
&
tcx
)
{
for
(
int
i
=
1
;
i
<
tcx
.
point_count
();
i
++
)
{
Point
&
point
=
*
tcx
.
GetPoint
(
i
);
Node
*
node
=
&
PointEvent
(
tcx
,
point
);
for
(
unsigned
int
i
=
0
;
i
<
point
.
edge_list
.
size
();
i
++
)
{
EdgeEvent
(
tcx
,
point
.
edge_list
[
i
],
node
);
}
}
}
void
Sweep
::
FinalizationPolygon
(
SweepContext
&
tcx
)
{
// Get an Internal triangle to start with
Triangle
*
t
=
tcx
.
front
()
->
head
()
->
next
->
triangle
;
Point
*
p
=
tcx
.
front
()
->
head
()
->
next
->
point
;
while
(
!
t
->
GetConstrainedEdgeCW
(
*
p
))
{
t
=
t
->
NeighborCCW
(
*
p
);
}
// Collect interior triangles constrained by edges
tcx
.
MeshClean
(
*
t
);
}
Node
&
Sweep
::
PointEvent
(
SweepContext
&
tcx
,
Point
&
point
)
{
Node
&
node
=
tcx
.
LocateNode
(
point
);
Node
&
new_node
=
NewFrontTriangle
(
tcx
,
point
,
node
);
// Only need to check +epsilon since point never have smaller
// x value than node due to how we fetch nodes from the front
if
(
point
.
x
<=
node
.
point
->
x
+
EPSILON
)
{
Fill
(
tcx
,
node
);
}
//tcx.AddNode(new_node);
FillAdvancingFront
(
tcx
,
new_node
);
return
new_node
;
}
void
Sweep
::
EdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
*
node
)
{
tcx
.
edge_event
.
constrained_edge
=
edge
;
tcx
.
edge_event
.
right
=
(
edge
->
p
->
x
>
edge
->
q
->
x
);
if
(
IsEdgeSideOfTriangle
(
*
node
->
triangle
,
*
edge
->
p
,
*
edge
->
q
))
{
return
;
}
// For now we will do all needed filling
// TODO: integrate with flip process might give some better performance
// but for now this avoid the issue with cases that needs both flips and fills
FillEdgeEvent
(
tcx
,
edge
,
node
);
EdgeEvent
(
tcx
,
*
edge
->
p
,
*
edge
->
q
,
node
->
triangle
,
*
edge
->
q
);
}
void
Sweep
::
EdgeEvent
(
SweepContext
&
tcx
,
Point
&
ep
,
Point
&
eq
,
Triangle
*
triangle
,
Point
&
point
)
{
if
(
IsEdgeSideOfTriangle
(
*
triangle
,
ep
,
eq
))
{
return
;
}
Point
*
p1
=
triangle
->
PointCCW
(
point
);
Orientation
o1
=
Orient2d
(
eq
,
*
p1
,
ep
);
if
(
o1
==
COLLINEAR
)
{
if
(
triangle
->
Contains
(
&
eq
,
p1
))
{
triangle
->
MarkConstrainedEdge
(
&
eq
,
p1
);
// We are modifying the constraint maybe it would be better to
// not change the given constraint and just keep a variable for the new constraint
tcx
.
edge_event
.
constrained_edge
->
q
=
p1
;
triangle
=
&
triangle
->
NeighborAcross
(
point
);
EdgeEvent
(
tcx
,
ep
,
*
p1
,
triangle
,
*
p1
);
}
else
{
std
::
runtime_error
(
"EdgeEvent - collinear points not supported"
);
assert
(
0
);
}
return
;
}
Point
*
p2
=
triangle
->
PointCW
(
point
);
Orientation
o2
=
Orient2d
(
eq
,
*
p2
,
ep
);
if
(
o2
==
COLLINEAR
)
{
if
(
triangle
->
Contains
(
&
eq
,
p2
))
{
triangle
->
MarkConstrainedEdge
(
&
eq
,
p2
);
// We are modifying the constraint maybe it would be better to
// not change the given constraint and just keep a variable for the new constraint
tcx
.
edge_event
.
constrained_edge
->
q
=
p2
;
triangle
=
&
triangle
->
NeighborAcross
(
point
);
EdgeEvent
(
tcx
,
ep
,
*
p2
,
triangle
,
*
p2
);
}
else
{
std
::
runtime_error
(
"EdgeEvent - collinear points not supported"
);
assert
(
0
);
}
return
;
}
if
(
o1
==
o2
)
{
// Need to decide if we are rotating CW or CCW to get to a triangle
// that will cross edge
if
(
o1
==
CW
)
{
triangle
=
triangle
->
NeighborCCW
(
point
);
}
else
{
triangle
=
triangle
->
NeighborCW
(
point
);
}
EdgeEvent
(
tcx
,
ep
,
eq
,
triangle
,
point
);
}
else
{
// This triangle crosses constraint so lets flippin start!
FlipEdgeEvent
(
tcx
,
ep
,
eq
,
triangle
,
point
);
}
}
bool
Sweep
::
IsEdgeSideOfTriangle
(
Triangle
&
triangle
,
Point
&
ep
,
Point
&
eq
)
{
int
index
=
triangle
.
EdgeIndex
(
&
ep
,
&
eq
);
if
(
index
!=
-
1
)
{
triangle
.
MarkConstrainedEdge
(
index
);
Triangle
*
t
=
triangle
.
GetNeighbor
(
index
);
if
(
t
)
{
t
->
MarkConstrainedEdge
(
&
ep
,
&
eq
);
}
return
true
;
}
return
false
;
}
Node
&
Sweep
::
NewFrontTriangle
(
SweepContext
&
tcx
,
Point
&
point
,
Node
&
node
)
{
Triangle
*
triangle
=
new
Triangle
(
point
,
*
node
.
point
,
*
node
.
next
->
point
);
triangle
->
MarkNeighbor
(
*
node
.
triangle
);
tcx
.
AddToMap
(
triangle
);
Node
*
new_node
=
new
Node
(
point
);
nodes_
.
push_back
(
new_node
);
new_node
->
next
=
node
.
next
;
new_node
->
prev
=
&
node
;
node
.
next
->
prev
=
new_node
;
/*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdexcept>
#include "sweep.h"
#include "sweep_context.h"
#include "advancing_front.h"
#include "../common/utils.h"
namespace
p2t
{
// Triangulate simple polygon with holes
void
Sweep
::
Triangulate
(
SweepContext
&
tcx
)
{
tcx
.
InitTriangulation
();
tcx
.
CreateAdvancingFront
(
nodes_
);
// Sweep points; build mesh
SweepPoints
(
tcx
);
// Clean up
FinalizationPolygon
(
tcx
);
}
void
Sweep
::
SweepPoints
(
SweepContext
&
tcx
)
{
for
(
int
i
=
1
;
i
<
tcx
.
point_count
();
i
++
)
{
Point
&
point
=
*
tcx
.
GetPoint
(
i
);
Node
*
node
=
&
PointEvent
(
tcx
,
point
);
for
(
unsigned
int
i
=
0
;
i
<
point
.
edge_list
.
size
();
i
++
)
{
EdgeEvent
(
tcx
,
point
.
edge_list
[
i
],
node
);
}
}
}
void
Sweep
::
FinalizationPolygon
(
SweepContext
&
tcx
)
{
// Get an Internal triangle to start with
Triangle
*
t
=
tcx
.
front
()
->
head
()
->
next
->
triangle
;
Point
*
p
=
tcx
.
front
()
->
head
()
->
next
->
point
;
while
(
!
t
->
GetConstrainedEdgeCW
(
*
p
))
{
t
=
t
->
NeighborCCW
(
*
p
);
}
// Collect interior triangles constrained by edges
tcx
.
MeshClean
(
*
t
);
}
Node
&
Sweep
::
PointEvent
(
SweepContext
&
tcx
,
Point
&
point
)
{
Node
&
node
=
tcx
.
LocateNode
(
point
);
Node
&
new_node
=
NewFrontTriangle
(
tcx
,
point
,
node
);
// Only need to check +epsilon since point never have smaller
// x value than node due to how we fetch nodes from the front
if
(
point
.
x
<=
node
.
point
->
x
+
EPSILON
)
{
Fill
(
tcx
,
node
);
}
//tcx.AddNode(new_node);
FillAdvancingFront
(
tcx
,
new_node
);
return
new_node
;
}
void
Sweep
::
EdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
*
node
)
{
tcx
.
edge_event
.
constrained_edge
=
edge
;
tcx
.
edge_event
.
right
=
(
edge
->
p
->
x
>
edge
->
q
->
x
);
if
(
IsEdgeSideOfTriangle
(
*
node
->
triangle
,
*
edge
->
p
,
*
edge
->
q
))
{
return
;
}
// For now we will do all needed filling
// TODO: integrate with flip process might give some better performance
// but for now this avoid the issue with cases that needs both flips and fills
FillEdgeEvent
(
tcx
,
edge
,
node
);
EdgeEvent
(
tcx
,
*
edge
->
p
,
*
edge
->
q
,
node
->
triangle
,
*
edge
->
q
);
}
void
Sweep
::
EdgeEvent
(
SweepContext
&
tcx
,
Point
&
ep
,
Point
&
eq
,
Triangle
*
triangle
,
Point
&
point
)
{
if
(
IsEdgeSideOfTriangle
(
*
triangle
,
ep
,
eq
))
{
return
;
}
Point
*
p1
=
triangle
->
PointCCW
(
point
);
Orientation
o1
=
Orient2d
(
eq
,
*
p1
,
ep
);
if
(
o1
==
COLLINEAR
)
{
if
(
triangle
->
Contains
(
&
eq
,
p1
))
{
triangle
->
MarkConstrainedEdge
(
&
eq
,
p1
);
// We are modifying the constraint maybe it would be better to
// not change the given constraint and just keep a variable for the new constraint
tcx
.
edge_event
.
constrained_edge
->
q
=
p1
;
triangle
=
&
triangle
->
NeighborAcross
(
point
);
EdgeEvent
(
tcx
,
ep
,
*
p1
,
triangle
,
*
p1
);
}
else
{
std
::
runtime_error
(
"EdgeEvent - collinear points not supported"
);
assert
(
0
);
}
return
;
}
Point
*
p2
=
triangle
->
PointCW
(
point
);
Orientation
o2
=
Orient2d
(
eq
,
*
p2
,
ep
);
if
(
o2
==
COLLINEAR
)
{
if
(
triangle
->
Contains
(
&
eq
,
p2
))
{
triangle
->
MarkConstrainedEdge
(
&
eq
,
p2
);
// We are modifying the constraint maybe it would be better to
// not change the given constraint and just keep a variable for the new constraint
tcx
.
edge_event
.
constrained_edge
->
q
=
p2
;
triangle
=
&
triangle
->
NeighborAcross
(
point
);
EdgeEvent
(
tcx
,
ep
,
*
p2
,
triangle
,
*
p2
);
}
else
{
std
::
runtime_error
(
"EdgeEvent - collinear points not supported"
);
assert
(
0
);
}
return
;
}
if
(
o1
==
o2
)
{
// Need to decide if we are rotating CW or CCW to get to a triangle
// that will cross edge
if
(
o1
==
CW
)
{
triangle
=
triangle
->
NeighborCCW
(
point
);
}
else
{
triangle
=
triangle
->
NeighborCW
(
point
);
}
EdgeEvent
(
tcx
,
ep
,
eq
,
triangle
,
point
);
}
else
{
// This triangle crosses constraint so lets flippin start!
FlipEdgeEvent
(
tcx
,
ep
,
eq
,
triangle
,
point
);
}
}
bool
Sweep
::
IsEdgeSideOfTriangle
(
Triangle
&
triangle
,
Point
&
ep
,
Point
&
eq
)
{
int
index
=
triangle
.
EdgeIndex
(
&
ep
,
&
eq
);
if
(
index
!=
-
1
)
{
triangle
.
MarkConstrainedEdge
(
index
);
Triangle
*
t
=
triangle
.
GetNeighbor
(
index
);
if
(
t
)
{
t
->
MarkConstrainedEdge
(
&
ep
,
&
eq
);
}
return
true
;
}
return
false
;
}
Node
&
Sweep
::
NewFrontTriangle
(
SweepContext
&
tcx
,
Point
&
point
,
Node
&
node
)
{
Triangle
*
triangle
=
new
Triangle
(
point
,
*
node
.
point
,
*
node
.
next
->
point
);
triangle
->
MarkNeighbor
(
*
node
.
triangle
);
tcx
.
AddToMap
(
triangle
);
Node
*
new_node
=
new
Node
(
point
);
nodes_
.
push_back
(
new_node
);
new_node
->
next
=
node
.
next
;
new_node
->
prev
=
&
node
;
node
.
next
->
prev
=
new_node
;
node
.
next
=
new_node
;
if
(
!
Legalize
(
tcx
,
*
triangle
))
{
tcx
.
MapTriangleToNodes
(
*
triangle
);
}
return
*
new_node
;
}
void
Sweep
::
Fill
(
SweepContext
&
tcx
,
Node
&
node
)
{
Triangle
*
triangle
=
new
Triangle
(
*
node
.
prev
->
point
,
*
node
.
point
,
*
node
.
next
->
point
);
// TODO: should copy the constrained_edge value from neighbor triangles
// for now constrained_edge values are copied during the legalize
triangle
->
MarkNeighbor
(
*
node
.
prev
->
triangle
);
triangle
->
MarkNeighbor
(
*
node
.
triangle
);
tcx
.
AddToMap
(
triangle
);
// Update the advancing front
node
.
prev
->
next
=
node
.
next
;
if
(
!
Legalize
(
tcx
,
*
triangle
))
{
tcx
.
MapTriangleToNodes
(
*
triangle
);
}
return
*
new_node
;
}
void
Sweep
::
Fill
(
SweepContext
&
tcx
,
Node
&
node
)
{
Triangle
*
triangle
=
new
Triangle
(
*
node
.
prev
->
point
,
*
node
.
point
,
*
node
.
next
->
point
);
// TODO: should copy the constrained_edge value from neighbor triangles
// for now constrained_edge values are copied during the legalize
triangle
->
MarkNeighbor
(
*
node
.
prev
->
triangle
);
triangle
->
MarkNeighbor
(
*
node
.
triangle
);
tcx
.
AddToMap
(
triangle
);
// Update the advancing front
node
.
prev
->
next
=
node
.
next
;
node
.
next
->
prev
=
node
.
prev
;
// If it was legalized the triangle has already been mapped
if
(
!
Legalize
(
tcx
,
*
triangle
))
{
tcx
.
MapTriangleToNodes
(
*
triangle
);
}
}
void
Sweep
::
FillAdvancingFront
(
SweepContext
&
tcx
,
Node
&
n
)
// If it was legalized the triangle has already been mapped
if
(
!
Legalize
(
tcx
,
*
triangle
))
{
tcx
.
MapTriangleToNodes
(
*
triangle
);
}
}
void
Sweep
::
FillAdvancingFront
(
SweepContext
&
tcx
,
Node
&
n
)
{
// Fill right holes
Node
*
node
=
n
.
next
;
while
(
node
->
next
)
{
// if HoleAngle exceeds 90 degrees then break.
if
(
LargeHole_DontFill
(
node
))
break
;
Fill
(
tcx
,
*
node
);
node
=
node
->
next
;
}
// Fill left holes
node
=
n
.
prev
;
while
(
node
->
prev
)
{
// if HoleAngle exceeds 90 degrees then break.
if
(
LargeHole_DontFill
(
node
))
break
;
Fill
(
tcx
,
*
node
);
node
=
node
->
prev
;
}
// Fill right basins
if
(
n
.
next
&&
n
.
next
->
next
)
{
double
angle
=
BasinAngle
(
n
);
if
(
angle
<
PI_3div4
)
{
FillBasin
(
tcx
,
n
);
}
}
}
// True if HoleAngle exceeds 90 degrees.
bool
Sweep
::
LargeHole_DontFill
(
Node
*
node
)
{
Node
*
nextNode
=
node
->
next
;
Node
*
prevNode
=
node
->
prev
;
if
(
!
AngleExceeds90Degrees
(
node
->
point
,
nextNode
->
point
,
prevNode
->
point
))
return
false
;
// Check additional points on front.
Node
*
next2Node
=
nextNode
->
next
;
// "..Plus.." because only want angles on same side as point being added.
if
((
next2Node
!=
NULL
)
&&
!
AngleExceedsPlus90DegreesOrIsNegative
(
node
->
point
,
next2Node
->
point
,
prevNode
->
point
))
return
false
;
Node
*
prev2Node
=
prevNode
->
prev
;
// "..Plus.." because only want angles on same side as point being added.
if
((
prev2Node
!=
NULL
)
&&
!
AngleExceedsPlus90DegreesOrIsNegative
(
node
->
point
,
nextNode
->
point
,
prev2Node
->
point
))
return
false
;
return
true
;
}
bool
Sweep
::
AngleExceeds90Degrees
(
Point
*
origin
,
Point
*
pa
,
Point
*
pb
)
{
double
angle
=
Angle
(
*
origin
,
*
pa
,
*
pb
);
bool
exceeds90Degrees
=
((
angle
>
PI_div2
)
||
(
angle
<
-
PI_div2
));
return
exceeds90Degrees
;
}
bool
Sweep
::
AngleExceedsPlus90DegreesOrIsNegative
(
Point
*
origin
,
Point
*
pa
,
Point
*
pb
)
{
double
angle
=
Angle
(
*
origin
,
*
pa
,
*
pb
);
bool
exceedsPlus90DegreesOrIsNegative
=
(
angle
>
PI_div2
)
||
(
angle
<
0
);
return
exceedsPlus90DegreesOrIsNegative
;
}
double
Sweep
::
Angle
(
Point
&
origin
,
Point
&
pa
,
Point
&
pb
)
{
/* Complex plane
* ab = cosA +i*sinA
* ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx)
* atan2(y,x) computes the principal value of the argument function
* applied to the complex number x+iy
* Where x = ax*bx + ay*by
* y = ax*by - ay*bx
*/
double
px
=
origin
.
x
;
double
py
=
origin
.
y
;
double
ax
=
pa
.
x
-
px
;
double
ay
=
pa
.
y
-
py
;
double
bx
=
pb
.
x
-
px
;
double
by
=
pb
.
y
-
py
;
double
x
=
ax
*
by
-
ay
*
bx
;
double
y
=
ax
*
bx
+
ay
*
by
;
double
angle
=
atan2
(
x
,
y
);
return
angle
;
}
double
Sweep
::
BasinAngle
(
Node
&
node
)
{
double
ax
=
node
.
point
->
x
-
node
.
next
->
next
->
point
->
x
;
double
ay
=
node
.
point
->
y
-
node
.
next
->
next
->
point
->
y
;
return
atan2
(
ay
,
ax
);
}
double
Sweep
::
HoleAngle
(
Node
&
node
)
{
/* Complex plane
* ab = cosA +i*sinA
* ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx)
* atan2(y,x) computes the principal value of the argument function
* applied to the complex number x+iy
* Where x = ax*bx + ay*by
* y = ax*by - ay*bx
*/
double
ax
=
node
.
next
->
point
->
x
-
node
.
point
->
x
;
double
ay
=
node
.
next
->
point
->
y
-
node
.
point
->
y
;
double
bx
=
node
.
prev
->
point
->
x
-
node
.
point
->
x
;
double
by
=
node
.
prev
->
point
->
y
-
node
.
point
->
y
;
return
atan2
(
ax
*
by
-
ay
*
bx
,
ax
*
bx
+
ay
*
by
);
}
bool
Sweep
::
Legalize
(
SweepContext
&
tcx
,
Triangle
&
t
)
{
// To legalize a triangle we start by finding if any of the three edges
// violate the Delaunay condition
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
if
(
t
.
delaunay_edge
[
i
])
continue
;
Triangle
*
ot
=
t
.
GetNeighbor
(
i
);
if
(
ot
)
{
Point
*
p
=
t
.
GetPoint
(
i
);
Point
*
op
=
ot
->
OppositePoint
(
t
,
*
p
);
int
oi
=
ot
->
Index
(
op
);
// If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization)
// then we should not try to legalize
if
(
ot
->
constrained_edge
[
oi
]
||
ot
->
delaunay_edge
[
oi
])
{
t
.
constrained_edge
[
i
]
=
ot
->
constrained_edge
[
oi
];
continue
;
}
bool
inside
=
Incircle
(
*
p
,
*
t
.
PointCCW
(
*
p
),
*
t
.
PointCW
(
*
p
),
*
op
);
if
(
inside
)
{
// Lets mark this shared edge as Delaunay
t
.
delaunay_edge
[
i
]
=
true
;
ot
->
delaunay_edge
[
oi
]
=
true
;
// Lets rotate shared edge one vertex CW to legalize it
RotateTrianglePair
(
t
,
*
p
,
*
ot
,
*
op
);
// We now got one valid Delaunay Edge shared by two triangles
// This gives us 4 new edges to check for Delaunay
// Make sure that triangle to node mapping is done only one time for a specific triangle
bool
not_legalized
=
!
Legalize
(
tcx
,
t
);
if
(
not_legalized
)
{
tcx
.
MapTriangleToNodes
(
t
);
}
not_legalized
=
!
Legalize
(
tcx
,
*
ot
);
if
(
not_legalized
)
tcx
.
MapTriangleToNodes
(
*
ot
);
// Reset the Delaunay edges, since they only are valid Delaunay edges
// until we add a new triangle or point.
// XXX: need to think about this. Can these edges be tried after we
// return to previous recursive level?
t
.
delaunay_edge
[
i
]
=
false
;
ot
->
delaunay_edge
[
oi
]
=
false
;
// If triangle have been legalized no need to check the other edges since
// the recursive legalization will handles those so we can end here.
return
true
;
}
}
}
return
false
;
}
bool
Sweep
::
Incircle
(
Point
&
pa
,
Point
&
pb
,
Point
&
pc
,
Point
&
pd
)
{
double
adx
=
pa
.
x
-
pd
.
x
;
double
ady
=
pa
.
y
-
pd
.
y
;
double
bdx
=
pb
.
x
-
pd
.
x
;
double
bdy
=
pb
.
y
-
pd
.
y
;
double
adxbdy
=
adx
*
bdy
;
double
bdxady
=
bdx
*
ady
;
double
oabd
=
adxbdy
-
bdxady
;
if
(
oabd
<=
0
)
return
false
;
double
cdx
=
pc
.
x
-
pd
.
x
;
double
cdy
=
pc
.
y
-
pd
.
y
;
double
cdxady
=
cdx
*
ady
;
double
adxcdy
=
adx
*
cdy
;
double
ocad
=
cdxady
-
adxcdy
;
if
(
ocad
<=
0
)
return
false
;
double
bdxcdy
=
bdx
*
cdy
;
double
cdxbdy
=
cdx
*
bdy
;
double
alift
=
adx
*
adx
+
ady
*
ady
;
double
blift
=
bdx
*
bdx
+
bdy
*
bdy
;
double
clift
=
cdx
*
cdx
+
cdy
*
cdy
;
double
det
=
alift
*
(
bdxcdy
-
cdxbdy
)
+
blift
*
ocad
+
clift
*
oabd
;
return
det
>
0
;
}
void
Sweep
::
RotateTrianglePair
(
Triangle
&
t
,
Point
&
p
,
Triangle
&
ot
,
Point
&
op
)
{
Triangle
*
n1
,
*
n2
,
*
n3
,
*
n4
;
n1
=
t
.
NeighborCCW
(
p
);
n2
=
t
.
NeighborCW
(
p
);
n3
=
ot
.
NeighborCCW
(
op
);
n4
=
ot
.
NeighborCW
(
op
);
bool
ce1
,
ce2
,
ce3
,
ce4
;
ce1
=
t
.
GetConstrainedEdgeCCW
(
p
);
ce2
=
t
.
GetConstrainedEdgeCW
(
p
);
ce3
=
ot
.
GetConstrainedEdgeCCW
(
op
);
ce4
=
ot
.
GetConstrainedEdgeCW
(
op
);
bool
de1
,
de2
,
de3
,
de4
;
de1
=
t
.
GetDelunayEdgeCCW
(
p
);
de2
=
t
.
GetDelunayEdgeCW
(
p
);
de3
=
ot
.
GetDelunayEdgeCCW
(
op
);
de4
=
ot
.
GetDelunayEdgeCW
(
op
);
t
.
Legalize
(
p
,
op
);
ot
.
Legalize
(
op
,
p
);
// Remap delaunay_edge
ot
.
SetDelunayEdgeCCW
(
p
,
de1
);
t
.
SetDelunayEdgeCW
(
p
,
de2
);
t
.
SetDelunayEdgeCCW
(
op
,
de3
);
ot
.
SetDelunayEdgeCW
(
op
,
de4
);
// Remap constrained_edge
ot
.
SetConstrainedEdgeCCW
(
p
,
ce1
);
t
.
SetConstrainedEdgeCW
(
p
,
ce2
);
t
.
SetConstrainedEdgeCCW
(
op
,
ce3
);
ot
.
SetConstrainedEdgeCW
(
op
,
ce4
);
// Remap neighbors
// XXX: might optimize the markNeighbor by keeping track of
// what side should be assigned to what neighbor after the
// rotation. Now mark neighbor does lots of testing to find
// the right side.
t
.
ClearNeighbors
();
ot
.
ClearNeighbors
();
if
(
n1
)
ot
.
MarkNeighbor
(
*
n1
);
if
(
n2
)
t
.
MarkNeighbor
(
*
n2
);
if
(
n3
)
t
.
MarkNeighbor
(
*
n3
);
if
(
n4
)
ot
.
MarkNeighbor
(
*
n4
);
t
.
MarkNeighbor
(
ot
);
}
void
Sweep
::
FillBasin
(
SweepContext
&
tcx
,
Node
&
node
)
{
if
(
Orient2d
(
*
node
.
point
,
*
node
.
next
->
point
,
*
node
.
next
->
next
->
point
)
==
CCW
)
{
tcx
.
basin
.
left_node
=
node
.
next
->
next
;
}
else
{
tcx
.
basin
.
left_node
=
node
.
next
;
}
// Find the bottom and right node
tcx
.
basin
.
bottom_node
=
tcx
.
basin
.
left_node
;
while
(
tcx
.
basin
.
bottom_node
->
next
&&
tcx
.
basin
.
bottom_node
->
point
->
y
>=
tcx
.
basin
.
bottom_node
->
next
->
point
->
y
)
{
tcx
.
basin
.
bottom_node
=
tcx
.
basin
.
bottom_node
->
next
;
}
if
(
tcx
.
basin
.
bottom_node
==
tcx
.
basin
.
left_node
)
{
// No valid basin
return
;
}
tcx
.
basin
.
right_node
=
tcx
.
basin
.
bottom_node
;
while
(
tcx
.
basin
.
right_node
->
next
&&
tcx
.
basin
.
right_node
->
point
->
y
<
tcx
.
basin
.
right_node
->
next
->
point
->
y
)
{
tcx
.
basin
.
right_node
=
tcx
.
basin
.
right_node
->
next
;
}
if
(
tcx
.
basin
.
right_node
==
tcx
.
basin
.
bottom_node
)
{
// No valid basins
return
;
}
tcx
.
basin
.
width
=
tcx
.
basin
.
right_node
->
point
->
x
-
tcx
.
basin
.
left_node
->
point
->
x
;
tcx
.
basin
.
left_highest
=
tcx
.
basin
.
left_node
->
point
->
y
>
tcx
.
basin
.
right_node
->
point
->
y
;
FillBasinReq
(
tcx
,
tcx
.
basin
.
bottom_node
);
}
void
Sweep
::
FillBasinReq
(
SweepContext
&
tcx
,
Node
*
node
)
{
// Fill right holes
Node
*
node
=
n
.
next
;
while
(
node
->
next
)
{
// if HoleAngle exceeds 90 degrees then break.
if
(
LargeHole_DontFill
(
node
))
break
;
Fill
(
tcx
,
*
node
);
node
=
node
->
next
;
}
// Fill left holes
node
=
n
.
prev
;
while
(
node
->
prev
)
{
// if HoleAngle exceeds 90 degrees then break.
if
(
LargeHole_DontFill
(
node
))
break
;
Fill
(
tcx
,
*
node
);
node
=
node
->
prev
;
}
// Fill right basins
if
(
n
.
next
&&
n
.
next
->
next
)
{
double
angle
=
BasinAngle
(
n
);
if
(
angle
<
PI_3div4
)
{
FillBasin
(
tcx
,
n
);
}
}
}
// True if HoleAngle exceeds 90 degrees.
bool
Sweep
::
LargeHole_DontFill
(
Node
*
node
)
{
Node
*
nextNode
=
node
->
next
;
Node
*
prevNode
=
node
->
prev
;
if
(
!
AngleExceeds90Degrees
(
node
->
point
,
nextNode
->
point
,
prevNode
->
point
))
return
false
;
// Check additional points on front.
Node
*
next2Node
=
nextNode
->
next
;
// "..Plus.." because only want angles on same side as point being added.
if
((
next2Node
!=
NULL
)
&&
!
AngleExceedsPlus90DegreesOrIsNegative
(
node
->
point
,
next2Node
->
point
,
prevNode
->
point
))
return
false
;
Node
*
prev2Node
=
prevNode
->
prev
;
// "..Plus.." because only want angles on same side as point being added.
if
((
prev2Node
!=
NULL
)
&&
!
AngleExceedsPlus90DegreesOrIsNegative
(
node
->
point
,
nextNode
->
point
,
prev2Node
->
point
))
return
false
;
return
true
;
}
bool
Sweep
::
AngleExceeds90Degrees
(
Point
*
origin
,
Point
*
pa
,
Point
*
pb
)
{
double
angle
=
Angle
(
*
origin
,
*
pa
,
*
pb
);
bool
exceeds90Degrees
=
((
angle
>
PI_div2
)
||
(
angle
<
-
PI_div2
));
return
exceeds90Degrees
;
}
bool
Sweep
::
AngleExceedsPlus90DegreesOrIsNegative
(
Point
*
origin
,
Point
*
pa
,
Point
*
pb
)
{
double
angle
=
Angle
(
*
origin
,
*
pa
,
*
pb
);
bool
exceedsPlus90DegreesOrIsNegative
=
(
angle
>
PI_div2
)
||
(
angle
<
0
);
return
exceedsPlus90DegreesOrIsNegative
;
}
double
Sweep
::
Angle
(
Point
&
origin
,
Point
&
pa
,
Point
&
pb
)
{
/* Complex plane
* ab = cosA +i*sinA
* ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx)
* atan2(y,x) computes the principal value of the argument function
* applied to the complex number x+iy
* Where x = ax*bx + ay*by
* y = ax*by - ay*bx
*/
double
px
=
origin
.
x
;
double
py
=
origin
.
y
;
double
ax
=
pa
.
x
-
px
;
double
ay
=
pa
.
y
-
py
;
double
bx
=
pb
.
x
-
px
;
double
by
=
pb
.
y
-
py
;
double
x
=
ax
*
by
-
ay
*
bx
;
double
y
=
ax
*
bx
+
ay
*
by
;
double
angle
=
atan2
(
x
,
y
);
return
angle
;
}
double
Sweep
::
BasinAngle
(
Node
&
node
)
{
double
ax
=
node
.
point
->
x
-
node
.
next
->
next
->
point
->
x
;
double
ay
=
node
.
point
->
y
-
node
.
next
->
next
->
point
->
y
;
return
atan2
(
ay
,
ax
);
}
double
Sweep
::
HoleAngle
(
Node
&
node
)
{
/* Complex plane
* ab = cosA +i*sinA
* ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx)
* atan2(y,x) computes the principal value of the argument function
* applied to the complex number x+iy
* Where x = ax*bx + ay*by
* y = ax*by - ay*bx
*/
double
ax
=
node
.
next
->
point
->
x
-
node
.
point
->
x
;
double
ay
=
node
.
next
->
point
->
y
-
node
.
point
->
y
;
double
bx
=
node
.
prev
->
point
->
x
-
node
.
point
->
x
;
double
by
=
node
.
prev
->
point
->
y
-
node
.
point
->
y
;
return
atan2
(
ax
*
by
-
ay
*
bx
,
ax
*
bx
+
ay
*
by
);
}
bool
Sweep
::
Legalize
(
SweepContext
&
tcx
,
Triangle
&
t
)
{
// To legalize a triangle we start by finding if any of the three edges
// violate the Delaunay condition
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
if
(
t
.
delaunay_edge
[
i
])
continue
;
Triangle
*
ot
=
t
.
GetNeighbor
(
i
);
if
(
ot
)
{
Point
*
p
=
t
.
GetPoint
(
i
);
Point
*
op
=
ot
->
OppositePoint
(
t
,
*
p
);
int
oi
=
ot
->
Index
(
op
);
// If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization)
// then we should not try to legalize
if
(
ot
->
constrained_edge
[
oi
]
||
ot
->
delaunay_edge
[
oi
])
{
t
.
constrained_edge
[
i
]
=
ot
->
constrained_edge
[
oi
];
continue
;
}
bool
inside
=
Incircle
(
*
p
,
*
t
.
PointCCW
(
*
p
),
*
t
.
PointCW
(
*
p
),
*
op
);
if
(
inside
)
{
// Lets mark this shared edge as Delaunay
t
.
delaunay_edge
[
i
]
=
true
;
ot
->
delaunay_edge
[
oi
]
=
true
;
// Lets rotate shared edge one vertex CW to legalize it
RotateTrianglePair
(
t
,
*
p
,
*
ot
,
*
op
);
// We now got one valid Delaunay Edge shared by two triangles
// This gives us 4 new edges to check for Delaunay
// Make sure that triangle to node mapping is done only one time for a specific triangle
bool
not_legalized
=
!
Legalize
(
tcx
,
t
);
if
(
not_legalized
)
{
tcx
.
MapTriangleToNodes
(
t
);
}
not_legalized
=
!
Legalize
(
tcx
,
*
ot
);
if
(
not_legalized
)
tcx
.
MapTriangleToNodes
(
*
ot
);
// Reset the Delaunay edges, since they only are valid Delaunay edges
// until we add a new triangle or point.
// XXX: need to think about this. Can these edges be tried after we
// return to previous recursive level?
t
.
delaunay_edge
[
i
]
=
false
;
ot
->
delaunay_edge
[
oi
]
=
false
;
// If triangle have been legalized no need to check the other edges since
// the recursive legalization will handles those so we can end here.
return
true
;
}
}
}
return
false
;
}
bool
Sweep
::
Incircle
(
Point
&
pa
,
Point
&
pb
,
Point
&
pc
,
Point
&
pd
)
{
double
adx
=
pa
.
x
-
pd
.
x
;
double
ady
=
pa
.
y
-
pd
.
y
;
double
bdx
=
pb
.
x
-
pd
.
x
;
double
bdy
=
pb
.
y
-
pd
.
y
;
double
adxbdy
=
adx
*
bdy
;
double
bdxady
=
bdx
*
ady
;
double
oabd
=
adxbdy
-
bdxady
;
if
(
oabd
<=
0
)
return
false
;
double
cdx
=
pc
.
x
-
pd
.
x
;
double
cdy
=
pc
.
y
-
pd
.
y
;
double
cdxady
=
cdx
*
ady
;
double
adxcdy
=
adx
*
cdy
;
double
ocad
=
cdxady
-
adxcdy
;
if
(
ocad
<=
0
)
return
false
;
double
bdxcdy
=
bdx
*
cdy
;
double
cdxbdy
=
cdx
*
bdy
;
double
alift
=
adx
*
adx
+
ady
*
ady
;
double
blift
=
bdx
*
bdx
+
bdy
*
bdy
;
double
clift
=
cdx
*
cdx
+
cdy
*
cdy
;
double
det
=
alift
*
(
bdxcdy
-
cdxbdy
)
+
blift
*
ocad
+
clift
*
oabd
;
return
det
>
0
;
}
void
Sweep
::
RotateTrianglePair
(
Triangle
&
t
,
Point
&
p
,
Triangle
&
ot
,
Point
&
op
)
{
Triangle
*
n1
,
*
n2
,
*
n3
,
*
n4
;
n1
=
t
.
NeighborCCW
(
p
);
n2
=
t
.
NeighborCW
(
p
);
n3
=
ot
.
NeighborCCW
(
op
);
n4
=
ot
.
NeighborCW
(
op
);
bool
ce1
,
ce2
,
ce3
,
ce4
;
ce1
=
t
.
GetConstrainedEdgeCCW
(
p
);
ce2
=
t
.
GetConstrainedEdgeCW
(
p
);
ce3
=
ot
.
GetConstrainedEdgeCCW
(
op
);
ce4
=
ot
.
GetConstrainedEdgeCW
(
op
);
bool
de1
,
de2
,
de3
,
de4
;
de1
=
t
.
GetDelunayEdgeCCW
(
p
);
de2
=
t
.
GetDelunayEdgeCW
(
p
);
de3
=
ot
.
GetDelunayEdgeCCW
(
op
);
de4
=
ot
.
GetDelunayEdgeCW
(
op
);
t
.
Legalize
(
p
,
op
);
ot
.
Legalize
(
op
,
p
);
// Remap delaunay_edge
ot
.
SetDelunayEdgeCCW
(
p
,
de1
);
t
.
SetDelunayEdgeCW
(
p
,
de2
);
t
.
SetDelunayEdgeCCW
(
op
,
de3
);
ot
.
SetDelunayEdgeCW
(
op
,
de4
);
// Remap constrained_edge
ot
.
SetConstrainedEdgeCCW
(
p
,
ce1
);
t
.
SetConstrainedEdgeCW
(
p
,
ce2
);
t
.
SetConstrainedEdgeCCW
(
op
,
ce3
);
ot
.
SetConstrainedEdgeCW
(
op
,
ce4
);
// Remap neighbors
// XXX: might optimize the markNeighbor by keeping track of
// what side should be assigned to what neighbor after the
// rotation. Now mark neighbor does lots of testing to find
// the right side.
t
.
ClearNeighbors
();
ot
.
ClearNeighbors
();
if
(
n1
)
ot
.
MarkNeighbor
(
*
n1
);
if
(
n2
)
t
.
MarkNeighbor
(
*
n2
);
if
(
n3
)
t
.
MarkNeighbor
(
*
n3
);
if
(
n4
)
ot
.
MarkNeighbor
(
*
n4
);
t
.
MarkNeighbor
(
ot
);
}
void
Sweep
::
FillBasin
(
SweepContext
&
tcx
,
Node
&
node
)
{
if
(
Orient2d
(
*
node
.
point
,
*
node
.
next
->
point
,
*
node
.
next
->
next
->
point
)
==
CCW
)
{
tcx
.
basin
.
left_node
=
node
.
next
->
next
;
}
else
{
tcx
.
basin
.
left_node
=
node
.
next
;
}
// Find the bottom and right node
tcx
.
basin
.
bottom_node
=
tcx
.
basin
.
left_node
;
while
(
tcx
.
basin
.
bottom_node
->
next
&&
tcx
.
basin
.
bottom_node
->
point
->
y
>=
tcx
.
basin
.
bottom_node
->
next
->
point
->
y
)
{
tcx
.
basin
.
bottom_node
=
tcx
.
basin
.
bottom_node
->
next
;
}
if
(
tcx
.
basin
.
bottom_node
==
tcx
.
basin
.
left_node
)
{
// No valid basin
return
;
}
tcx
.
basin
.
right_node
=
tcx
.
basin
.
bottom_node
;
while
(
tcx
.
basin
.
right_node
->
next
&&
tcx
.
basin
.
right_node
->
point
->
y
<
tcx
.
basin
.
right_node
->
next
->
point
->
y
)
{
tcx
.
basin
.
right_node
=
tcx
.
basin
.
right_node
->
next
;
}
if
(
tcx
.
basin
.
right_node
==
tcx
.
basin
.
bottom_node
)
{
// No valid basins
return
;
}
tcx
.
basin
.
width
=
tcx
.
basin
.
right_node
->
point
->
x
-
tcx
.
basin
.
left_node
->
point
->
x
;
tcx
.
basin
.
left_highest
=
tcx
.
basin
.
left_node
->
point
->
y
>
tcx
.
basin
.
right_node
->
point
->
y
;
FillBasinReq
(
tcx
,
tcx
.
basin
.
bottom_node
);
}
void
Sweep
::
FillBasinReq
(
SweepContext
&
tcx
,
Node
*
node
)
{
// if shallow stop filling
if
(
IsShallow
(
tcx
,
*
node
))
{
return
;
}
// if shallow stop filling
if
(
IsShallow
(
tcx
,
*
node
))
{
return
;
}
Fill
(
tcx
,
*
node
);
if
(
node
->
prev
==
tcx
.
basin
.
left_node
&&
node
->
next
==
tcx
.
basin
.
right_node
)
{
return
;
}
else
if
(
node
->
prev
==
tcx
.
basin
.
left_node
)
{
Orientation
o
=
Orient2d
(
*
node
->
point
,
*
node
->
next
->
point
,
*
node
->
next
->
next
->
point
);
if
(
o
==
CW
)
{
return
;
}
node
=
node
->
next
;
}
else
if
(
node
->
next
==
tcx
.
basin
.
right_node
)
{
Orientation
o
=
Orient2d
(
*
node
->
point
,
*
node
->
prev
->
point
,
*
node
->
prev
->
prev
->
point
);
if
(
o
==
CCW
)
{
return
;
}
node
=
node
->
prev
;
}
else
{
// Continue with the neighbor node with lowest Y value
if
(
node
->
prev
->
point
->
y
<
node
->
next
->
point
->
y
)
{
node
=
node
->
prev
;
}
else
{
node
=
node
->
next
;
}
}
FillBasinReq
(
tcx
,
node
);
}
bool
Sweep
::
IsShallow
(
SweepContext
&
tcx
,
Node
&
node
)
{
double
height
;
if
(
tcx
.
basin
.
left_highest
)
{
height
=
tcx
.
basin
.
left_node
->
point
->
y
-
node
.
point
->
y
;
}
else
{
height
=
tcx
.
basin
.
right_node
->
point
->
y
-
node
.
point
->
y
;
}
// if shallow stop filling
if
(
tcx
.
basin
.
width
>
height
)
{
return
true
;
}
return
false
;
}
void
Sweep
::
FillEdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
*
node
)
{
if
(
tcx
.
edge_event
.
right
)
{
FillRightAboveEdgeEvent
(
tcx
,
edge
,
node
);
}
else
{
FillLeftAboveEdgeEvent
(
tcx
,
edge
,
node
);
}
}
void
Sweep
::
FillRightAboveEdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
*
node
)
{
while
(
node
->
next
->
point
->
x
<
edge
->
p
->
x
)
{
// Check if next node is below the edge
if
(
Orient2d
(
*
edge
->
q
,
*
node
->
next
->
point
,
*
edge
->
p
)
==
CCW
)
{
FillRightBelowEdgeEvent
(
tcx
,
edge
,
*
node
);
}
else
{
node
=
node
->
next
;
}
}
}
void
Sweep
::
FillRightBelowEdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
&
node
)
{
if
(
node
.
point
->
x
<
edge
->
p
->
x
)
{
if
(
Orient2d
(
*
node
.
point
,
*
node
.
next
->
point
,
*
node
.
next
->
next
->
point
)
==
CCW
)
{
// Concave
FillRightConcaveEdgeEvent
(
tcx
,
edge
,
node
);
}
else
{
// Convex
FillRightConvexEdgeEvent
(
tcx
,
edge
,
node
);
// Retry this one
FillRightBelowEdgeEvent
(
tcx
,
edge
,
node
);
}
}
}
void
Sweep
::
FillRightConcaveEdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
&
node
)
{
Fill
(
tcx
,
*
node
.
next
);
if
(
node
.
next
->
point
!=
edge
->
p
)
{
// Next above or below edge?
if
(
Orient2d
(
*
edge
->
q
,
*
node
.
next
->
point
,
*
edge
->
p
)
==
CCW
)
{
// Below
if
(
Orient2d
(
*
node
.
point
,
*
node
.
next
->
point
,
*
node
.
next
->
next
->
point
)
==
CCW
)
{
// Next is concave
FillRightConcaveEdgeEvent
(
tcx
,
edge
,
node
);
}
else
{
// Next is convex
}
}
}
}
void
Sweep
::
FillRightConvexEdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
&
node
)
{
// Next concave or convex?
if
(
Orient2d
(
*
node
.
next
->
point
,
*
node
.
next
->
next
->
point
,
*
node
.
next
->
next
->
next
->
point
)
==
CCW
)
{
// Concave
FillRightConcaveEdgeEvent
(
tcx
,
edge
,
*
node
.
next
);
}
else
{
// Convex
// Next above or below edge?
if
(
Orient2d
(
*
edge
->
q
,
*
node
.
next
->
next
->
point
,
*
edge
->
p
)
==
CCW
)
{
// Below
FillRightConvexEdgeEvent
(
tcx
,
edge
,
*
node
.
next
);
}
else
{
// Above
}
}
}
void
Sweep
::
FillLeftAboveEdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
*
node
)
{
while
(
node
->
prev
->
point
->
x
>
edge
->
p
->
x
)
{
// Check if next node is below the edge
if
(
Orient2d
(
*
edge
->
q
,
*
node
->
prev
->
point
,
*
edge
->
p
)
==
CW
)
{
FillLeftBelowEdgeEvent
(
tcx
,
edge
,
*
node
);
}
else
{
node
=
node
->
prev
;
}
}
}
void
Sweep
::
FillLeftBelowEdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
&
node
)
{
if
(
node
.
point
->
x
>
edge
->
p
->
x
)
{
if
(
Orient2d
(
*
node
.
point
,
*
node
.
prev
->
point
,
*
node
.
prev
->
prev
->
point
)
==
CW
)
{
// Concave
FillLeftConcaveEdgeEvent
(
tcx
,
edge
,
node
);
}
else
{
// Convex
FillLeftConvexEdgeEvent
(
tcx
,
edge
,
node
);
// Retry this one
FillLeftBelowEdgeEvent
(
tcx
,
edge
,
node
);
}
}
}
void
Sweep
::
FillLeftConvexEdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
&
node
)
{
// Next concave or convex?
if
(
Orient2d
(
*
node
.
prev
->
point
,
*
node
.
prev
->
prev
->
point
,
*
node
.
prev
->
prev
->
prev
->
point
)
==
CW
)
{
// Concave
FillLeftConcaveEdgeEvent
(
tcx
,
edge
,
*
node
.
prev
);
}
else
{
// Convex
// Next above or below edge?
if
(
Orient2d
(
*
edge
->
q
,
*
node
.
prev
->
prev
->
point
,
*
edge
->
p
)
==
CW
)
{
// Below
FillLeftConvexEdgeEvent
(
tcx
,
edge
,
*
node
.
prev
);
}
else
{
// Above
}
}
}
void
Sweep
::
FillLeftConcaveEdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
&
node
)
{
Fill
(
tcx
,
*
node
.
prev
);
if
(
node
.
prev
->
point
!=
edge
->
p
)
{
// Next above or below edge?
if
(
Orient2d
(
*
edge
->
q
,
*
node
.
prev
->
point
,
*
edge
->
p
)
==
CW
)
{
// Below
if
(
Orient2d
(
*
node
.
point
,
*
node
.
prev
->
point
,
*
node
.
prev
->
prev
->
point
)
==
CW
)
{
// Next is concave
FillLeftConcaveEdgeEvent
(
tcx
,
edge
,
node
);
}
else
{
// Next is convex
}
}
}
}
void
Sweep
::
FlipEdgeEvent
(
SweepContext
&
tcx
,
Point
&
ep
,
Point
&
eq
,
Triangle
*
t
,
Point
&
p
)
{
Triangle
&
ot
=
t
->
NeighborAcross
(
p
);
Point
&
op
=
*
ot
.
OppositePoint
(
*
t
,
p
);
if
(
&
ot
==
NULL
)
{
// If we want to integrate the fillEdgeEvent do it here
// With current implementation we should never get here
//throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle");
assert
(
0
);
}
if
(
InScanArea
(
p
,
*
t
->
PointCCW
(
p
),
*
t
->
PointCW
(
p
),
op
))
{
// Lets rotate shared edge one vertex CW
RotateTrianglePair
(
*
t
,
p
,
ot
,
op
);
tcx
.
MapTriangleToNodes
(
*
t
);
tcx
.
MapTriangleToNodes
(
ot
);
if
(
p
==
eq
&&
op
==
ep
)
{
if
(
eq
==
*
tcx
.
edge_event
.
constrained_edge
->
q
&&
ep
==
*
tcx
.
edge_event
.
constrained_edge
->
p
)
{
t
->
MarkConstrainedEdge
(
&
ep
,
&
eq
);
ot
.
MarkConstrainedEdge
(
&
ep
,
&
eq
);
Legalize
(
tcx
,
*
t
);
Legalize
(
tcx
,
ot
);
}
else
{
// XXX: I think one of the triangles should be legalized here?
}
}
else
{
Orientation
o
=
Orient2d
(
eq
,
op
,
ep
);
t
=
&
NextFlipTriangle
(
tcx
,
(
int
)
o
,
*
t
,
ot
,
p
,
op
);
FlipEdgeEvent
(
tcx
,
ep
,
eq
,
t
,
p
);
}
}
else
{
Point
&
newP
=
NextFlipPoint
(
ep
,
eq
,
ot
,
op
);
FlipScanEdgeEvent
(
tcx
,
ep
,
eq
,
*
t
,
ot
,
newP
);
EdgeEvent
(
tcx
,
ep
,
eq
,
t
,
p
);
}
}
Triangle
&
Sweep
::
NextFlipTriangle
(
SweepContext
&
tcx
,
int
o
,
Triangle
&
t
,
Triangle
&
ot
,
Point
&
p
,
Point
&
op
)
{
if
(
o
==
CCW
)
{
// ot is not crossing edge after flip
int
edge_index
=
ot
.
EdgeIndex
(
&
p
,
&
op
);
ot
.
delaunay_edge
[
edge_index
]
=
true
;
Legalize
(
tcx
,
ot
);
ot
.
ClearDelunayEdges
();
return
t
;
}
// t is not crossing edge after flip
int
edge_index
=
t
.
EdgeIndex
(
&
p
,
&
op
);
t
.
delaunay_edge
[
edge_index
]
=
true
;
Legalize
(
tcx
,
t
);
t
.
ClearDelunayEdges
();
return
ot
;
}
Point
&
Sweep
::
NextFlipPoint
(
Point
&
ep
,
Point
&
eq
,
Triangle
&
ot
,
Point
&
op
)
{
Orientation
o2d
=
Orient2d
(
eq
,
op
,
ep
);
if
(
o2d
==
CW
)
{
// Right
return
*
ot
.
PointCCW
(
op
);
}
else
if
(
o2d
==
CCW
)
{
// Left
return
*
ot
.
PointCW
(
op
);
}
else
{
//throw new RuntimeException("[Unsupported] Opposing point on constrained edge");
assert
(
0
);
}
}
void
Sweep
::
FlipScanEdgeEvent
(
SweepContext
&
tcx
,
Point
&
ep
,
Point
&
eq
,
Triangle
&
flip_triangle
,
Triangle
&
t
,
Point
&
p
)
{
Triangle
&
ot
=
t
.
NeighborAcross
(
p
);
Point
&
op
=
*
ot
.
OppositePoint
(
t
,
p
);
if
(
&
t
.
NeighborAcross
(
p
)
==
NULL
)
{
// If we want to integrate the fillEdgeEvent do it here
// With current implementation we should never get here
//throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle");
assert
(
0
);
}
if
(
InScanArea
(
eq
,
*
flip_triangle
.
PointCCW
(
eq
),
*
flip_triangle
.
PointCW
(
eq
),
op
))
{
// flip with new edge op->eq
FlipEdgeEvent
(
tcx
,
eq
,
op
,
&
ot
,
op
);
// TODO: Actually I just figured out that it should be possible to
// improve this by getting the next ot and op before the the above
// flip and continue the flipScanEdgeEvent here
// set new ot and op here and loop back to inScanArea test
// also need to set a new flip_triangle first
// Turns out at first glance that this is somewhat complicated
// so it will have to wait.
}
else
{
Point
&
newP
=
NextFlipPoint
(
ep
,
eq
,
ot
,
op
);
FlipScanEdgeEvent
(
tcx
,
ep
,
eq
,
flip_triangle
,
ot
,
newP
);
}
if
(
node
->
prev
==
tcx
.
basin
.
left_node
&&
node
->
next
==
tcx
.
basin
.
right_node
)
{
return
;
}
else
if
(
node
->
prev
==
tcx
.
basin
.
left_node
)
{
Orientation
o
=
Orient2d
(
*
node
->
point
,
*
node
->
next
->
point
,
*
node
->
next
->
next
->
point
);
if
(
o
==
CW
)
{
return
;
}
node
=
node
->
next
;
}
else
if
(
node
->
next
==
tcx
.
basin
.
right_node
)
{
Orientation
o
=
Orient2d
(
*
node
->
point
,
*
node
->
prev
->
point
,
*
node
->
prev
->
prev
->
point
);
if
(
o
==
CCW
)
{
return
;
}
node
=
node
->
prev
;
}
else
{
// Continue with the neighbor node with lowest Y value
if
(
node
->
prev
->
point
->
y
<
node
->
next
->
point
->
y
)
{
node
=
node
->
prev
;
}
else
{
node
=
node
->
next
;
}
}
FillBasinReq
(
tcx
,
node
);
}
bool
Sweep
::
IsShallow
(
SweepContext
&
tcx
,
Node
&
node
)
{
double
height
;
if
(
tcx
.
basin
.
left_highest
)
{
height
=
tcx
.
basin
.
left_node
->
point
->
y
-
node
.
point
->
y
;
}
else
{
height
=
tcx
.
basin
.
right_node
->
point
->
y
-
node
.
point
->
y
;
}
// if shallow stop filling
if
(
tcx
.
basin
.
width
>
height
)
{
return
true
;
}
return
false
;
}
void
Sweep
::
FillEdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
*
node
)
{
if
(
tcx
.
edge_event
.
right
)
{
FillRightAboveEdgeEvent
(
tcx
,
edge
,
node
);
}
else
{
FillLeftAboveEdgeEvent
(
tcx
,
edge
,
node
);
}
}
void
Sweep
::
FillRightAboveEdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
*
node
)
{
while
(
node
->
next
->
point
->
x
<
edge
->
p
->
x
)
{
// Check if next node is below the edge
if
(
Orient2d
(
*
edge
->
q
,
*
node
->
next
->
point
,
*
edge
->
p
)
==
CCW
)
{
FillRightBelowEdgeEvent
(
tcx
,
edge
,
*
node
);
}
else
{
node
=
node
->
next
;
}
}
}
void
Sweep
::
FillRightBelowEdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
&
node
)
{
if
(
node
.
point
->
x
<
edge
->
p
->
x
)
{
if
(
Orient2d
(
*
node
.
point
,
*
node
.
next
->
point
,
*
node
.
next
->
next
->
point
)
==
CCW
)
{
// Concave
FillRightConcaveEdgeEvent
(
tcx
,
edge
,
node
);
}
else
{
// Convex
FillRightConvexEdgeEvent
(
tcx
,
edge
,
node
);
// Retry this one
FillRightBelowEdgeEvent
(
tcx
,
edge
,
node
);
}
}
}
void
Sweep
::
FillRightConcaveEdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
&
node
)
{
Fill
(
tcx
,
*
node
.
next
);
if
(
node
.
next
->
point
!=
edge
->
p
)
{
// Next above or below edge?
if
(
Orient2d
(
*
edge
->
q
,
*
node
.
next
->
point
,
*
edge
->
p
)
==
CCW
)
{
// Below
if
(
Orient2d
(
*
node
.
point
,
*
node
.
next
->
point
,
*
node
.
next
->
next
->
point
)
==
CCW
)
{
// Next is concave
FillRightConcaveEdgeEvent
(
tcx
,
edge
,
node
);
}
else
{
// Next is convex
}
}
}
}
void
Sweep
::
FillRightConvexEdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
&
node
)
{
// Next concave or convex?
if
(
Orient2d
(
*
node
.
next
->
point
,
*
node
.
next
->
next
->
point
,
*
node
.
next
->
next
->
next
->
point
)
==
CCW
)
{
// Concave
FillRightConcaveEdgeEvent
(
tcx
,
edge
,
*
node
.
next
);
}
else
{
// Convex
// Next above or below edge?
if
(
Orient2d
(
*
edge
->
q
,
*
node
.
next
->
next
->
point
,
*
edge
->
p
)
==
CCW
)
{
// Below
FillRightConvexEdgeEvent
(
tcx
,
edge
,
*
node
.
next
);
}
else
{
// Above
}
}
}
void
Sweep
::
FillLeftAboveEdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
*
node
)
{
while
(
node
->
prev
->
point
->
x
>
edge
->
p
->
x
)
{
// Check if next node is below the edge
if
(
Orient2d
(
*
edge
->
q
,
*
node
->
prev
->
point
,
*
edge
->
p
)
==
CW
)
{
FillLeftBelowEdgeEvent
(
tcx
,
edge
,
*
node
);
}
else
{
node
=
node
->
prev
;
}
}
}
void
Sweep
::
FillLeftBelowEdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
&
node
)
{
if
(
node
.
point
->
x
>
edge
->
p
->
x
)
{
if
(
Orient2d
(
*
node
.
point
,
*
node
.
prev
->
point
,
*
node
.
prev
->
prev
->
point
)
==
CW
)
{
// Concave
FillLeftConcaveEdgeEvent
(
tcx
,
edge
,
node
);
}
else
{
// Convex
FillLeftConvexEdgeEvent
(
tcx
,
edge
,
node
);
// Retry this one
FillLeftBelowEdgeEvent
(
tcx
,
edge
,
node
);
}
}
}
void
Sweep
::
FillLeftConvexEdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
&
node
)
{
// Next concave or convex?
if
(
Orient2d
(
*
node
.
prev
->
point
,
*
node
.
prev
->
prev
->
point
,
*
node
.
prev
->
prev
->
prev
->
point
)
==
CW
)
{
// Concave
FillLeftConcaveEdgeEvent
(
tcx
,
edge
,
*
node
.
prev
);
}
else
{
// Convex
// Next above or below edge?
if
(
Orient2d
(
*
edge
->
q
,
*
node
.
prev
->
prev
->
point
,
*
edge
->
p
)
==
CW
)
{
// Below
FillLeftConvexEdgeEvent
(
tcx
,
edge
,
*
node
.
prev
);
}
else
{
// Above
}
}
}
void
Sweep
::
FillLeftConcaveEdgeEvent
(
SweepContext
&
tcx
,
Edge
*
edge
,
Node
&
node
)
{
Fill
(
tcx
,
*
node
.
prev
);
if
(
node
.
prev
->
point
!=
edge
->
p
)
{
// Next above or below edge?
if
(
Orient2d
(
*
edge
->
q
,
*
node
.
prev
->
point
,
*
edge
->
p
)
==
CW
)
{
// Below
if
(
Orient2d
(
*
node
.
point
,
*
node
.
prev
->
point
,
*
node
.
prev
->
prev
->
point
)
==
CW
)
{
// Next is concave
FillLeftConcaveEdgeEvent
(
tcx
,
edge
,
node
);
}
else
{
// Next is convex
}
}
}
}
void
Sweep
::
FlipEdgeEvent
(
SweepContext
&
tcx
,
Point
&
ep
,
Point
&
eq
,
Triangle
*
t
,
Point
&
p
)
{
Triangle
&
ot
=
t
->
NeighborAcross
(
p
);
Point
&
op
=
*
ot
.
OppositePoint
(
*
t
,
p
);
if
(
&
ot
==
NULL
)
{
// If we want to integrate the fillEdgeEvent do it here
// With current implementation we should never get here
//throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle");
assert
(
0
);
}
if
(
InScanArea
(
p
,
*
t
->
PointCCW
(
p
),
*
t
->
PointCW
(
p
),
op
))
{
// Lets rotate shared edge one vertex CW
RotateTrianglePair
(
*
t
,
p
,
ot
,
op
);
tcx
.
MapTriangleToNodes
(
*
t
);
tcx
.
MapTriangleToNodes
(
ot
);
if
(
p
==
eq
&&
op
==
ep
)
{
if
(
eq
==
*
tcx
.
edge_event
.
constrained_edge
->
q
&&
ep
==
*
tcx
.
edge_event
.
constrained_edge
->
p
)
{
t
->
MarkConstrainedEdge
(
&
ep
,
&
eq
);
ot
.
MarkConstrainedEdge
(
&
ep
,
&
eq
);
Legalize
(
tcx
,
*
t
);
Legalize
(
tcx
,
ot
);
}
else
{
// XXX: I think one of the triangles should be legalized here?
}
}
else
{
Orientation
o
=
Orient2d
(
eq
,
op
,
ep
);
t
=
&
NextFlipTriangle
(
tcx
,
(
int
)
o
,
*
t
,
ot
,
p
,
op
);
FlipEdgeEvent
(
tcx
,
ep
,
eq
,
t
,
p
);
}
}
else
{
Point
&
newP
=
NextFlipPoint
(
ep
,
eq
,
ot
,
op
);
FlipScanEdgeEvent
(
tcx
,
ep
,
eq
,
*
t
,
ot
,
newP
);
EdgeEvent
(
tcx
,
ep
,
eq
,
t
,
p
);
}
}
Triangle
&
Sweep
::
NextFlipTriangle
(
SweepContext
&
tcx
,
int
o
,
Triangle
&
t
,
Triangle
&
ot
,
Point
&
p
,
Point
&
op
)
{
if
(
o
==
CCW
)
{
// ot is not crossing edge after flip
int
edge_index
=
ot
.
EdgeIndex
(
&
p
,
&
op
);
ot
.
delaunay_edge
[
edge_index
]
=
true
;
Legalize
(
tcx
,
ot
);
ot
.
ClearDelunayEdges
();
return
t
;
}
// t is not crossing edge after flip
int
edge_index
=
t
.
EdgeIndex
(
&
p
,
&
op
);
t
.
delaunay_edge
[
edge_index
]
=
true
;
Legalize
(
tcx
,
t
);
t
.
ClearDelunayEdges
();
return
ot
;
}
Point
&
Sweep
::
NextFlipPoint
(
Point
&
ep
,
Point
&
eq
,
Triangle
&
ot
,
Point
&
op
)
{
Orientation
o2d
=
Orient2d
(
eq
,
op
,
ep
);
if
(
o2d
==
CW
)
{
// Right
return
*
ot
.
PointCCW
(
op
);
}
else
if
(
o2d
==
CCW
)
{
// Left
return
*
ot
.
PointCW
(
op
);
}
else
{
//throw new RuntimeException("[Unsupported] Opposing point on constrained edge");
assert
(
0
);
}
}
void
Sweep
::
FlipScanEdgeEvent
(
SweepContext
&
tcx
,
Point
&
ep
,
Point
&
eq
,
Triangle
&
flip_triangle
,
Triangle
&
t
,
Point
&
p
)
{
Triangle
&
ot
=
t
.
NeighborAcross
(
p
);
Point
&
op
=
*
ot
.
OppositePoint
(
t
,
p
);
if
(
&
t
.
NeighborAcross
(
p
)
==
NULL
)
{
// If we want to integrate the fillEdgeEvent do it here
// With current implementation we should never get here
//throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle");
assert
(
0
);
}
if
(
InScanArea
(
eq
,
*
flip_triangle
.
PointCCW
(
eq
),
*
flip_triangle
.
PointCW
(
eq
),
op
))
{
// flip with new edge op->eq
FlipEdgeEvent
(
tcx
,
eq
,
op
,
&
ot
,
op
);
// TODO: Actually I just figured out that it should be possible to
// improve this by getting the next ot and op before the the above
// flip and continue the flipScanEdgeEvent here
// set new ot and op here and loop back to inScanArea test
// also need to set a new flip_triangle first
// Turns out at first glance that this is somewhat complicated
// so it will have to wait.
}
else
{
Point
&
newP
=
NextFlipPoint
(
ep
,
eq
,
ot
,
op
);
FlipScanEdgeEvent
(
tcx
,
ep
,
eq
,
flip_triangle
,
ot
,
newP
);
}
}
Sweep
::~
Sweep
()
{
...
...
@@ -807,7 +807,7 @@ Sweep::~Sweep() {
delete
nodes_
[
i
];
}
}
}
}
}
polygon/poly2tri/sweep/sweep_context.h
View file @
0d4b71ef
/*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SWEEP_CONTEXT_H
#define SWEEP_CONTEXT_H
#include <list>
#include <vector>
#include <cstddef>
namespace
p2t
{
// Inital triangle factor, seed triangle will extend 30% of
// PointSet width to both left and right.
const
double
kAlpha
=
0
.
3
;
struct
Point
;
class
Triangle
;
struct
Node
;
struct
Edge
;
class
AdvancingFront
;
class
SweepContext
{
public
:
/// Constructor
SweepContext
(
std
::
vector
<
Point
*>
polyline
);
/// Destructor
~
SweepContext
();
void
set_head
(
Point
*
p1
);
Point
*
head
();
void
set_tail
(
Point
*
p1
);
Point
*
tail
();
int
point_count
();
Node
&
LocateNode
(
Point
&
point
);
void
RemoveNode
(
Node
*
node
);
void
CreateAdvancingFront
(
std
::
vector
<
Node
*>
nodes
);
/// Try to map a node to all sides of this triangle that don't have a neighbor
void
MapTriangleToNodes
(
Triangle
&
t
);
void
AddToMap
(
Triangle
*
triangle
);
Point
*
GetPoint
(
const
int
&
index
);
Point
*
GetPoints
();
void
RemoveFromMap
(
Triangle
*
triangle
);
void
AddHole
(
std
::
vector
<
Point
*>
polyline
);
void
AddPoint
(
Point
*
point
);
AdvancingFront
*
front
();
void
MeshClean
(
Triangle
&
triangle
);
std
::
vector
<
Triangle
*>
GetTriangles
();
/*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SWEEP_CONTEXT_H
#define SWEEP_CONTEXT_H
#include <list>
#include <vector>
#include <cstddef>
namespace
p2t
{
// Inital triangle factor, seed triangle will extend 30% of
// PointSet width to both left and right.
const
double
kAlpha
=
0
.
3
;
struct
Point
;
class
Triangle
;
struct
Node
;
struct
Edge
;
class
AdvancingFront
;
class
SweepContext
{
public
:
/// Constructor
SweepContext
(
std
::
vector
<
Point
*>
polyline
);
/// Destructor
~
SweepContext
();
void
set_head
(
Point
*
p1
);
Point
*
head
();
void
set_tail
(
Point
*
p1
);
Point
*
tail
();
int
point_count
();
Node
&
LocateNode
(
Point
&
point
);
void
RemoveNode
(
Node
*
node
);
void
CreateAdvancingFront
(
std
::
vector
<
Node
*>
nodes
);
/// Try to map a node to all sides of this triangle that don't have a neighbor
void
MapTriangleToNodes
(
Triangle
&
t
);
void
AddToMap
(
Triangle
*
triangle
);
Point
*
GetPoint
(
const
int
&
index
);
Point
*
GetPoints
();
void
RemoveFromMap
(
Triangle
*
triangle
);
void
AddHole
(
std
::
vector
<
Point
*>
polyline
);
void
AddPoint
(
Point
*
point
);
AdvancingFront
*
front
();
void
MeshClean
(
Triangle
&
triangle
);
std
::
vector
<
Triangle
*>
GetTriangles
();
std
::
list
<
Triangle
*>
GetMap
();
std
::
vector
<
Edge
*>
edge_list
;
struct
Basin
{
Node
*
left_node
;
Node
*
bottom_node
;
Node
*
right_node
;
double
width
;
bool
left_highest
;
Basin
()
:
left_node
(
NULL
),
bottom_node
(
NULL
),
right_node
(
NULL
),
width
(
0
.
0
),
left_highest
(
false
)
{
}
void
Clear
()
{
left_node
=
NULL
;
bottom_node
=
NULL
;
right_node
=
NULL
;
width
=
0
.
0
;
left_highest
=
false
;
}
};
struct
EdgeEvent
{
Edge
*
constrained_edge
;
bool
right
;
EdgeEvent
()
:
constrained_edge
(
NULL
),
right
(
false
)
{
}
};
Basin
basin
;
EdgeEvent
edge_event
;
private
:
friend
class
Sweep
;
std
::
vector
<
Triangle
*>
triangles_
;
std
::
list
<
Triangle
*>
map_
;
std
::
vector
<
Point
*>
points_
;
// Advancing front
AdvancingFront
*
front_
;
// head point used with advancing front
Point
*
head_
;
// tail point used with advancing front
Point
*
tail_
;
Node
*
af_head_
,
*
af_middle_
,
*
af_tail_
;
void
InitTriangulation
();
void
InitEdges
(
std
::
vector
<
Point
*>
polyline
);
};
inline
AdvancingFront
*
SweepContext
::
front
()
{
return
front_
;
}
inline
int
SweepContext
::
point_count
()
{
return
points_
.
size
();
}
inline
void
SweepContext
::
set_head
(
Point
*
p1
)
{
head_
=
p1
;
}
inline
Point
*
SweepContext
::
head
()
{
return
head_
;
}
inline
void
SweepContext
::
set_tail
(
Point
*
p1
)
{
tail_
=
p1
;
}
inline
Point
*
SweepContext
::
tail
()
{
return
tail_
;
}
}
#endif
std
::
vector
<
Edge
*>
edge_list
;
struct
Basin
{
Node
*
left_node
;
Node
*
bottom_node
;
Node
*
right_node
;
double
width
;
bool
left_highest
;
Basin
()
:
left_node
(
NULL
),
bottom_node
(
NULL
),
right_node
(
NULL
),
width
(
0
.
0
),
left_highest
(
false
)
{
}
void
Clear
()
{
left_node
=
NULL
;
bottom_node
=
NULL
;
right_node
=
NULL
;
width
=
0
.
0
;
left_highest
=
false
;
}
};
struct
EdgeEvent
{
Edge
*
constrained_edge
;
bool
right
;
EdgeEvent
()
:
constrained_edge
(
NULL
),
right
(
false
)
{
}
};
Basin
basin
;
EdgeEvent
edge_event
;
private
:
friend
class
Sweep
;
std
::
vector
<
Triangle
*>
triangles_
;
std
::
list
<
Triangle
*>
map_
;
std
::
vector
<
Point
*>
points_
;
// Advancing front
AdvancingFront
*
front_
;
// head point used with advancing front
Point
*
head_
;
// tail point used with advancing front
Point
*
tail_
;
Node
*
af_head_
,
*
af_middle_
,
*
af_tail_
;
void
InitTriangulation
();
void
InitEdges
(
std
::
vector
<
Point
*>
polyline
);
};
inline
AdvancingFront
*
SweepContext
::
front
()
{
return
front_
;
}
inline
int
SweepContext
::
point_count
()
{
return
points_
.
size
();
}
inline
void
SweepContext
::
set_head
(
Point
*
p1
)
{
head_
=
p1
;
}
inline
Point
*
SweepContext
::
head
()
{
return
head_
;
}
inline
void
SweepContext
::
set_tail
(
Point
*
p1
)
{
tail_
=
p1
;
}
inline
Point
*
SweepContext
::
tail
()
{
return
tail_
;
}
}
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment