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
6fa2f060
Commit
6fa2f060
authored
Apr 07, 2014
by
Maciej Suminski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Formatted ttl library to comply with KiCad coding policy.
parent
a0fb4ed0
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
2654 additions
and
2517 deletions
+2654
-2517
hetriang.cpp
common/geometry/hetriang.cpp
+556
-560
hedart.h
include/ttl/halfedge/hedart.h
+108
-67
hetraits.h
include/ttl/halfedge/hetraits.h
+124
-111
hetriang.h
include/ttl/halfedge/hetriang.h
+277
-207
ttl.h
include/ttl/ttl.h
+1510
-1479
ttl_util.h
include/ttl/ttl_util.h
+53
-67
ratsnest_data.cpp
pcbnew/ratsnest_data.cpp
+17
-17
ratsnest_data.h
pcbnew/ratsnest_data.h
+7
-7
ratsnest_viewitem.cpp
pcbnew/ratsnest_viewitem.cpp
+2
-2
No files found.
common/geometry/hetriang.cpp
View file @
6fa2f060
...
@@ -48,154 +48,154 @@
...
@@ -48,154 +48,154 @@
#include <boost/foreach.hpp>
#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>
#include <boost/make_shared.hpp>
using
namespace
hed
;
using
namespace
hed
;
using
namespace
std
;
#ifdef TTL_USE_NODE_ID
#ifdef TTL_USE_NODE_ID
int
N
ode
::
id_count
=
0
;
int
N
ODE
::
id_count
=
0
;
#endif
#endif
//#define DEBUG_HE
//#define DEBUG_HE
#ifdef DEBUG_HE
#ifdef DEBUG_HE
#include <iostream>
#include <iostream>
static
void
errorAndExit
(
char
*
message
)
{
static
void
errorAndExit
(
char
*
aMessage
)
cout
<<
"
\n
!!! ERROR: "
<<
message
<<
" !!!
\n
"
<<
endl
;
exit
(
-
1
);
{
}
cout
<<
"
\n
!!! ERROR: "
<<
aMessage
<<
" !!!
\n
"
<<
endl
;
exit
(
-
1
);
}
#endif
#endif
//--------------------------------------------------------------------------------------------------
static
EDGE_PTR
getLeadingEdgeInTriangle
(
const
EDGE_PTR
&
aEdge
)
static
EdgePtr
getLeadingEdgeInTriangle
(
const
EdgePtr
&
e
)
{
{
EdgePtr
edge
=
e
;
EDGE_PTR
edge
=
aEdg
e
;
// Code: 3EF (assumes triangle)
// Code: 3EF (assumes triangle)
if
(
!
edge
->
isLeadingEdge
())
{
if
(
!
edge
->
IsLeadingEdge
()
)
edge
=
edge
->
getNextEdgeInFace
();
{
if
(
!
edge
->
isLeadingEdge
())
edge
=
edge
->
GetNextEdgeInFace
();
edge
=
edge
->
getNextEdgeInFace
();
if
(
!
edge
->
IsLeadingEdge
()
)
edge
=
edge
->
GetNextEdgeInFace
();
}
}
if
(
!
edge
->
isLeadingEdge
())
{
if
(
!
edge
->
IsLeadingEdge
()
)
return
EdgePtr
();
{
return
EDGE_PTR
();
}
}
return
edge
;
return
edge
;
}
}
//--------------------------------------------------------------------------------------------------
static
void
getLimits
(
NODES_CONTAINER
::
iterator
aFirst
,
NODES_CONTAINER
::
iterator
aLast
,
static
void
getLimits
(
NodesContainer
::
iterator
first
,
int
&
aXmin
,
int
&
aYmin
,
int
&
aXmax
,
int
&
aYmax
)
NodesContainer
::
iterator
last
,
{
int
&
xmin
,
int
&
ymin
,
aXmin
=
aYmin
=
std
::
numeric_limits
<
int
>::
min
();
int
&
xmax
,
int
&
ymax
)
{
aXmax
=
aYmax
=
std
::
numeric_limits
<
int
>::
max
();
xmin
=
ymin
=
std
::
numeric_limits
<
int
>::
min
();
NODES_CONTAINER
::
iterator
it
;
xmax
=
ymax
=
std
::
numeric_limits
<
int
>::
max
();
NodesContainer
::
iterator
it
;
for
(
it
=
aFirst
;
it
!=
aLast
;
++
it
)
for
(
it
=
first
;
it
!=
last
;
++
it
)
{
{
xmin
=
min
(
xmin
,
(
*
it
)
->
GetX
()
);
aXmin
=
std
::
min
(
aXmin
,
(
*
it
)
->
GetX
()
);
ymin
=
min
(
ymin
,
(
*
it
)
->
GetY
()
);
aYmin
=
std
::
min
(
aYmin
,
(
*
it
)
->
GetY
()
);
xmax
=
max
(
xmax
,
(
*
it
)
->
GetX
()
);
aXmax
=
std
::
max
(
aXmax
,
(
*
it
)
->
GetX
()
);
ymax
=
max
(
ymax
,
(
*
it
)
->
GetY
()
);
aYmax
=
std
::
max
(
aYmax
,
(
*
it
)
->
GetY
()
);
}
}
}
}
//--------------------------------------------------------------------------------------------------
EDGE_PTR
TRIANGULATION
::
InitTwoEnclosingTriangles
(
NODES_CONTAINER
::
iterator
aFirst
,
EdgePtr
Triangulation
::
initTwoEnclosingTriangles
(
NodesContainer
::
iterator
first
,
NODES_CONTAINER
::
iterator
aLast
)
NodesContainer
::
iterator
last
)
{
{
int
xmin
,
ymin
,
xmax
,
ymax
;
int
xmin
,
ymin
,
xmax
,
ymax
;
getLimits
(
first
,
last
,
xmin
,
ymin
,
xmax
,
ymax
);
getLimits
(
aFirst
,
aLast
,
xmin
,
ymin
,
xmax
,
ymax
);
// Add 10% of range:
// Add 10% of range:
double
fac
=
10.0
;
double
fac
=
10.0
;
double
dx
=
(
xmax
-
xmin
)
/
fac
;
double
dx
=
(
xmax
-
xmin
)
/
fac
;
double
dy
=
(
ymax
-
ymin
)
/
fac
;
double
dy
=
(
ymax
-
ymin
)
/
fac
;
NodePtr
n1
=
boost
::
make_shared
<
Node
>
(
xmin
-
dx
,
ymin
-
dy
);
NODE_PTR
n1
=
boost
::
make_shared
<
NODE
>
(
xmin
-
dx
,
ymin
-
dy
);
NodePtr
n2
=
boost
::
make_shared
<
Node
>
(
xmax
+
dx
,
ymin
-
dy
);
NODE_PTR
n2
=
boost
::
make_shared
<
NODE
>
(
xmax
+
dx
,
ymin
-
dy
);
NodePtr
n3
=
boost
::
make_shared
<
Node
>
(
xmax
+
dx
,
ymax
+
dy
);
NODE_PTR
n3
=
boost
::
make_shared
<
NODE
>
(
xmax
+
dx
,
ymax
+
dy
);
NodePtr
n4
=
boost
::
make_shared
<
Node
>
(
xmin
-
dx
,
ymax
+
dy
);
NODE_PTR
n4
=
boost
::
make_shared
<
NODE
>
(
xmin
-
dx
,
ymax
+
dy
);
// diagonal
// diagonal
EdgePtr
e1d
=
boost
::
make_shared
<
Edge
>
();
EDGE_PTR
e1d
=
boost
::
make_shared
<
EDGE
>
();
EdgePtr
e2d
=
boost
::
make_shared
<
Edge
>
();
EDGE_PTR
e2d
=
boost
::
make_shared
<
EDGE
>
();
// lower triangle
// lower triangle
EdgePtr
e11
=
boost
::
make_shared
<
Edge
>
();
EDGE_PTR
e11
=
boost
::
make_shared
<
EDGE
>
();
EdgePtr
e12
=
boost
::
make_shared
<
Edge
>
();
EDGE_PTR
e12
=
boost
::
make_shared
<
EDGE
>
();
// upper triangle
// upper triangle
EdgePtr
e21
=
boost
::
make_shared
<
Edge
>
();
EDGE_PTR
e21
=
boost
::
make_shared
<
EDGE
>
();
EdgePtr
e22
=
boost
::
make_shared
<
Edge
>
();
EDGE_PTR
e22
=
boost
::
make_shared
<
EDGE
>
();
// lower triangle
// lower triangle
e1d
->
setSourceNode
(
n3
);
e1d
->
SetSourceNode
(
n3
);
e1d
->
setNextEdgeInFace
(
e11
);
e1d
->
SetNextEdgeInFace
(
e11
);
e1d
->
setTwinEdge
(
e2d
);
e1d
->
SetTwinEdge
(
e2d
);
addLeadingEdge
(
e1d
);
addLeadingEdge
(
e1d
);
e11
->
setSourceNode
(
n1
);
e11
->
SetSourceNode
(
n1
);
e11
->
setNextEdgeInFace
(
e12
);
e11
->
SetNextEdgeInFace
(
e12
);
e12
->
setSourceNode
(
n2
);
e12
->
SetSourceNode
(
n2
);
e12
->
setNextEdgeInFace
(
e1d
);
e12
->
SetNextEdgeInFace
(
e1d
);
// upper triangle
// upper triangle
e2d
->
setSourceNode
(
n1
);
e2d
->
SetSourceNode
(
n1
);
e2d
->
setNextEdgeInFace
(
e21
);
e2d
->
SetNextEdgeInFace
(
e21
);
e2d
->
setTwinEdge
(
e1d
);
e2d
->
SetTwinEdge
(
e1d
);
addLeadingEdge
(
e2d
);
addLeadingEdge
(
e2d
);
e21
->
setSourceNode
(
n3
);
e21
->
SetSourceNode
(
n3
);
e21
->
setNextEdgeInFace
(
e22
);
e21
->
SetNextEdgeInFace
(
e22
);
e22
->
setSourceNode
(
n4
);
e22
->
SetSourceNode
(
n4
);
e22
->
setNextEdgeInFace
(
e2d
);
e22
->
SetNextEdgeInFace
(
e2d
);
return
e11
;
return
e11
;
}
}
//--------------------------------------------------------------------------------------------------
TRIANGULATION
::
TRIANGULATION
()
Triangulation
::
Triangulation
()
{
{
helper
=
new
ttl
::
TriangulationHelper
(
*
this
);
m_helper
=
new
ttl
::
TRIANGULATION_HELPER
(
*
this
);
}
}
//--------------------------------------------------------------------------------------------------
TRIANGULATION
::
TRIANGULATION
(
const
TRIANGULATION
&
aTriangulation
)
Triangulation
::
Triangulation
(
const
Triangulation
&
tr
)
{
{
std
::
cout
<<
"Triangulation: Copy constructor not present - EXIT."
;
// Triangulation: Copy constructor not present
exit
(
-
1
);
assert
(
false
);
}
}
//--------------------------------------------------------------------------------------------------
TRIANGULATION
::~
TRIANGULATION
()
Triangulation
::~
Triangulation
()
{
{
cleanAll
();
cleanAll
();
delete
helper
;
delete
m_
helper
;
}
}
//--------------------------------------------------------------------------------------------------
void
TRIANGULATION
::
CreateDelaunay
(
NODES_CONTAINER
::
iterator
aFirst
,
void
Triangulation
::
createDelaunay
(
NodesContainer
::
iterator
first
,
NODES_CONTAINER
::
iterator
aLast
)
NodesContainer
::
iterator
last
)
{
{
cleanAll
();
cleanAll
();
EdgePtr
bedge
=
initTwoEnclosingTriangles
(
first
,
last
);
EDGE_PTR
bedge
=
InitTwoEnclosingTriangles
(
aFirst
,
aLast
);
Dart
dc
(
bedge
);
DART
dc
(
bedge
);
Dart
d_iter
=
dc
;
DART
d_iter
=
dc
;
NodesContainer
::
iterator
it
;
NODES_CONTAINER
::
iterator
it
;
for
(
it
=
first
;
it
!=
last
;
++
it
)
{
for
(
it
=
aFirst
;
it
!=
aLast
;
++
it
)
helper
->
insertNode
<
TTLtraits
>
(
d_iter
,
*
it
);
{
m_helper
->
InsertNode
<
TTLtraits
>
(
d_iter
,
*
it
);
}
}
// In general (e.g. for the triangle based data structure), the initial dart
// In general (e.g. for the triangle based data structure), the initial dart
...
@@ -206,112 +206,107 @@ void Triangulation::createDelaunay(NodesContainer::iterator first,
...
@@ -206,112 +206,107 @@ void Triangulation::createDelaunay(NodesContainer::iterator first,
// triangle "outside" the triangulation.)
// triangle "outside" the triangulation.)
// Assumes rectangular domain
// Assumes rectangular domain
helper
->
removeRectangularBoundary
<
TTLtraits
>
(
dc
);
m_helper
->
RemoveRectangularBoundary
<
TTLtraits
>
(
dc
);
}
}
//--------------------------------------------------------------------------------------------------
void
TRIANGULATION
::
RemoveTriangle
(
EDGE_PTR
&
aEdge
)
void
Triangulation
::
removeTriangle
(
EdgePtr
&
edge
)
{
{
EDGE_PTR
e1
=
getLeadingEdgeInTriangle
(
aEdge
);
EdgePtr
e1
=
getLeadingEdgeInTriangle
(
edge
);
#ifdef DEBUG_HE
#ifdef DEBUG_HE
if
(
!
e1
)
if
(
!
e1
)
errorAndExit
(
"Triangulation::removeTriangle: could not find leading edge"
);
errorAndExit
(
"Triangulation::removeTriangle: could not find leading aEdge"
);
#endif
#endif
removeLeadingEdgeFromList
(
e1
);
removeLeadingEdgeFromList
(
e1
);
// cout << "No leading edges = " << leadingEdges_.size() << endl;
// cout << "No leading edges = " << leadingEdges_.size() << endl;
// Remove the triangle
// Remove the triangle
EdgePtr
e2
(
e1
->
getNextEdgeInFace
()
);
EDGE_PTR
e2
(
e1
->
GetNextEdgeInFace
()
);
EdgePtr
e3
(
e2
->
getNextEdgeInFace
()
);
EDGE_PTR
e3
(
e2
->
GetNextEdgeInFace
()
);
e1
->
c
lear
();
e1
->
C
lear
();
e2
->
c
lear
();
e2
->
C
lear
();
e3
->
c
lear
();
e3
->
C
lear
();
}
}
//--------------------------------------------------------------------------------------------------
void
TRIANGULATION
::
ReverseSplitTriangle
(
EDGE_PTR
&
aEdge
)
void
Triangulation
::
reverse_splitTriangle
(
EdgePtr
&
edge
)
{
{
// Reverse operation of splitTriangle
// Reverse operation of splitTriangle
EDGE_PTR
e1
(
aEdge
->
GetNextEdgeInFace
()
);
EdgePtr
e1
(
edge
->
getNextEdgeInFace
());
EDGE_PTR
le
(
getLeadingEdgeInTriangle
(
e1
)
);
EdgePtr
le
(
getLeadingEdgeInTriangle
(
e1
));
#ifdef DEBUG_HE
#ifdef DEBUG_HE
if
(
!
le
)
if
(
!
le
)
errorAndExit
(
"Triangulation::removeTriangle: could not find leading edge"
);
errorAndExit
(
"Triangulation::removeTriangle: could not find leading edge"
);
#endif
#endif
removeLeadingEdgeFromList
(
le
);
removeLeadingEdgeFromList
(
le
);
EdgePtr
e2
(
e1
->
getNextEdgeInFace
()
->
getTwinEdge
()
->
getNextEdgeInFace
()
);
EDGE_PTR
e2
(
e1
->
GetNextEdgeInFace
()
->
GetTwinEdge
()
->
GetNextEdgeInFace
()
);
le
=
getLeadingEdgeInTriangle
(
e2
);
le
=
getLeadingEdgeInTriangle
(
e2
);
#ifdef DEBUG_HE
#ifdef DEBUG_HE
if
(
!
le
)
if
(
!
le
)
errorAndExit
(
"Triangulation::removeTriangle: could not find leading edge"
);
errorAndExit
(
"Triangulation::removeTriangle: could not find leading edge"
);
#endif
#endif
removeLeadingEdgeFromList
(
le
);
removeLeadingEdgeFromList
(
le
);
EdgePtr
e3
(
edge
->
getTwinEdge
()
->
getNextEdgeInFace
()
->
getNextEdgeInFace
()
);
EDGE_PTR
e3
(
aEdge
->
GetTwinEdge
()
->
GetNextEdgeInFace
()
->
GetNextEdgeInFace
()
);
le
=
getLeadingEdgeInTriangle
(
e3
);
le
=
getLeadingEdgeInTriangle
(
e3
);
#ifdef DEBUG_HE
#ifdef DEBUG_HE
if
(
!
le
)
if
(
!
le
)
errorAndExit
(
"Triangulation::removeTriangle: could not find leading edge"
);
errorAndExit
(
"Triangulation::removeTriangle: could not find leading edge"
);
#endif
#endif
removeLeadingEdgeFromList
(
le
);
removeLeadingEdgeFromList
(
le
);
// The three triangles at the node have now been removed
// The three triangles at the node have now been removed
// from the triangulation, but the arcs have not been deleted.
// from the triangulation, but the arcs have not been deleted.
// Next delete the 6 half edges radiating from the node
// Next delete the 6 half edges radiating from the node
// The node is maintained by handle and need not be deleted explicitly
// The node is maintained by handle and need not be deleted explicitly
EdgePtr
estar
=
e
dge
;
EDGE_PTR
estar
=
aE
dge
;
EdgePtr
enext
=
estar
->
getTwinEdge
()
->
g
etNextEdgeInFace
();
EDGE_PTR
enext
=
estar
->
GetTwinEdge
()
->
G
etNextEdgeInFace
();
estar
->
getTwinEdge
()
->
c
lear
();
estar
->
GetTwinEdge
()
->
C
lear
();
estar
->
c
lear
();
estar
->
C
lear
();
estar
=
enext
;
estar
=
enext
;
enext
=
estar
->
getTwinEdge
()
->
getNextEdgeInFace
();
enext
=
estar
->
GetTwinEdge
()
->
GetNextEdgeInFace
();
estar
->
getTwinEdge
()
->
clear
();
estar
->
GetTwinEdge
()
->
Clear
();
estar
->
clear
();
estar
->
Clear
();
enext
->
getTwinEdge
()
->
clear
();
enext
->
clear
();
enext
->
GetTwinEdge
()
->
Clear
();
enext
->
Clear
();
// Create the new triangle
// Create the new triangle
e1
->
setNextEdgeInFace
(
e2
);
e1
->
SetNextEdgeInFace
(
e2
);
e2
->
setNextEdgeInFace
(
e3
);
e2
->
SetNextEdgeInFace
(
e3
);
e3
->
setNextEdgeInFace
(
e1
);
e3
->
SetNextEdgeInFace
(
e1
);
addLeadingEdge
(
e1
);
addLeadingEdge
(
e1
);
}
}
//--------------------------------------------------------------------------------------------------
DART
TRIANGULATION
::
CreateDart
()
Dart
Triangulation
::
createDart
()
{
{
// Return an arbitrary CCW dart
// Return an arbitrary CCW dart
return
Dart
(
*
leadingEdges_
.
begin
()
);
return
DART
(
*
m_leadingEdges
.
begin
()
);
}
}
//--------------------------------------------------------------------------------------------------
bool
TRIANGULATION
::
removeLeadingEdgeFromList
(
EDGE_PTR
&
aLeadingEdge
)
bool
Triangulation
::
removeLeadingEdgeFromList
(
EdgePtr
&
leadingEdge
)
{
{
// Remove the edge from the list of leading edges,
// Remove the edge from the list of leading edges,
// but don't delete it.
// but don't delete it.
// Also set flag for leading edge to false.
// Also set flag for leading edge to false.
// Must search from start of list. Since edges are added to the
// Must search from start of list. Since edges are added to the
// start of the list during triangulation, this operation will
// start of the list during triangulation, this operation will
// normally be fast (when used in the triangulation algorithm)
// normally be fast (when used in the triangulation algorithm)
list
<
EdgePtr
>::
iterator
it
;
std
::
list
<
EDGE_PTR
>::
iterator
it
;
for
(
it
=
leadingEdges_
.
begin
();
it
!=
leadingEdges_
.
end
();
++
it
)
{
for
(
it
=
m_leadingEdges
.
begin
();
it
!=
m_leadingEdges
.
end
();
++
it
)
{
EdgePtr
edge
=
*
it
;
EDGE_PTR
edge
=
*
it
;
if
(
edge
==
leadingEdge
)
{
edge
->
setAsLeadingEdge
(
false
);
if
(
edge
==
aLeadingEdge
)
it
=
leadingEdges_
.
erase
(
it
);
{
edge
->
SetAsLeadingEdge
(
false
);
it
=
m_leadingEdges
.
erase
(
it
);
return
true
;
return
true
;
}
}
...
@@ -321,73 +316,75 @@ bool Triangulation::removeLeadingEdgeFromList(EdgePtr& leadingEdge) {
...
@@ -321,73 +316,75 @@ bool Triangulation::removeLeadingEdgeFromList(EdgePtr& leadingEdge) {
}
}
//--------------------------------------------------------------------------------------------------
void
TRIANGULATION
::
cleanAll
()
void
Triangulation
::
cleanAll
()
{
{
BOOST_FOREACH
(
EdgePtr
&
edge
,
leadingEdges_
)
BOOST_FOREACH
(
EDGE_PTR
&
edge
,
m_leadingEdges
)
edge
->
setNextEdgeInFace
(
EdgePtr
()
);
edge
->
SetNextEdgeInFace
(
EDGE_PTR
()
);
}
}
//--------------------------------------------------------------------------------------------------
void
TRIANGULATION
::
swapEdge
(
DART
&
aDart
)
void
Triangulation
::
swapEdge
(
Dart
&
dart
)
{
{
swapEdge
(
dart
.
getEdge
()
);
SwapEdge
(
aDart
.
GetEdge
()
);
}
}
//--------------------------------------------------------------------------------------------------
void
TRIANGULATION
::
splitTriangle
(
DART
&
aDart
,
const
NODE_PTR
&
aPoint
)
void
Triangulation
::
splitTriangle
(
Dart
&
dart
,
const
NodePtr
&
point
)
{
{
EdgePtr
edge
=
splitTriangle
(
dart
.
getEdge
(),
point
);
EDGE_PTR
edge
=
SplitTriangle
(
aDart
.
GetEdge
(),
aPoint
);
dart
.
init
(
edge
);
aDart
.
Init
(
edge
);
}
}
//--------------------------------------------------------------------------------------------------
void
TRIANGULATION
::
reverseSplitTriangle
(
DART
&
aDart
)
void
Triangulation
::
reverse_splitTriangle
(
Dart
&
dart
)
{
{
reverse_splitTriangle
(
dart
.
getEdge
()
);
ReverseSplitTriangle
(
aDart
.
GetEdge
()
);
}
}
//--------------------------------------------------------------------------------------------------
void
TRIANGULATION
::
removeBoundaryTriangle
(
DART
&
aDart
)
void
Triangulation
::
removeBoundaryTriangle
(
Dart
&
d
)
{
{
removeTriangle
(
d
.
getEdge
()
);
RemoveTriangle
(
aDart
.
GetEdge
()
);
}
}
#ifdef TTL_USE_NODE_FLAG
#ifdef TTL_USE_NODE_FLAG
//--------------------------------------------------------------------------------------------------
void
TRIANGULATION
::
FlagNodes
(
bool
aFlag
)
const
// This is a "template" for accessing all nodes (but multiple tests)
{
void
Triangulation
::
flagNodes
(
bool
flag
)
const
{
std
::
list
<
EDGE_PTR
>::
const_iterator
it
;
for
(
it
=
m_leadingEdges
.
begin
();
it
!=
m_leadingEdges
.
end
();
++
it
)
list
<
EdgePtr
>::
const_iterator
it
;
{
for
(
it
=
leadingEdges_
.
begin
();
it
!=
leadingEdges_
.
end
();
++
it
)
{
EDGE_PTR
edge
=
*
it
;
EdgePtr
edge
=
*
it
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
{
edge
->
getSourceNode
()
->
SetFlag
(
flag
);
edge
->
GetSourceNode
()
->
SetFlag
(
aFlag
);
edge
=
edge
->
g
etNextEdgeInFace
();
edge
=
edge
->
G
etNextEdgeInFace
();
}
}
}
}
}
}
//--------------------------------------------------------------------------------------------------
std
::
list
<
NODE_PTR
>*
TRIANGULATION
::
GetNodes
()
const
list
<
NodePtr
>*
Triangulation
::
getNodes
()
const
{
{
FlagNodes
(
false
);
flagNodes
(
false
)
;
std
::
list
<
NODE_PTR
>*
nodeList
=
new
std
::
list
<
NODE_PTR
>
;
list
<
NodePtr
>*
nodeList
=
new
list
<
NodePtr
>
;
std
::
list
<
EDGE_PTR
>::
const_iterator
it
;
list
<
EdgePtr
>::
const_iterator
it
;
for
(
it
=
m_leadingEdges
.
begin
();
it
!=
m_leadingEdges
.
end
();
++
it
)
for
(
it
=
leadingEdges_
.
begin
();
it
!=
leadingEdges_
.
end
();
++
it
)
{
{
EdgePtr
edge
=
*
it
;
EDGE_PTR
edge
=
*
it
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
for
(
int
i
=
0
;
i
<
3
;
++
i
)
const
NodePtr
&
node
=
edge
->
getSourceNode
();
{
const
NODE_PTR
&
node
=
edge
->
GetSourceNode
();
if
(
node
->
GetFlag
()
==
false
)
{
if
(
node
->
GetFlag
()
==
false
)
nodeList
->
push_back
(
node
);
{
node
->
SetFlag
(
true
);
nodeList
->
push_back
(
node
);
node
->
SetFlag
(
true
);
}
}
edge
=
edge
->
g
etNextEdgeInFace
();
edge
=
edge
->
G
etNextEdgeInFace
();
}
}
}
}
return
nodeList
;
return
nodeList
;
...
@@ -395,42 +392,38 @@ list<NodePtr>* Triangulation::getNodes() const {
...
@@ -395,42 +392,38 @@ list<NodePtr>* Triangulation::getNodes() const {
#endif
#endif
//--------------------------------------------------------------------------------------------------
std
::
list
<
EDGE_PTR
>*
TRIANGULATION
::
GetEdges
(
bool
aSkipBoundaryEdges
)
const
list
<
EdgePtr
>*
Triangulation
::
getEdges
(
bool
skip_boundary_edges
)
const
{
{
// collect all arcs (one half edge for each arc)
// collect all arcs (one half edge for each arc)
// (boundary edges are also collected).
// (boundary edges are also collected).
std
::
list
<
EDGE_PTR
>::
const_iterator
it
;
list
<
EdgePtr
>::
const_iterator
it
;
std
::
list
<
EDGE_PTR
>*
elist
=
new
std
::
list
<
EDGE_PTR
>
;
list
<
EdgePtr
>*
elist
=
new
list
<
EdgePtr
>
;
for
(
it
=
leadingEdges_
.
begin
();
it
!=
leadingEdges_
.
end
();
++
it
)
{
for
(
it
=
m_leadingEdges
.
begin
();
it
!=
m_leadingEdges
.
end
();
++
it
)
EdgePtr
edge
=
*
it
;
{
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
EDGE_PTR
edge
=
*
it
;
EdgePtr
twinedge
=
edge
->
getTwinEdge
();
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
EDGE_PTR
twinedge
=
edge
->
GetTwinEdge
();
// only one of the half-edges
// only one of the half-edges
if
(
(
!
twinedge
&&
!
skip_boundary_edges
)
||
if
(
(
!
twinedge
&&
!
aSkipBoundaryEdges
)
(
twinedge
&&
((
size_t
)
edge
.
get
()
>
(
size_t
)
twinedge
.
get
())
)
)
||
(
twinedge
&&
(
(
size_t
)
edge
.
get
()
>
(
size_t
)
twinedge
.
get
()
)
)
)
elist
->
push_front
(
edge
);
elist
->
push_front
(
edge
);
edge
=
edge
->
g
etNextEdgeInFace
();
edge
=
edge
->
G
etNextEdgeInFace
();
}
}
}
}
return
elist
;
return
elist
;
}
}
//--------------------------------------------------------------------------------------------------
EDGE_PTR
TRIANGULATION
::
SplitTriangle
(
EDGE_PTR
&
aEdge
,
const
NODE_PTR
&
aPoint
)
EdgePtr
Triangulation
::
splitTriangle
(
EdgePtr
&
edge
,
const
NodePtr
&
point
)
{
{
// Add a node by just splitting a triangle into three triangles
// Add a node by just splitting a triangle into three triangles
// Assumes the half edge is located in the triangle
// Assumes the half aEdge is located in the triangle
// Returns a half edge with source node as the new node
// Returns a half aEdge with source node as the new node
// double x, y, z;
// x = point.x();
// y = point.y();
// z = point.z();
// e#_n are new edges
// e#_n are new edges
// e# are existing edges
// e# are existing edges
...
@@ -438,158 +431,149 @@ EdgePtr Triangulation::splitTriangle(EdgePtr& edge, const NodePtr& point) {
...
@@ -438,158 +431,149 @@ EdgePtr Triangulation::splitTriangle(EdgePtr& edge, const NodePtr& point) {
// e##_n are edges incident to the new node
// e##_n are edges incident to the new node
// Add the node to the structure
// Add the node to the structure
//NodePtr
new_node(new Node(x,y,z));
//NODE_PTR
new_node(new Node(x,y,z));
NodePtr
n1
(
edge
->
getSourceNode
()
);
NODE_PTR
n1
(
aEdge
->
GetSourceNode
()
);
EdgePtr
e1
(
edge
);
EDGE_PTR
e1
(
aEdge
);
EdgePtr
e2
(
edge
->
getNextEdgeInFace
()
);
EDGE_PTR
e2
(
aEdge
->
GetNextEdgeInFace
()
);
NodePtr
n2
(
e2
->
getSourceNode
()
);
NODE_PTR
n2
(
e2
->
GetSourceNode
()
);
EdgePtr
e3
(
e2
->
getNextEdgeInFace
()
);
EDGE_PTR
e3
(
e2
->
GetNextEdgeInFace
()
);
NodePtr
n3
(
e3
->
getSourceNode
()
);
NODE_PTR
n3
(
e3
->
GetSourceNode
()
);
EdgePtr
e1_n
=
boost
::
make_shared
<
Edge
>
();
EDGE_PTR
e1_n
=
boost
::
make_shared
<
EDGE
>
();
EdgePtr
e11_n
=
boost
::
make_shared
<
Edge
>
();
EDGE_PTR
e11_n
=
boost
::
make_shared
<
EDGE
>
();
EdgePtr
e2_n
=
boost
::
make_shared
<
Edge
>
();
EDGE_PTR
e2_n
=
boost
::
make_shared
<
EDGE
>
();
EdgePtr
e22_n
=
boost
::
make_shared
<
Edge
>
();
EDGE_PTR
e22_n
=
boost
::
make_shared
<
EDGE
>
();
EdgePtr
e3_n
=
boost
::
make_shared
<
Edge
>
();
EDGE_PTR
e3_n
=
boost
::
make_shared
<
EDGE
>
();
EdgePtr
e33_n
=
boost
::
make_shared
<
Edge
>
();
EDGE_PTR
e33_n
=
boost
::
make_shared
<
EDGE
>
();
e1_n
->
setSourceNode
(
n1
);
e1_n
->
SetSourceNode
(
n1
);
e11_n
->
setSourceNode
(
point
);
e11_n
->
SetSourceNode
(
aPoint
);
e2_n
->
setSourceNode
(
n2
);
e2_n
->
SetSourceNode
(
n2
);
e22_n
->
setSourceNode
(
point
);
e22_n
->
SetSourceNode
(
aPoint
);
e3_n
->
setSourceNode
(
n3
);
e3_n
->
SetSourceNode
(
n3
);
e33_n
->
setSourceNode
(
point
);
e33_n
->
SetSourceNode
(
aPoint
);
e1_n
->
setTwinEdge
(
e11_n
);
e1_n
->
SetTwinEdge
(
e11_n
);
e11_n
->
setTwinEdge
(
e1_n
);
e11_n
->
SetTwinEdge
(
e1_n
);
e2_n
->
setTwinEdge
(
e22_n
);
e2_n
->
SetTwinEdge
(
e22_n
);
e22_n
->
setTwinEdge
(
e2_n
);
e22_n
->
SetTwinEdge
(
e2_n
);
e3_n
->
setTwinEdge
(
e33_n
);
e3_n
->
SetTwinEdge
(
e33_n
);
e33_n
->
setTwinEdge
(
e3_n
);
e33_n
->
SetTwinEdge
(
e3_n
);
e1_n
->
setNextEdgeInFace
(
e33_n
);
e1_n
->
SetNextEdgeInFace
(
e33_n
);
e2_n
->
setNextEdgeInFace
(
e11_n
);
e2_n
->
SetNextEdgeInFace
(
e11_n
);
e3_n
->
setNextEdgeInFace
(
e22_n
);
e3_n
->
SetNextEdgeInFace
(
e22_n
);
e11_n
->
setNextEdgeInFace
(
e1
);
e11_n
->
SetNextEdgeInFace
(
e1
);
e22_n
->
setNextEdgeInFace
(
e2
);
e22_n
->
SetNextEdgeInFace
(
e2
);
e33_n
->
setNextEdgeInFace
(
e3
);
e33_n
->
SetNextEdgeInFace
(
e3
);
// and update old's next e
dge
// and update old's next aE
dge
e1
->
setNextEdgeInFace
(
e2_n
);
e1
->
SetNextEdgeInFace
(
e2_n
);
e2
->
setNextEdgeInFace
(
e3_n
);
e2
->
SetNextEdgeInFace
(
e3_n
);
e3
->
setNextEdgeInFace
(
e1_n
);
e3
->
SetNextEdgeInFace
(
e1_n
);
// add the three new leading edges,
// add the three new leading edges,
// Must remove the old leading e
dge from the list.
// Must remove the old leading aE
dge from the list.
// Use the field telling if an edge is a leading e
dge
// Use the field telling if an aEdge is a leading aE
dge
// NOTE: Must search in the list!!!
// NOTE: Must search in the list!!!
if
(
e1
->
isLeadingEdge
()
)
if
(
e1
->
IsLeadingEdge
()
)
removeLeadingEdgeFromList
(
e1
);
removeLeadingEdgeFromList
(
e1
);
else
if
(
e2
->
isLeadingEdge
()
)
else
if
(
e2
->
IsLeadingEdge
()
)
removeLeadingEdgeFromList
(
e2
);
removeLeadingEdgeFromList
(
e2
);
else
if
(
e3
->
isLeadingEdge
()
)
else
if
(
e3
->
IsLeadingEdge
()
)
removeLeadingEdgeFromList
(
e3
);
removeLeadingEdgeFromList
(
e3
);
else
else
assert
(
false
);
// one of the edges should be leading
assert
(
false
);
// one of the edges should be leading
addLeadingEdge
(
e1_n
);
addLeadingEdge
(
e1_n
);
addLeadingEdge
(
e2_n
);
addLeadingEdge
(
e2_n
);
addLeadingEdge
(
e3_n
);
addLeadingEdge
(
e3_n
);
// Return a half e
dge incident to the new node (with the new node as source node)
// Return a half aE
dge incident to the new node (with the new node as source node)
return
e11_n
;
return
e11_n
;
}
}
//--------------------------------------------------------------------------------------------------
void
TRIANGULATION
::
SwapEdge
(
EDGE_PTR
&
aDiagonal
)
void
Triangulation
::
swapEdge
(
EdgePtr
&
diagonal
)
{
{
// Note that diagonal is both input and output and it is always
// Note that diagonal is both input and output and it is always
// kept in counterclockwise direction (this is not required by all
// kept in counterclockwise direction (this is not required by all
// functions in TriangulationHelper now)
// functions in TriangulationHelper now)
// Swap by rotating counterclockwise
// Swap by rotating counterclockwise
// Use the same objects - no deletion or new objects
// Use the same objects - no deletion or new objects
EdgePtr
eL
(
diagonal
);
EDGE_PTR
eL
(
aDiagonal
);
EdgePtr
eR
(
eL
->
getTwinEdge
()
);
EDGE_PTR
eR
(
eL
->
GetTwinEdge
()
);
EdgePtr
eL_1
(
eL
->
getNextEdgeInFace
()
);
EDGE_PTR
eL_1
(
eL
->
GetNextEdgeInFace
()
);
EdgePtr
eL_2
(
eL_1
->
getNextEdgeInFace
()
);
EDGE_PTR
eL_2
(
eL_1
->
GetNextEdgeInFace
()
);
EdgePtr
eR_1
(
eR
->
getNextEdgeInFace
()
);
EDGE_PTR
eR_1
(
eR
->
GetNextEdgeInFace
()
);
EdgePtr
eR_2
(
eR_1
->
getNextEdgeInFace
()
);
EDGE_PTR
eR_2
(
eR_1
->
GetNextEdgeInFace
()
);
// avoid node to be dereferenced to zero and deleted
// avoid node to be dereferenced to zero and deleted
NodePtr
nR
(
eR_2
->
getSourceNode
()
);
NODE_PTR
nR
(
eR_2
->
GetSourceNode
()
);
NodePtr
nL
(
eL_2
->
getSourceNode
()
);
NODE_PTR
nL
(
eL_2
->
GetSourceNode
()
);
eL
->
setSourceNode
(
nR
);
eL
->
SetSourceNode
(
nR
);
eR
->
setSourceNode
(
nL
);
eR
->
SetSourceNode
(
nL
);
// and now 6 1-sewings
// and now 6 1-sewings
eL
->
setNextEdgeInFace
(
eL_2
);
eL
->
SetNextEdgeInFace
(
eL_2
);
eL_2
->
setNextEdgeInFace
(
eR_1
);
eL_2
->
SetNextEdgeInFace
(
eR_1
);
eR_1
->
setNextEdgeInFace
(
eL
);
eR_1
->
SetNextEdgeInFace
(
eL
);
eR
->
setNextEdgeInFace
(
eR_2
);
eR
->
SetNextEdgeInFace
(
eR_2
);
eR_2
->
setNextEdgeInFace
(
eL_1
);
eR_2
->
SetNextEdgeInFace
(
eL_1
);
eL_1
->
setNextEdgeInFace
(
eR
);
eL_1
->
SetNextEdgeInFace
(
eR
);
if
(
eL
->
isLeadingEdge
()
)
if
(
eL
->
IsLeadingEdge
()
)
removeLeadingEdgeFromList
(
eL
);
removeLeadingEdgeFromList
(
eL
);
else
if
(
eL_1
->
isLeadingEdge
()
)
else
if
(
eL_1
->
IsLeadingEdge
()
)
removeLeadingEdgeFromList
(
eL_1
);
removeLeadingEdgeFromList
(
eL_1
);
else
if
(
eL_2
->
isLeadingEdge
()
)
else
if
(
eL_2
->
IsLeadingEdge
()
)
removeLeadingEdgeFromList
(
eL_2
);
removeLeadingEdgeFromList
(
eL_2
);
if
(
eR
->
isLeadingEdge
()
)
if
(
eR
->
IsLeadingEdge
()
)
removeLeadingEdgeFromList
(
eR
);
removeLeadingEdgeFromList
(
eR
);
else
if
(
eR_1
->
isLeadingEdge
()
)
else
if
(
eR_1
->
IsLeadingEdge
()
)
removeLeadingEdgeFromList
(
eR_1
);
removeLeadingEdgeFromList
(
eR_1
);
else
if
(
eR_2
->
isLeadingEdge
()
)
else
if
(
eR_2
->
IsLeadingEdge
()
)
removeLeadingEdgeFromList
(
eR_2
);
removeLeadingEdgeFromList
(
eR_2
);
addLeadingEdge
(
eL
);
addLeadingEdge
(
eL
);
addLeadingEdge
(
eR
);
addLeadingEdge
(
eR
);
}
}
////--------------------------------------------------------------------------
bool
TRIANGULATION
::
CheckDelaunay
()
const
//static void printEdge(const Dart& dart, ostream& ofile) {
{
//
// Dart d0 = dart;
// d0.alpha0();
//
// ofile << dart.x() << " " << dart.y() << endl;
// ofile << d0.x() << " " << d0.y() << endl;
//}
//--------------------------------------------------------------------------
bool
Triangulation
::
checkDelaunay
()
const
{
// ???? outputs !!!!
// ???? outputs !!!!
// ofstream os("qweND.dat");
// ofstream os("qweND.dat");
const
list
<
EdgePtr
>&
leadingEdges
=
g
etLeadingEdges
();
const
std
::
list
<
EDGE_PTR
>&
leadingEdges
=
G
etLeadingEdges
();
list
<
EdgePtr
>::
const_iterator
it
;
std
::
list
<
EDGE_PTR
>::
const_iterator
it
;
bool
ok
=
true
;
bool
ok
=
true
;
int
noNotDelaunay
=
0
;
int
noNotDelaunay
=
0
;
for
(
it
=
leadingEdges
.
begin
();
it
!=
leadingEdges
.
end
();
++
it
)
{
for
(
it
=
leadingEdges
.
begin
();
it
!=
leadingEdges
.
end
();
++
it
)
EdgePtr
edge
=
*
it
;
{
EDGE_PTR
edge
=
*
it
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
for
(
int
i
=
0
;
i
<
3
;
++
i
)
EdgePtr
twinedge
=
edge
->
getTwinEdge
();
{
EDGE_PTR
twinedge
=
edge
->
GetTwinEdge
();
// only one of the half-edges
// only one of the half-edges
if
(
!
twinedge
||
(
size_t
)
edge
.
get
()
>
(
size_t
)
twinedge
.
get
())
{
if
(
!
twinedge
||
(
size_t
)
edge
.
get
()
>
(
size_t
)
twinedge
.
get
()
)
Dart
dart
(
edge
);
{
if
(
helper
->
swapTestDelaunay
<
TTLtraits
>
(
dart
))
{
DART
dart
(
edge
);
if
(
m_helper
->
SwapTestDelaunay
<
TTLtraits
>
(
dart
)
)
{
noNotDelaunay
++
;
noNotDelaunay
++
;
//printEdge(dart,os); os << "\n";
//printEdge(dart,os); os << "\n";
...
@@ -597,7 +581,8 @@ bool Triangulation::checkDelaunay() const {
...
@@ -597,7 +581,8 @@ bool Triangulation::checkDelaunay() const {
//cout << "............. not Delaunay .... " << endl;
//cout << "............. not Delaunay .... " << endl;
}
}
}
}
edge
=
edge
->
getNextEdgeInFace
();
edge
=
edge
->
GetNextEdgeInFace
();
}
}
}
}
...
@@ -609,9 +594,8 @@ bool Triangulation::checkDelaunay() const {
...
@@ -609,9 +594,8 @@ bool Triangulation::checkDelaunay() const {
}
}
//--------------------------------------------------------------------------------------------------
void
TRIANGULATION
::
OptimizeDelaunay
()
void
Triangulation
::
optimizeDelaunay
()
{
{
// This function is also present in ttl where it is implemented
// This function is also present in ttl where it is implemented
// generically.
// generically.
// The implementation below is tailored for the half-edge data structure,
// The implementation below is tailored for the half-edge data structure,
...
@@ -619,114 +603,126 @@ void Triangulation::optimizeDelaunay() {
...
@@ -619,114 +603,126 @@ void Triangulation::optimizeDelaunay() {
// Collect all interior edges (one half edge for each arc)
// Collect all interior edges (one half edge for each arc)
bool
skip_boundary_edges
=
true
;
bool
skip_boundary_edges
=
true
;
list
<
EdgePtr
>*
elist
=
getEdges
(
skip_boundary_edges
);
std
::
list
<
EDGE_PTR
>*
elist
=
GetEdges
(
skip_boundary_edges
);
// Assumes that elist has only one half-edge for each arc.
// Assumes that elist has only one half-edge for each arc.
bool
cycling_check
=
true
;
bool
cycling_check
=
true
;
bool
optimal
=
false
;
bool
optimal
=
false
;
list
<
EdgePtr
>::
const_iterator
it
;
std
::
list
<
EDGE_PTR
>::
const_iterator
it
;
while
(
!
optimal
)
{
while
(
!
optimal
)
{
optimal
=
true
;
optimal
=
true
;
for
(
it
=
elist
->
begin
();
it
!=
elist
->
end
();
++
it
)
{
EdgePtr
edge
=
*
it
;
Dart
dart
(
edge
);
for
(
it
=
elist
->
begin
();
it
!=
elist
->
end
();
++
it
)
{
EDGE_PTR
edge
=
*
it
;
DART
dart
(
edge
);
// Constrained edges should not be swapped
// Constrained edges should not be swapped
if
(
helper
->
swapTestDelaunay
<
TTLtraits
>
(
dart
,
cycling_check
))
{
if
(
m_helper
->
SwapTestDelaunay
<
TTLtraits
>
(
dart
,
cycling_check
)
)
{
optimal
=
false
;
optimal
=
false
;
swapEdge
(
edge
);
SwapEdge
(
edge
);
}
}
}
}
}
}
delete
elist
;
delete
elist
;
}
}
//--------------------------------------------------------------------------------------------------
EDGE_PTR
TRIANGULATION
::
GetInteriorNode
()
const
EdgePtr
Triangulation
::
getInteriorNode
()
const
{
{
const
std
::
list
<
EDGE_PTR
>&
leadingEdges
=
GetLeadingEdges
();
std
::
list
<
EDGE_PTR
>::
const_iterator
it
;
const
list
<
EdgePtr
>&
leadingEdges
=
getLeadingEdges
();
for
(
it
=
leadingEdges
.
begin
();
it
!=
leadingEdges
.
end
();
++
it
)
list
<
EdgePtr
>::
const_iterator
it
;
{
for
(
it
=
leadingEdges
.
begin
();
it
!=
leadingEdges
.
end
();
++
it
)
{
EDGE_PTR
edge
=
*
it
;
EdgePtr
edge
=
*
it
;
// multiple checks, but only until found
// multiple checks, but only until found
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
for
(
int
i
=
0
;
i
<
3
;
++
i
)
if
(
edge
->
getTwinEdge
())
{
{
if
(
edge
->
GetTwinEdge
()
)
if
(
!
helper
->
isBoundaryNode
(
Dart
(
edge
)))
{
if
(
!
m_helper
->
IsBoundaryNode
(
DART
(
edge
)
)
)
return
edge
;
return
edge
;
}
}
edge
=
edge
->
getNextEdgeInFace
();
edge
=
edge
->
GetNextEdgeInFace
();
}
}
}
}
return
EdgePtr
();
// no boundary nodes
return
EDGE_PTR
();
// no boundary nodes
}
}
//--------------------------------------------------------------------------------------------------
EDGE_PTR
TRIANGULATION
::
GetBoundaryEdgeInTriangle
(
const
EDGE_PTR
&
aEdge
)
const
EdgePtr
Triangulation
::
getBoundaryEdgeInTriangle
(
const
EdgePtr
&
e
)
const
{
{
EdgePtr
edge
=
e
;
EDGE_PTR
edge
=
aEdg
e
;
if
(
helper
->
isBoundaryEdge
(
Dart
(
edge
))
)
if
(
m_helper
->
IsBoundaryEdge
(
DART
(
edge
)
)
)
return
edge
;
return
edge
;
edge
=
edge
->
g
etNextEdgeInFace
();
edge
=
edge
->
G
etNextEdgeInFace
();
if
(
helper
->
isBoundaryEdge
(
Dart
(
edge
))
)
if
(
m_helper
->
IsBoundaryEdge
(
DART
(
edge
)
)
)
return
edge
;
return
edge
;
edge
=
edge
->
g
etNextEdgeInFace
();
edge
=
edge
->
G
etNextEdgeInFace
();
if
(
helper
->
isBoundaryEdge
(
Dart
(
edge
))
)
if
(
m_helper
->
IsBoundaryEdge
(
DART
(
edge
)
)
)
return
edge
;
return
edge
;
return
EdgePtr
();
return
EDGE_PTR
();
}
}
//--------------------------------------------------------------------------------------------------
EDGE_PTR
TRIANGULATION
::
GetBoundaryEdge
()
const
EdgePtr
Triangulation
::
getBoundaryEdge
()
const
{
{
// Get an arbitrary (CCW) boundary edge
// Get an arbitrary (CCW) boundary edge
// If the triangulation is closed, NULL is returned
// If the triangulation is closed, NULL is returned
const
std
::
list
<
EDGE_PTR
>&
leadingEdges
=
GetLeadingEdges
();
std
::
list
<
EDGE_PTR
>::
const_iterator
it
;
EDGE_PTR
edge
;
const
list
<
EdgePtr
>&
leadingEdges
=
getLeadingEdges
();
for
(
it
=
leadingEdges
.
begin
();
it
!=
leadingEdges
.
end
();
++
it
)
list
<
EdgePtr
>::
const_iterator
it
;
{
EdgePtr
edge
;
edge
=
GetBoundaryEdgeInTriangle
(
*
it
);
for
(
it
=
leadingEdges
.
begin
();
it
!=
leadingEdges
.
end
();
++
it
)
{
edge
=
getBoundaryEdgeInTriangle
(
*
it
);
if
(
edge
)
if
(
edge
)
return
edge
;
return
edge
;
}
}
return
EdgePtr
();
return
EDGE_PTR
();
}
}
//--------------------------------------------------------------------------------------------------
void
TRIANGULATION
::
PrintEdges
(
std
::
ofstream
&
aOutput
)
const
void
Triangulation
::
printEdges
(
ofstream
&
os
)
const
{
{
// Print source node and target node for each edge face by face,
// Print source node and target node for each edge face by face,
// but only one of the half-edges.
// but only one of the half-edges.
const
std
::
list
<
EDGE_PTR
>&
leadingEdges
=
GetLeadingEdges
();
std
::
list
<
EDGE_PTR
>::
const_iterator
it
;
const
list
<
EdgePtr
>&
leadingEdges
=
getLeadingEdges
();
for
(
it
=
leadingEdges
.
begin
();
it
!=
leadingEdges
.
end
();
++
it
)
list
<
EdgePtr
>::
const_iterator
it
;
{
for
(
it
=
leadingEdges
.
begin
();
it
!=
leadingEdges
.
end
();
++
it
)
{
EDGE_PTR
edge
=
*
it
;
EdgePtr
edge
=
*
it
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
for
(
int
i
=
0
;
i
<
3
;
++
i
)
EdgePtr
twinedge
=
edge
->
getTwinEdge
();
{
EDGE_PTR
twinedge
=
edge
->
GetTwinEdge
();
// Print only one edge (the highest value of the pointer)
// Print only one edge (the highest value of the pointer)
if
(
!
twinedge
||
(
size_t
)
edge
.
get
()
>
(
size_t
)
twinedge
.
get
())
{
if
(
!
twinedge
||
(
size_t
)
edge
.
get
()
>
(
size_t
)
twinedge
.
get
()
)
{
// Print source node and target node
// Print source node and target node
NodePtr
node
=
edge
->
g
etSourceNode
();
NODE_PTR
node
=
edge
->
G
etSourceNode
();
os
<<
node
->
GetX
()
<<
" "
<<
node
->
GetY
()
<<
endl
;
aOutput
<<
node
->
GetX
()
<<
" "
<<
node
->
GetY
()
<<
std
::
endl
;
node
=
edge
->
g
etTargetNode
();
node
=
edge
->
G
etTargetNode
();
os
<<
node
->
GetX
()
<<
" "
<<
node
->
GetY
()
<<
endl
;
aOutput
<<
node
->
GetX
()
<<
" "
<<
node
->
GetY
()
<<
std
::
endl
;
os
<<
'\n'
;
// blank line
aOutput
<<
'\n'
;
// blank line
}
}
edge
=
edge
->
getNextEdgeInFace
();
edge
=
edge
->
GetNextEdgeInFace
();
}
}
}
}
}
}
include/ttl/halfedge/hedart.h
View file @
6fa2f060
...
@@ -40,111 +40,152 @@
...
@@ -40,111 +40,152 @@
#ifndef _HALF_EDGE_DART_
#ifndef _HALF_EDGE_DART_
#define _HALF_EDGE_DART_
#define _HALF_EDGE_DART_
#include <ttl/halfedge/hetriang.h>
#include <ttl/halfedge/hetriang.h>
namespace
hed
namespace
hed
{
{
/**
* \class Dart
//------------------------------------------------------------------------------------------------
// Dart class for the half-edge data structure
//------------------------------------------------------------------------------------------------
/** \class Dart
* \brief \b %Dart class for the half-edge data structure.
* \brief \b %Dart class for the half-edge data structure.
*
*
* See \ref api for a detailed description of how the member functions
* See \ref api for a detailed description of how the member functions
* should be implemented.
* should be implemented.
*/
*/
class
DART
{
EDGE_PTR
m_edge
;
class
Dart
{
/// Dart direction: true if dart is counterclockwise in face
bool
m_dir
;
EdgePtr
edge_
;
bool
dir_
;
// true if dart is counterclockwise in face
public
:
public
:
/// Default constructor
/// Default constructor
Dart
()
{
dir_
=
true
;
}
DART
()
{
m_dir
=
true
;
}
/// Constructor
/// Constructor
Dart
(
const
EdgePtr
&
edge
,
bool
dir
=
true
)
{
edge_
=
edge
;
dir_
=
dir
;
}
DART
(
const
EDGE_PTR
&
aEdge
,
bool
aDir
=
true
)
{
m_edge
=
aEdge
;
m_dir
=
aDir
;
}
/// Copy constructor
/// Copy constructor
Dart
(
const
Dart
&
dart
)
{
edge_
=
dart
.
edge_
;
dir_
=
dart
.
dir_
;
}
DART
(
const
DART
&
aDart
)
{
m_edge
=
aDart
.
m_edge
;
m_dir
=
aDart
.
m_dir
;
}
/// Destructor
/// Destructor
~
Dart
()
{}
~
DART
()
{
}
/// Assignment operator
/// Assignment operator
Dart
&
operator
=
(
const
Dart
&
dart
)
{
DART
&
operator
=
(
const
DART
&
aDart
)
if
(
this
==
&
dart
)
{
if
(
this
==
&
aDart
)
return
*
this
;
return
*
this
;
edge_
=
dart
.
edge_
;
dir_
=
dart
.
dir_
;
m_edge
=
aDart
.
m_edge
;
m_dir
=
aDart
.
m_dir
;
return
*
this
;
return
*
this
;
}
}
/// Comparing dart objects
/// Comparing dart objects
bool
operator
==
(
const
Dart
&
dart
)
const
{
bool
operator
==
(
const
DART
&
aDart
)
const
if
(
dart
.
edge_
==
edge_
&&
dart
.
dir_
==
dir_
)
{
return
true
;
return
(
aDart
.
m_edge
==
m_edge
&&
aDart
.
m_dir
==
m_dir
);
return
false
;
}
}
/// Comparing dart objects
/// Comparing dart objects
bool
operator
!=
(
const
Dart
&
dart
)
const
{
bool
operator
!=
(
const
DART
&
aDart
)
const
return
!
(
dart
==*
this
);
{
return
!
(
aDart
==
*
this
);
}
}
/// Maps the dart to a different node
/// Maps the dart to a different node
Dart
&
alpha0
()
{
dir_
=
!
dir_
;
return
*
this
;
}
DART
&
Alpha0
()
{
m_dir
=
!
m_dir
;
return
*
this
;
}
/// Maps the dart to a different edge
/// Maps the dart to a different edge
Dart
&
alpha1
()
{
DART
&
Alpha1
()
if
(
dir_
)
{
{
edge_
=
edge_
->
getNextEdgeInFace
()
->
getNextEdgeInFace
();
if
(
m_dir
)
dir_
=
false
;
{
m_edge
=
m_edge
->
GetNextEdgeInFace
()
->
GetNextEdgeInFace
();
m_dir
=
false
;
}
}
else
{
else
edge_
=
edge_
->
getNextEdgeInFace
();
{
dir_
=
true
;
m_edge
=
m_edge
->
GetNextEdgeInFace
();
m_dir
=
true
;
}
}
return
*
this
;
return
*
this
;
}
}
/// Maps the dart to a different triangle. \b Note: the dart is not changed if it is at the boundary!
/// Maps the dart to a different triangle. \b Note: the dart is not changed if it is at the boundary!
Dart
&
alpha2
()
{
DART
&
Alpha2
()
if
(
edge_
->
getTwinEdge
())
{
{
edge_
=
edge_
->
getTwinEdge
();
if
(
m_edge
->
GetTwinEdge
()
)
dir_
=
!
dir_
;
{
m_edge
=
m_edge
->
GetTwinEdge
();
m_dir
=
!
m_dir
;
}
}
// else, the dart is at the boundary and should not be changed
// else, the dart is at the boundary and should not be changed
return
*
this
;
return
*
this
;
}
}
// Utilities not required by TTL
// -----------------------------
/** @name Utilities not required by TTL */
/** @name Utilities not required by TTL */
//@{
//@{
void
Init
(
const
EDGE_PTR
&
aEdge
,
bool
aDir
=
true
)
{
m_edge
=
aEdge
;
m_dir
=
aDir
;
}
double
X
()
const
{
return
GetNode
()
->
GetX
();
}
void
init
(
const
EdgePtr
&
edge
,
bool
dir
=
true
)
{
edge_
=
edge
;
dir_
=
dir
;
}
double
Y
()
const
{
return
GetNode
()
->
GetY
();
}
double
x
()
const
{
return
getNode
()
->
GetX
();
}
// x-coordinate of source node
bool
IsCCW
()
const
double
y
()
const
{
return
getNode
()
->
GetY
();
}
// y-coordinate of source node
{
return
m_dir
;
}
bool
isCounterClockWise
()
const
{
return
dir_
;
}
const
NODE_PTR
&
GetNode
()
const
{
return
m_dir
?
m_edge
->
GetSourceNode
()
:
m_edge
->
GetTargetNode
();
}
const
NodePtr
&
getNode
()
const
{
return
dir_
?
edge_
->
getSourceNode
()
:
edge_
->
getTargetNode
();
}
const
NODE_PTR
&
GetOppositeNode
()
const
const
NodePtr
&
getOppositeNode
()
const
{
return
dir_
?
edge_
->
getTargetNode
()
:
edge_
->
getSourceNode
();
}
{
EdgePtr
&
getEdge
()
{
return
edge_
;
}
return
m_dir
?
m_edge
->
GetTargetNode
()
:
m_edge
->
GetSourceNode
();
}
//@} // End of Utilities not required by TTL
EDGE_PTR
&
GetEdge
()
{
return
m_edge
;
}
};
//@} // End of Utilities not required by TTL
};
}
;
// End of hed namespace
}
// End of hed namespace
#endif
#endif
include/ttl/halfedge/hetraits.h
View file @
6fa2f060
...
@@ -40,19 +40,13 @@
...
@@ -40,19 +40,13 @@
#ifndef _HALF_EDGE_TRAITS_
#ifndef _HALF_EDGE_TRAITS_
#define _HALF_EDGE_TRAITS_
#define _HALF_EDGE_TRAITS_
#include <ttl/halfedge/hetriang.h>
#include <ttl/halfedge/hetriang.h>
#include <ttl/halfedge/hedart.h>
#include <ttl/halfedge/hedart.h>
namespace
hed
namespace
hed
{
{
/**
* \struct TTLtraits
//------------------------------------------------------------------------------------------------
// Traits class for the half-edge data structure
//------------------------------------------------------------------------------------------------
/** \struct TTLtraits
* \brief \b Traits class (static struct) for the half-edge data structure.
* \brief \b Traits class (static struct) for the half-edge data structure.
*
*
* The member functions are those required by different function templates
* The member functions are those required by different function templates
...
@@ -64,112 +58,131 @@ namespace hed {
...
@@ -64,112 +58,131 @@ namespace hed {
* half-edge data structure.
* half-edge data structure.
*
*
* \see \ref api
* \see \ref api
*
*/
*/
struct
TTLtraits
struct
TTLtraits
{
{
/**
/** The floating point type used in calculations
* The floating point type used in calculations involving scalar products and cross products.
* involving scalar products and cross products.
*/
*/
typedef
double
real_type
;
typedef
double
REAL_TYPE
;
//----------------------------------------------------------------------------------------------
// ------------------------------- Geometric Predicates Group ---------------------------------
//----------------------------------------------------------------------------------------------
/** @name Geometric Predicates */
/** @name Geometric Predicates */
//@{
//@{
/**
//----------------------------------------------------------------------------------------------
* Scalar product between two 2D vectors represented as darts.\n
/** Scalar product between two 2D vectors represented as darts.\n
*
*
* ttl_util::scalarProduct2d can be used.
* ttl_util::scalarProduct2d can be used.
*/
*/
static
real_type
scalarProduct2d
(
const
Dart
&
v1
,
const
Dart
&
v2
)
{
static
REAL_TYPE
ScalarProduct2D
(
const
DART
&
aV1
,
const
DART
&
aV2
)
Dart
v10
=
v1
;
v10
.
alpha0
();
{
Dart
v20
=
v2
;
v20
.
alpha0
();
DART
v10
=
aV1
;
return
ttl_util
::
scalarProduct2d
(
v10
.
x
()
-
v1
.
x
(),
v10
.
y
()
-
v1
.
y
(),
v10
.
Alpha0
();
v20
.
x
()
-
v2
.
x
(),
v20
.
y
()
-
v2
.
y
());
}
DART
v20
=
aV2
;
v20
.
Alpha0
();
//----------------------------------------------------------------------------------------------
return
ttl_util
::
ScalarProduct2D
(
v10
.
X
()
-
aV1
.
X
(),
v10
.
Y
()
-
aV1
.
Y
(),
/** Scalar product between two 2D vectors.
v20
.
X
()
-
aV2
.
X
(),
v20
.
Y
()
-
aV2
.
Y
()
);
}
/**
* Scalar product between two 2D vectors.
* The first vector is represented by a dart \e v, and the second
* The first vector is represented by a dart \e v, and the second
* vector has direction from the source node of \e v to the point \e p.\n
* vector has direction from the source node of \e v to the point \e p.\n
*
*
* ttl_util::scalarProduct2d
can be used.
* ttl_util::ScalarProduct2D
can be used.
*/
*/
static
real_type
scalarProduct2d
(
const
Dart
&
v
,
const
NodePtr
&
p
)
{
static
REAL_TYPE
ScalarProduct2D
(
const
DART
&
aV
,
const
NODE_PTR
&
aP
)
Dart
d0
=
v
;
d0
.
alpha0
();
{
return
ttl_util
::
scalarProduct2d
(
d0
.
x
()
-
v
.
x
(),
d0
.
y
()
-
v
.
y
(),
DART
d0
=
aV
;
p
->
GetX
()
-
v
.
x
(),
p
->
GetY
()
-
v
.
y
());
d0
.
Alpha0
();
}
return
ttl_util
::
ScalarProduct2D
(
d0
.
X
()
-
aV
.
X
(),
d0
.
Y
()
-
aV
.
Y
(),
aP
->
GetX
()
-
aV
.
X
(),
aP
->
GetY
()
-
aV
.
Y
()
);
}
/
/----------------------------------------------------------------------------------------------
/
**
/*
* Cross product between two vectors in the plane represented as darts.
* Cross product between two vectors in the plane represented as darts.
* The z-component of the cross product is returned.\n
* The z-component of the cross product is returned.\n
*
*
* ttl_util::crossProduct2d
can be used.
* ttl_util::CrossProduct2D
can be used.
*/
*/
static
real_type
crossProduct2d
(
const
Dart
&
v1
,
const
Dart
&
v2
)
{
static
REAL_TYPE
CrossProduct2D
(
const
DART
&
aV1
,
const
DART
&
aV2
)
Dart
v10
=
v1
;
v10
.
alpha0
();
{
Dart
v20
=
v2
;
v20
.
alpha0
();
DART
v10
=
aV1
;
return
ttl_util
::
crossProduct2d
(
v10
.
x
()
-
v1
.
x
(),
v10
.
y
()
-
v1
.
y
(),
v10
.
Alpha0
();
v20
.
x
()
-
v2
.
x
(),
v20
.
y
()
-
v2
.
y
());
}
DART
v20
=
aV2
;
v20
.
Alpha0
();
//----------------------------------------------------------------------------------------------
return
ttl_util
::
CrossProduct2D
(
v10
.
X
()
-
aV1
.
X
(),
v10
.
Y
()
-
aV1
.
Y
(),
/** Cross product between two vectors in the plane.
v20
.
X
()
-
aV2
.
X
(),
v20
.
Y
()
-
aV2
.
Y
()
);
}
/**
* Cross product between two vectors in the plane.
* The first vector is represented by a dart \e v, and the second
* The first vector is represented by a dart \e v, and the second
* vector has direction from the source node of \e v to the point \e p.
* vector has direction from the source node of \e v to the point \e p.
* The z-component of the cross product is returned.\n
* The z-component of the cross product is returned.\n
*
*
* ttl_util::c
rossProduct2d can be used.
* ttl_util::C
rossProduct2d can be used.
*/
*/
static
real_type
crossProduct2d
(
const
Dart
&
v
,
const
NodePtr
&
p
)
{
static
REAL_TYPE
CrossProduct2D
(
const
DART
&
aV
,
const
NODE_PTR
&
aP
)
Dart
d0
=
v
;
d0
.
alpha0
();
{
return
ttl_util
::
crossProduct2d
(
d0
.
x
()
-
v
.
x
(),
d0
.
y
()
-
v
.
y
(),
DART
d0
=
aV
;
p
->
GetX
()
-
v
.
x
(),
p
->
GetY
()
-
v
.
y
());
d0
.
Alpha0
();
}
return
ttl_util
::
CrossProduct2D
(
d0
.
X
()
-
aV
.
X
(),
d0
.
Y
()
-
aV
.
Y
(),
aP
->
GetX
()
-
aV
.
X
(),
aP
->
GetY
()
-
aV
.
Y
()
);
}
/
/----------------------------------------------------------------------------------------------
/
**
/*
* Let \e n1 and \e n2 be the nodes associated with two darts, and let \e p
* Let \e n1 and \e n2 be the nodes associated with two darts, and let \e p
* be a point in the plane. Return a positive value if \e n1, \e n2,
* be a point in the plane. Return a positive value if \e n1, \e n2,
* and \e p occur in counterclockwise order; a negative value if they occur
* and \e p occur in counterclockwise order; a negative value if they occur
* in clockwise order; and zero if they are collinear.
* in clockwise order; and zero if they are collinear.
*/
*/
static
real_type
orient2d
(
const
Dart
&
n1
,
const
Dart
&
n2
,
const
NodePtr
&
p
)
{
static
REAL_TYPE
Orient2D
(
const
DART
&
aN1
,
const
DART
&
aN2
,
const
NODE_PTR
&
aP
)
real_type
pa
[
2
];
real_type
pb
[
2
];
real_type
pc
[
2
];
{
pa
[
0
]
=
n1
.
x
();
pa
[
1
]
=
n1
.
y
();
REAL_TYPE
pa
[
2
];
pb
[
0
]
=
n2
.
x
();
pb
[
1
]
=
n2
.
y
();
REAL_TYPE
pb
[
2
];
pc
[
0
]
=
p
->
GetX
();
pc
[
1
]
=
p
->
GetY
();
REAL_TYPE
pc
[
2
];
return
ttl_util
::
orient2dfast
(
pa
,
pb
,
pc
);
pa
[
0
]
=
aN1
.
X
();
pa
[
1
]
=
aN1
.
Y
();
pb
[
0
]
=
aN2
.
X
();
pb
[
1
]
=
aN2
.
Y
();
pc
[
0
]
=
aP
->
GetX
();
pc
[
1
]
=
aP
->
GetY
();
return
ttl_util
::
Orient2DFast
(
pa
,
pb
,
pc
);
}
}
/**
//----------------------------------------------------------------------------------------------
* This is the same predicate as represented with the function above,
/** This is the same predicate as represented with the function above,
* but with a slighty different interface:
* but with a slighty different interface:
* The last parameter is given as a dart where the source node of the dart
* The last parameter is given as a dart where the source node of the dart
* represents a point in the plane.
* represents a point in the plane.
* This function is required for constrained triangulation.
* This function is required for constrained triangulation.
*/
*/
static
real_type
orient2d
(
const
Dart
&
n1
,
const
Dart
&
n2
,
const
Dart
&
p
)
{
static
REAL_TYPE
Orient2D
(
const
DART
&
aN1
,
const
DART
&
aN2
,
const
DART
&
aP
)
real_type
pa
[
2
];
real_type
pb
[
2
];
real_type
pc
[
2
];
{
pa
[
0
]
=
n1
.
x
();
pa
[
1
]
=
n1
.
y
();
REAL_TYPE
pa
[
2
];
pb
[
0
]
=
n2
.
x
();
pb
[
1
]
=
n2
.
y
();
REAL_TYPE
pb
[
2
];
pc
[
0
]
=
p
.
x
();
pc
[
1
]
=
p
.
y
();
REAL_TYPE
pc
[
2
];
return
ttl_util
::
orient2dfast
(
pa
,
pb
,
pc
);
pa
[
0
]
=
aN1
.
X
();
pa
[
1
]
=
aN1
.
Y
();
pb
[
0
]
=
aN2
.
X
();
pb
[
1
]
=
aN2
.
Y
();
pc
[
0
]
=
aP
.
X
();
pc
[
1
]
=
aP
.
Y
();
return
ttl_util
::
Orient2DFast
(
pa
,
pb
,
pc
);
}
}
//@} // End of Geometric Predicates Group
//@} // End of Geometric Predicates Group
};
};
};
// End of hed namespace
};
// End of hed namespace
...
...
include/ttl/halfedge/hetriang.h
View file @
6fa2f060
...
@@ -42,11 +42,9 @@
...
@@ -42,11 +42,9 @@
#ifndef _HE_TRIANG_H_
#ifndef _HE_TRIANG_H_
#define _HE_TRIANG_H_
#define _HE_TRIANG_H_
#define TTL_USE_NODE_ID // Each node gets it's own unique id
#define TTL_USE_NODE_ID // Each node gets it's own unique id
#define TTL_USE_NODE_FLAG // Each node gets a flag (can be set to true or false)
#define TTL_USE_NODE_FLAG // Each node gets a flag (can be set to true or false)
#include <list>
#include <list>
#include <vector>
#include <vector>
#include <iostream>
#include <iostream>
...
@@ -55,28 +53,26 @@
...
@@ -55,28 +53,26 @@
#include <boost/shared_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/weak_ptr.hpp>
namespace
ttl
{
namespace
ttl
class
TriangulationHelper
;
{
class
TRIANGULATION_HELPER
;
};
};
//--------------------------------------------------------------------------------------------------
/**
// The half-edge data structure
* The half-edge data structure
//--------------------------------------------------------------------------------------------------
*/
namespace
hed
namespace
hed
{
{
// Helper typedefs
// Helper typedefs
class
Node
;
class
NODE
;
class
Edge
;
class
EDGE
;
typedef
boost
::
shared_ptr
<
Node
>
NodePtr
;
typedef
boost
::
shared_ptr
<
NODE
>
NODE_PTR
;
typedef
boost
::
shared_ptr
<
Edge
>
EdgePtr
;
typedef
boost
::
shared_ptr
<
EDGE
>
EDGE_PTR
;
typedef
boost
::
weak_ptr
<
Edge
>
EdgeWeakPtr
;
typedef
boost
::
weak_ptr
<
EDGE
>
EDGE_WEAK_PTR
;
typedef
std
::
vector
<
NodePtr
>
NodesContainer
;
typedef
std
::
vector
<
NODE_PTR
>
NODES_CONTAINER
;
//------------------------------------------------------------------------------------------------
/**
// Node class for data structures
* \class NODE
//------------------------------------------------------------------------------------------------
/** \class Node
* \brief \b Node class for data structures (Inherits from HandleId)
* \brief \b Node class for data structures (Inherits from HandleId)
*
*
* \note
* \note
...
@@ -85,13 +81,12 @@ namespace hed {
...
@@ -85,13 +81,12 @@ namespace hed {
* - TTL_USE_NODE_ID and TTL_USE_NODE_FLAG should only be enabled if this functionality is
* - TTL_USE_NODE_ID and TTL_USE_NODE_FLAG should only be enabled if this functionality is
* required by the application, because they increase the memory usage for each Node object.
* required by the application, because they increase the memory usage for each Node object.
*/
*/
class
NODE
class
Node
{
{
protected
:
protected
:
#ifdef TTL_USE_NODE_FLAG
#ifdef TTL_USE_NODE_FLAG
/// TTL_USE_NODE_FLAG must be defined
/// TTL_USE_NODE_FLAG must be defined
bool
flag_
;
bool
m_flag
;
#endif
#endif
#ifdef TTL_USE_NODE_ID
#ifdef TTL_USE_NODE_ID
...
@@ -99,173 +94,245 @@ protected:
...
@@ -99,173 +94,245 @@ protected:
static
int
id_count
;
static
int
id_count
;
/// A unique id for each node (TTL_USE_NODE_ID must be defined)
/// A unique id for each node (TTL_USE_NODE_ID must be defined)
int
id_
;
int
m_id
;
#endif
#endif
int
x_
,
y_
;
/// Node coordinates
int
m_x
,
m_y
;
unsigned
int
refCount_
;
/// Reference count
unsigned
int
m_refCount
;
public
:
public
:
/// Constructor
/// Constructor
N
ode
(
int
x
=
0
,
int
y
=
0
)
:
N
ODE
(
int
aX
=
0
,
int
aY
=
0
)
:
#ifdef TTL_USE_NODE_FLAG
#ifdef TTL_USE_NODE_FLAG
flag_
(
false
),
m_flag
(
false
),
#endif
#endif
#ifdef TTL_USE_NODE_ID
#ifdef TTL_USE_NODE_ID
id_
(
id_count
++
),
m_id
(
id_count
++
),
#endif
#endif
x_
(
x
),
y_
(
y
),
refCount_
(
0
)
{}
m_x
(
aX
),
m_y
(
aY
),
m_refCount
(
0
)
{
}
/// Destructor
/// Destructor
~
N
ode
()
{}
~
N
ODE
()
{}
/// Returns the x-coordinate
/// Returns the x-coordinate
int
GetX
()
const
{
return
x_
;
}
int
GetX
()
const
{
return
m_x
;
}
/// Returns the y-coordinate
/// Returns the y-coordinate
int
GetY
()
const
{
return
y_
;
}
int
GetY
()
const
{
return
m_y
;
}
#ifdef TTL_USE_NODE_ID
#ifdef TTL_USE_NODE_ID
/// Returns the id (TTL_USE_NODE_ID must be defined)
/// Returns the id (TTL_USE_NODE_ID must be defined)
int
Id
()
const
{
return
id_
;
}
int
Id
()
const
{
return
m_id
;
}
#endif
#endif
#ifdef TTL_USE_NODE_FLAG
#ifdef TTL_USE_NODE_FLAG
/// Sets the flag (TTL_USE_NODE_FLAG must be defined)
/// Sets the flag (TTL_USE_NODE_FLAG must be defined)
void
SetFlag
(
bool
aFlag
)
{
flag_
=
aFlag
;
}
void
SetFlag
(
bool
aFlag
)
{
m_flag
=
aFlag
;
}
/// Returns the flag (TTL_USE_NODE_FLAG must be defined)
/// Returns the flag (TTL_USE_NODE_FLAG must be defined)
const
bool
&
GetFlag
()
const
{
return
flag_
;
}
const
bool
&
GetFlag
()
const
{
return
m_flag
;
}
#endif
#endif
void
IncRefCount
()
{
refCount_
++
;
}
void
IncRefCount
()
void
DecRefCount
()
{
refCount_
--
;
}
{
unsigned
int
GetRefCount
()
const
{
return
refCount_
;
}
m_refCount
++
;
};
// End of class Node
}
void
DecRefCount
()
{
m_refCount
--
;
}
unsigned
int
GetRefCount
()
const
{
return
m_refCount
;
}
};
//------------------------------------------------------------------------------------------------
// Edge class in the half-edge data structure
//------------------------------------------------------------------------------------------------
/** \class Edge
/**
* \class EDGE
* \brief \b %Edge class in the in the half-edge data structure.
* \brief \b %Edge class in the in the half-edge data structure.
*/
*/
class
EDGE
class
Edge
{
{
public
:
public
:
/// Constructor
/// Constructor
Edge
()
:
weight_
(
0
),
isLeadingEdge_
(
false
)
{}
EDGE
()
:
m_weight
(
0
),
m_isLeadingEdge
(
false
)
{
}
/// Destructor
/// Destructor
virtual
~
Edge
()
{}
virtual
~
EDGE
()
{
}
/// Sets the source node
/// Sets the source node
void
setSourceNode
(
const
NodePtr
&
node
)
{
sourceNode_
=
node
;
}
void
SetSourceNode
(
const
NODE_PTR
&
aNode
)
{
m_sourceNode
=
aNode
;
}
/// Sets the next edge in face
/// Sets the next edge in face
void
setNextEdgeInFace
(
const
EdgePtr
&
edge
)
{
nextEdgeInFace_
=
edge
;
}
void
SetNextEdgeInFace
(
const
EDGE_PTR
&
aEdge
)
{
m_nextEdgeInFace
=
aEdge
;
}
/// Sets the twin edge
/// Sets the twin edge
void
setTwinEdge
(
const
EdgePtr
&
edge
)
{
twinEdge_
=
edge
;
}
void
SetTwinEdge
(
const
EDGE_PTR
&
aEdge
)
{
m_twinEdge
=
aEdge
;
}
/// Sets the edge as a leading edge
/// Sets the edge as a leading edge
void
setAsLeadingEdge
(
bool
val
=
true
)
{
isLeadingEdge_
=
val
;
}
void
SetAsLeadingEdge
(
bool
aLeading
=
true
)
{
m_isLeadingEdge
=
aLeading
;
}
/// Checks if an edge is a leading edge
/// Checks if an edge is a leading edge
bool
isLeadingEdge
()
const
{
return
isLeadingEdge_
;
}
bool
IsLeadingEdge
()
const
{
return
m_isLeadingEdge
;
}
/// Returns the twin edge
/// Returns the twin edge
EdgePtr
getTwinEdge
()
const
{
return
twinEdge_
.
lock
();
};
EDGE_PTR
GetTwinEdge
()
const
{
return
m_twinEdge
.
lock
();
}
void
clearTwinEdge
()
{
twinEdge_
.
reset
();
}
void
ClearTwinEdge
()
{
m_twinEdge
.
reset
();
}
/// Returns the next edge in face
/// Returns the next edge in face
const
EdgePtr
&
getNextEdgeInFace
()
const
{
return
nextEdgeInFace_
;
}
const
EDGE_PTR
&
GetNextEdgeInFace
()
const
{
return
m_nextEdgeInFace
;
}
/// Retuns the source node
/// Retuns the source node
const
NodePtr
&
getSourceNode
()
const
{
return
sourceNode_
;
}
const
NODE_PTR
&
GetSourceNode
()
const
{
return
m_sourceNode
;
}
/// Returns the target node
/// Returns the target node
virtual
const
NodePtr
&
getTargetNode
()
const
{
return
nextEdgeInFace_
->
getSourceNode
();
}
virtual
const
NODE_PTR
&
GetTargetNode
()
const
{
return
m_nextEdgeInFace
->
GetSourceNode
();
}
void
setWeight
(
unsigned
int
weight
)
{
weight_
=
weight
;
}
void
SetWeight
(
unsigned
int
weight
)
{
m_weight
=
weight
;
}
unsigned
int
getWeight
()
const
{
return
weight_
;
}
unsigned
int
GetWeight
()
const
{
return
m_weight
;
}
void
c
lear
()
void
C
lear
()
{
{
sourceNode_
.
reset
();
m_sourceNode
.
reset
();
nextEdgeInFace_
.
reset
();
m_nextEdgeInFace
.
reset
();
if
(
!
twinEdge_
.
expired
()
)
if
(
!
m_twinEdge
.
expired
()
)
{
{
twinEdge_
.
lock
()
->
c
learTwinEdge
();
m_twinEdge
.
lock
()
->
C
learTwinEdge
();
twinEdge_
.
reset
();
m_twinEdge
.
reset
();
}
}
}
}
protected
:
protected
:
N
odePtr
sourceNode_
;
N
ODE_PTR
m_sourceNode
;
E
dgeWeakPtr
twinEdge_
;
E
DGE_WEAK_PTR
m_twinEdge
;
E
dgePtr
nextEdgeInFace_
;
E
DGE_PTR
m_nextEdgeInFace
;
unsigned
int
weight_
;
unsigned
int
m_weight
;
bool
isLeadingEdge_
;
bool
m_isLeadingEdge
;
};
// End of class Edge
};
/** \class EdgeMST
/**
* \brief \b Specialization of %Edge class to be used for Minimum Spanning Tree algorithm.
* \class EDGE_MST
* \brief \b Specialization of %EDGE class to be used for Minimum Spanning Tree algorithm.
*/
*/
class
EdgeMST
:
public
Edge
class
EDGE_MST
:
public
EDGE
{
{
private
:
private
:
N
odePtr
target_
;
N
ODE_PTR
m_target
;
public
:
public
:
EdgeMST
(
const
NodePtr
&
source
,
const
NodePtr
&
target
,
unsigned
int
weight
=
0
)
:
EDGE_MST
(
const
NODE_PTR
&
aSource
,
const
NODE_PTR
&
aTarget
,
unsigned
int
aWeight
=
0
)
:
target_
(
target
)
m_target
(
aTarget
)
{
sourceNode_
=
source
;
weight_
=
weight
;
}
{
m_sourceNode
=
aSource
;
m_weight
=
aWeight
;
}
E
dgeMST
(
const
Edge
&
edge
)
E
DGE_MST
(
const
EDGE
&
edge
)
{
{
sourceNode_
=
edge
.
g
etSourceNode
();
m_sourceNode
=
edge
.
G
etSourceNode
();
target_
=
edge
.
g
etTargetNode
();
m_target
=
edge
.
G
etTargetNode
();
weight_
=
edge
.
g
etWeight
();
m_weight
=
edge
.
G
etWeight
();
}
}
~
EdgeMST
()
{};
~
EDGE_MST
()
{
}
/// @copydoc Edge::setSourceNode()
/// @copydoc Edge::setSourceNode()
virtual
const
NodePtr
&
getTargetNode
()
const
{
return
target_
;
}
virtual
const
NODE_PTR
&
GetTargetNode
()
const
};
{
return
m_target
;
}
//------------------------------------------------------------------------------------------------
};
class
Dart
;
// Forward declaration (class in this namespace)
//------------------------------------------------------------------------------------------------
class
DART
;
// Forward declaration (class in this namespace)
// Triangulation class in the half-edge data structure
//------------------------------------------------------------------------------------------------
/** \class Triangulation
/**
* \class TRIANGULATION
* \brief \b %Triangulation class for the half-edge data structure with adaption to TTL.
* \brief \b %Triangulation class for the half-edge data structure with adaption to TTL.
*/
*/
class
TRIANGULATION
{
protected
:
/// One half-edge for each arc
std
::
list
<
EDGE_PTR
>
m_leadingEdges
;
class
Triangulation
{
ttl
::
TRIANGULATION_HELPER
*
m_helper
;
protected
:
std
::
list
<
EdgePtr
>
leadingEdges_
;
// one half-edge for each arc
ttl
::
TriangulationHelper
*
helper
;
void
addLeadingEdge
(
EdgePtr
&
edge
)
{
void
addLeadingEdge
(
EDGE_PTR
&
aEdge
)
edge
->
setAsLeadingEdge
();
{
leadingEdges_
.
push_front
(
edge
);
aEdge
->
SetAsLeadingEdge
();
m_leadingEdges
.
push_front
(
aEdge
);
}
}
bool
removeLeadingEdgeFromList
(
EdgePtr
&
leadingEdge
);
bool
removeLeadingEdgeFromList
(
EDGE_PTR
&
aLeadingEdge
);
void
cleanAll
();
void
cleanAll
();
...
@@ -275,7 +342,7 @@ public:
...
@@ -275,7 +342,7 @@ public:
* \image html swapEdge.gif
* \image html swapEdge.gif
* </center>
* </center>
*
*
* \param d
art
* \param aD
art
* Some of the functions require a dart as output.
* Some of the functions require a dart as output.
* If this is required by the actual function, the dart should be delivered
* If this is required by the actual function, the dart should be delivered
* back in a position as seen if it was glued to the edge when swapping (rotating)
* back in a position as seen if it was glued to the edge when swapping (rotating)
...
@@ -287,115 +354,118 @@ public:
...
@@ -287,115 +354,118 @@ public:
* - Some functions in TTL require that \c swapEdge is implemented such that
* - Some functions in TTL require that \c swapEdge is implemented such that
* darts outside the quadrilateral are not affected by the swap.
* darts outside the quadrilateral are not affected by the swap.
*/
*/
void
swapEdge
(
Dart
&
dart
);
void
swapEdge
(
DART
&
aDart
);
/** Splits the triangle associated with \e dart in the actual data structure into
/**
* Splits the triangle associated with \e dart in the actual data structure into
* three new triangles joining at \e point.
* three new triangles joining at \e point.
*
*
* <center>
* <center>
* \image html splitTriangle.gif
* \image html splitTriangle.gif
* </center>
* </center>
*
*
* \param d
art
* \param aD
art
* Output: A CCW dart incident with the new node; see the figure.
* Output: A CCW dart incident with the new node; see the figure.
*/
*/
void
splitTriangle
(
Dart
&
dart
,
const
NodePtr
&
point
);
void
splitTriangle
(
DART
&
aDart
,
const
NODE_PTR
&
aPoint
);
/** The reverse operation of TTLtraits::splitTriangle.
/**
* The reverse operation of TTLtraits::splitTriangle.
* This function is only required for functions that involve
* This function is only required for functions that involve
* removal of interior nodes; see for example TrinagulationHelper::r
emoveInteriorNode.
* removal of interior nodes; see for example TrinagulationHelper::R
emoveInteriorNode.
*
*
* <center>
* <center>
* \image html reverse_splitTriangle.gif
* \image html reverse_splitTriangle.gif
* </center>
* </center>
*/
*/
void
reverse
_splitTriangle
(
Dart
&
dart
);
void
reverse
SplitTriangle
(
DART
&
aDart
);
/** Removes a triangle with an edge at the boundary of the triangulation
/**
* Removes a triangle with an edge at the boundary of the triangulation
* in the actual data structure
* in the actual data structure
*/
*/
void
removeBoundaryTriangle
(
Dart
&
d
);
void
removeBoundaryTriangle
(
DART
&
aDart
);
public
:
public
:
/// Default constructor
/// Default constructor
T
riangulation
();
T
RIANGULATION
();
/// Copy constructor
/// Copy constructor
T
riangulation
(
const
Triangulation
&
tr
);
T
RIANGULATION
(
const
TRIANGULATION
&
aTriangulation
);
/// Destructor
/// Destructor
~
T
riangulation
();
~
T
RIANGULATION
();
/// Creates a Delaunay triangulation from a set of points
/// Creates a Delaunay triangulation from a set of points
void
createDelaunay
(
NodesContainer
::
iterator
first
,
void
CreateDelaunay
(
NODES_CONTAINER
::
iterator
aFirst
,
NODES_CONTAINER
::
iterator
aLast
);
NodesContainer
::
iterator
last
);
/// Creates an initial Delaunay triangulation from two enclosing triangles
/// Creates an initial Delaunay triangulation from two enclosing triangles
// When using rectangular boundary - loop through all points and expand.
// When using rectangular boundary - loop through all points and expand.
// (Called from createDelaunay(...) when starting)
// (Called from createDelaunay(...) when starting)
EdgePtr
initTwoEnclosingTriangles
(
NodesContainer
::
iterator
first
,
EDGE_PTR
InitTwoEnclosingTriangles
(
NODES_CONTAINER
::
iterator
aFirst
,
NodesContainer
::
iterator
last
);
NODES_CONTAINER
::
iterator
aLast
);
// These two functions are required by TTL for Delaunay triangulation
// These two functions are required by TTL for Delaunay triangulation
/// Swaps the edge associated with diagonal
/// Swaps the edge associated with diagonal
void
swapEdge
(
EdgePtr
&
diagonal
);
void
SwapEdge
(
EDGE_PTR
&
aDiagonal
);
/// Splits the triangle associated with edge into three new triangles joining at point
/// Splits the triangle associated with edge into three new triangles joining at point
EdgePtr
splitTriangle
(
EdgePtr
&
edge
,
const
NodePtr
&
point
);
EDGE_PTR
SplitTriangle
(
EDGE_PTR
&
aEdge
,
const
NODE_PTR
&
aPoint
);
// Functions required by TTL for removing nodes in a Delaunay triangulation
// Functions required by TTL for removing nodes in a Delaunay triangulation
/// Removes the boundary triangle associated with edge
/// Removes the boundary triangle associated with edge
void
removeTriangle
(
EdgePtr
&
edge
);
// boundary triangle required
void
RemoveTriangle
(
EDGE_PTR
&
aEdge
);
// boundary triangle required
/// The reverse operation of removeTriangle
/// The reverse operation of removeTriangle
void
reverse_splitTriangle
(
EdgePtr
&
edge
);
void
ReverseSplitTriangle
(
EDGE_PTR
&
aEdge
);
/// Creates an arbitrary CCW dart
/// Creates an arbitrary CCW dart
D
art
c
reateDart
();
D
ART
C
reateDart
();
/// Returns a list of "triangles" (one leading half-edge for each triangle)
/// Returns a list of "triangles" (one leading half-edge for each triangle)
const
std
::
list
<
EdgePtr
>&
getLeadingEdges
()
const
{
return
leadingEdges_
;
}
const
std
::
list
<
EDGE_PTR
>&
GetLeadingEdges
()
const
{
return
m_leadingEdges
;
}
/// Returns the number of triangles
/// Returns the number of triangles
int
noTriangles
()
const
{
return
(
int
)
leadingEdges_
.
size
();
}
int
NoTriangles
()
const
{
return
(
int
)
m_leadingEdges
.
size
();
}
/// Returns a list of half-edges (one half-edge for each arc)
/// Returns a list of half-edges (one half-edge for each arc)
std
::
list
<
E
dgePtr
>*
getEdges
(
bool
skip_boundary_edges
=
false
)
const
;
std
::
list
<
E
DGE_PTR
>*
GetEdges
(
bool
aSkipBoundaryEdges
=
false
)
const
;
#ifdef TTL_USE_NODE_FLAG
#ifdef TTL_USE_NODE_FLAG
/// Sets flag in all the nodes
/// Sets flag in all the nodes
void
flagNodes
(
bool
flag
)
const
;
void
FlagNodes
(
bool
aFlag
)
const
;
/// Returns a list of nodes. This function requires TTL_USE_NODE_FLAG to be defined. \see Node.
/// Returns a list of nodes. This function requires TTL_USE_NODE_FLAG to be defined. \see Node.
std
::
list
<
N
odePtr
>*
g
etNodes
()
const
;
std
::
list
<
N
ODE_PTR
>*
G
etNodes
()
const
;
#endif
#endif
/// Swaps edges until the triangulation is Delaunay (constrained edges are not swapped)
/// Swaps edges until the triangulation is Delaunay (constrained edges are not swapped)
void
o
ptimizeDelaunay
();
void
O
ptimizeDelaunay
();
/// Checks if the triangulation is Delaunay
/// Checks if the triangulation is Delaunay
bool
checkDelaunay
()
const
;
bool
CheckDelaunay
()
const
;
/// Returns an arbitrary interior node (as the source node of the returned edge)
/// Returns an arbitrary interior node (as the source node of the returned edge)
E
dgePtr
g
etInteriorNode
()
const
;
E
DGE_PTR
G
etInteriorNode
()
const
;
E
dgePtr
getBoundaryEdgeInTriangle
(
const
EdgePtr
&
e
)
const
;
E
DGE_PTR
GetBoundaryEdgeInTriangle
(
const
EDGE_PTR
&
aEdge
)
const
;
/// Returns an arbitrary boundary edge
/// Returns an arbitrary boundary edge
E
dgePtr
g
etBoundaryEdge
()
const
;
E
DGE_PTR
G
etBoundaryEdge
()
const
;
/// Print edges for plotting with, e.g., gnuplot
/// Print edges for plotting with, e.g., gnuplot
void
printEdges
(
std
::
ofstream
&
os
)
const
;
void
PrintEdges
(
std
::
ofstream
&
aOutput
)
const
;
friend
class
ttl
::
TriangulationHelper
;
};
// End of class Triangulation
friend
class
ttl
::
TRIANGULATION_HELPER
;
};
};
// End of hed namespace
};
// End of hed namespace
#endif
#endif
include/ttl/ttl.h
View file @
6fa2f060
...
@@ -40,19 +40,18 @@
...
@@ -40,19 +40,18 @@
#ifndef _TTL_H_
#ifndef _TTL_H_
#define _TTL_H_
#define _TTL_H_
#include <list>
#include <list>
#include <iterator>
#include <iterator>
// Debugging
// Debugging
#ifdef DEBUG_TTL
#ifdef DEBUG_TTL
static
void
errorAndExit
(
char
*
message
)
{
static
void
errorAndExit
(
char
*
aMessage
)
cout
<<
"
\n
!!! ERROR: "
<<
message
<<
" !!!
\n
"
<<
endl
;
{
cout
<<
"
\n
!!! ERROR: "
<<
aMessage
<<
" !!!
\n
"
<<
endl
;
exit
(
-
1
);
exit
(
-
1
);
}
}
#endif
#endif
// Next on TOPOLOGY:
// Next on TOPOLOGY:
// - get triangle strips
// - get triangle strips
// - weighted graph, algorithms using a weight (real) for each edge,
// - weighted graph, algorithms using a weight (real) for each edge,
...
@@ -63,8 +62,8 @@
...
@@ -63,8 +62,8 @@
// - analyze in detail locateFace: e.g. detect 0-orbit in case of infinite loop
// - analyze in detail locateFace: e.g. detect 0-orbit in case of infinite loop
// around a node etc.
// around a node etc.
/**
/*
* \brief Main interface to TTL
* \brief Main interface to TTL
*
*
* This namespace contains the basic generic algorithms for the TTL,
* This namespace contains the basic generic algorithms for the TTL,
* the Triangulation Template Library.\n
* the Triangulation Template Library.\n
...
@@ -77,21 +76,21 @@
...
@@ -77,21 +76,21 @@
* - Misc. queries for extracting information for visualisation systems etc.
* - Misc. queries for extracting information for visualisation systems etc.
*
*
* \par General requirements and assumptions:
* \par General requirements and assumptions:
*
- \e DartType and \e TraitsType
should be implemented in accordance with the description
*
- \e DART_TYPE and \e TRAITS_TYPE
should be implemented in accordance with the description
* in \ref api.
* in \ref api.
* - A \b "Requires:" section in the documentation of a function template
* - A \b "Requires:" section in the documentation of a function template
*
shows which functionality is required in \e TraitsType
to
*
shows which functionality is required in \e TRAITS_TYPE
to
* support that specific function.\n
* support that specific function.\n
*
Functionalty required in \e DartType
is the same (almost) for all
*
Functionalty required in \e DART_TYPE
is the same (almost) for all
* function templates; see \ref api and the example referred to.
* function templates; see \ref api and the example referred to.
* - When a reference to a \e dart object is passed to a function in TTL,
* - When a reference to a \e dart object is passed to a function in TTL,
* it is assumed that it is oriented \e counterclockwise (CCW) in a triangle
* it is assumed that it is oriented \e counterclockwise (CCW) in a triangle
* unless it is explicitly mentioned that it can also be \e clockwise (CW).
* unless it is explicitly mentioned that it can also be \e clockwise (CW).
* The same applies for a dart that is passed from a function in TTL to
* The same applies for a dart that is passed from a function in TTL to
*
the users TraitsType
class (or struct).
*
the users TRAITS_TYPE
class (or struct).
* - When an edge (represented with a dart) is swapped, it is assumed that darts
* - When an edge (represented with a dart) is swapped, it is assumed that darts
* outside the quadrilateral where the edge is a diagonal are not affected by
* outside the quadrilateral where the edge is a diagonal are not affected by
*
the swap. Thus, \ref hed::TTLtraits::swapEdge "TraitsType
::swapEdge"
*
the swap. Thus, \ref hed::TTLtraits::swapEdge "TRAITS_TYPE
::swapEdge"
* must be implemented in accordance with this rule.
* must be implemented in accordance with this rule.
*
*
* \par Glossary:
* \par Glossary:
...
@@ -111,152 +110,146 @@
...
@@ -111,152 +110,146 @@
*/
*/
namespace
ttl
{
namespace
ttl
{
class
T
riangulationHelper
class
T
RIANGULATION_HELPER
{
{
#ifndef DOXYGEN_SHOULD_SKIP_THIS
#ifndef DOXYGEN_SHOULD_SKIP_THIS
public
:
public
:
TriangulationHelper
(
hed
::
Triangulation
&
triang
)
:
triangulation
(
triang
)
TRIANGULATION_HELPER
(
hed
::
TRIANGULATION
&
aTriang
)
:
m_triangulation
(
aTriang
)
{
{
}
}
// Delaunay Triangulation
// Delaunay Triangulation
// ----------------------
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
,
class
POINT_TYPE
>
template
<
class
TraitsType
,
class
DartType
,
class
PointType
>
bool
InsertNode
(
DART_TYPE
&
aDart
,
POINT_TYPE
&
aPoint
);
bool
insertNode
(
DartType
&
dart
,
PointType
&
point
);
template
<
class
TraitsType
,
class
DartType
>
void
removeRectangularBoundary
(
DartType
&
dart
);
template
<
class
TraitsType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
>
void
removeNode
(
DartType
&
dart
);
void
RemoveRectangularBoundary
(
DART_TYPE
&
aDart
);
template
<
class
TraitsType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
>
void
removeBoundaryNode
(
DartType
&
dart
);
void
RemoveNode
(
DART_TYPE
&
aDart
);
template
<
class
TraitsType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
>
void
removeInteriorNode
(
DartType
&
dart
);
void
RemoveBoundaryNode
(
DART_TYPE
&
aDart
);
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
>
void
RemoveInteriorNode
(
DART_TYPE
&
aDart
);
// Topological and Geometric Queries
// Topological and Geometric Queries
// ---------------------------------
// ---------------------------------
template
<
class
TraitsType
,
class
PointType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
POINT_TYPE
,
class
DART_TYPE
>
static
bool
locateFaceSimplest
(
const
PointType
&
point
,
DartType
&
dart
);
static
bool
LocateFaceSimplest
(
const
POINT_TYPE
&
aPoint
,
DART_TYPE
&
aDart
);
template
<
class
TraitsType
,
class
PointType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
POINT_TYPE
,
class
DART_TYPE
>
static
bool
locateTriangle
(
const
PointType
&
point
,
DartType
&
dart
);
static
bool
LocateTriangle
(
const
POINT_TYPE
&
aPoint
,
DART_TYPE
&
aDart
);
template
<
class
TraitsType
,
class
PointType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
POINT_TYPE
,
class
DART_TYPE
>
static
bool
inTriangleSimplest
(
const
PointType
&
point
,
const
DartType
&
dart
);
static
bool
InTriangleSimplest
(
const
POINT_TYPE
&
aPoint
,
const
DART_TYPE
&
aDart
);
template
<
class
TraitsType
,
class
PointType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
POINT_TYPE
,
class
DART_TYPE
>
static
bool
inTriangle
(
const
PointType
&
point
,
const
DartType
&
dart
);
static
bool
InTriangle
(
const
POINT_TYPE
&
aPoint
,
const
DART_TYPE
&
aDart
);
template
<
class
DartType
,
class
DartListType
>
template
<
class
DART_TYPE
,
class
DART_LIST_TYPE
>
static
void
getBoundary
(
const
DartType
&
dart
,
DartListType
&
boundary
);
static
void
GetBoundary
(
const
DART_TYPE
&
aDart
,
DART_LIST_TYPE
&
aBoundary
);
template
<
class
DartType
>
template
<
class
DART_TYPE
>
static
bool
isBoundaryEdge
(
const
DartType
&
dart
);
static
bool
IsBoundaryEdge
(
const
DART_TYPE
&
aDart
);
template
<
class
DartType
>
template
<
class
DART_TYPE
>
static
bool
isBoundaryFace
(
const
DartType
&
dart
);
static
bool
IsBoundaryFace
(
const
DART_TYPE
&
aDart
);
template
<
class
DartType
>
template
<
class
DART_TYPE
>
static
bool
isBoundaryNode
(
const
DartType
&
dart
);
static
bool
IsBoundaryNode
(
const
DART_TYPE
&
aDart
);
template
<
class
DartType
>
template
<
class
DART_TYPE
>
static
int
getDegreeOfNode
(
const
DartType
&
dart
);
static
int
GetDegreeOfNode
(
const
DART_TYPE
&
aDart
);
template
<
class
DartType
,
class
DartListType
>
template
<
class
DART_TYPE
,
class
DART_LIST_TYPE
>
static
void
get_0_orbit_interior
(
const
DartType
&
dart
,
DartListType
&
orbit
);
static
void
Get0OrbitInterior
(
const
DART_TYPE
&
aDart
,
DART_LIST_TYPE
&
aOrbit
);
template
<
class
DartType
,
class
DartListType
>
template
<
class
DART_TYPE
,
class
DART_LIST_TYPE
>
static
void
get_0_orbit_boundary
(
const
DartType
&
dart
,
DartListType
&
orbit
);
static
void
Get0OrbitBoundary
(
const
DART_TYPE
&
aDart
,
DART_LIST_TYPE
&
aOrbit
);
template
<
class
DartType
>
template
<
class
DART_TYPE
>
static
bool
same_0_orbit
(
const
DartType
&
d1
,
const
DartType
&
d2
);
static
bool
Same0Orbit
(
const
DART_TYPE
&
aD1
,
const
DART_TYPE
&
aD2
);
template
<
class
DartType
>
template
<
class
DART_TYPE
>
static
bool
same_1_orbit
(
const
DartType
&
d1
,
const
DartType
&
d2
);
static
bool
Same1Orbit
(
const
DART_TYPE
&
aD1
,
const
DART_TYPE
&
aD2
);
template
<
class
DartType
>
template
<
class
DART_TYPE
>
static
bool
same_2_orbit
(
const
DartType
&
d1
,
const
DartType
&
d2
);
static
bool
Same2Orbit
(
const
DART_TYPE
&
aD1
,
const
DART_TYPE
&
aD2
);
template
<
class
TraitsType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
>
static
bool
swappableEdge
(
const
DartType
&
dart
,
bool
allowDegeneracy
=
false
);
static
bool
SwappableEdge
(
const
DART_TYPE
&
aDart
,
bool
aAllowDegeneracy
=
false
);
template
<
class
DartType
>
template
<
class
DART_TYPE
>
static
void
positionAtNextBoundaryEdge
(
DartType
&
dart
);
static
void
PositionAtNextBoundaryEdge
(
DART_TYPE
&
aDart
);
template
<
class
TraitsType
,
class
DartType
>
static
bool
convexBoundary
(
const
DartType
&
dart
);
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
>
static
bool
ConvexBoundary
(
const
DART_TYPE
&
aDart
);
// Utilities for Delaunay Triangulation
// Utilities for Delaunay Triangulation
// ------------------------------------
// ------------------------------------
template
<
class
TraitsType
,
class
DartType
,
class
DartListType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
,
class
DART_LIST_TYPE
>
void
optimizeDelaunay
(
DartListType
&
elist
);
void
OptimizeDelaunay
(
DART_LIST_TYPE
&
aElist
);
template
<
class
TraitsType
,
class
DartType
,
class
DartListType
>
void
optimizeDelaunay
(
DartListType
&
elist
,
const
typename
DartListType
::
iterator
end
);
template
<
class
TraitsType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
,
class
DART_LIST_TYPE
>
bool
swapTestDelaunay
(
const
DartType
&
dart
,
bool
cycling_check
=
false
)
const
;
void
OptimizeDelaunay
(
DART_LIST_TYPE
&
aElist
,
const
typename
DART_LIST_TYPE
::
iterator
aEnd
)
;
template
<
class
TraitsType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
>
void
recSwapDelaunay
(
DartType
&
diagonal
)
;
bool
SwapTestDelaunay
(
const
DART_TYPE
&
aDart
,
bool
aCyclingCheck
=
false
)
const
;
template
<
class
TraitsType
,
class
DartType
,
class
ListType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
>
void
swapEdgesAwayFromInteriorNode
(
DartType
&
dart
,
ListType
&
swapped_edges
);
void
RecSwapDelaunay
(
DART_TYPE
&
aDiagonal
);
template
<
class
TraitsType
,
class
DartType
,
class
ListType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
,
class
LIST_TYPE
>
void
swapEdgesAwayFromBoundaryNode
(
DartType
&
dart
,
ListType
&
swapped_edges
);
void
SwapEdgesAwayFromInteriorNode
(
DART_TYPE
&
aDart
,
LIST_TYPE
&
aSwappedEdges
);
template
<
class
TraitsType
,
class
DartType
,
class
DartListType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
,
class
LIST_TYPE
>
void
swapEdgeInList
(
const
typename
DartListType
::
iterator
&
it
,
DartListType
&
elist
);
void
SwapEdgesAwayFromBoundaryNode
(
DART_TYPE
&
aDart
,
LIST_TYPE
&
aSwappedEdges
);
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
,
class
DART_LIST_TYPE
>
void
SwapEdgeInList
(
const
typename
DART_LIST_TYPE
::
iterator
&
aIt
,
DART_LIST_TYPE
&
aElist
);
// Constrained Triangulation
// Constrained Triangulation
// -------------------------
// -------------------------
template
<
class
TraitsType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
>
static
D
artType
insertConstraint
(
DartType
&
dstart
,
DartType
&
dend
,
bool
optimize_delaunay
);
static
D
ART_TYPE
InsertConstraint
(
DART_TYPE
&
aDStart
,
DART_TYPE
&
aDEnd
,
bool
aOptimizeDelaunay
);
private
:
private
:
hed
::
Triangulation
&
triangulation
;
hed
::
TRIANGULATION
&
m_
triangulation
;
template
<
class
TraitsType
,
class
ForwardIterator
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
FORWARD_ITERATOR
,
class
DART_TYPE
>
void
insertNodes
(
ForwardIterator
first
,
ForwardIterator
last
,
DartType
&
dart
);
void
insertNodes
(
FORWARD_ITERATOR
aFirst
,
FORWARD_ITERATOR
aLast
,
DART_TYPE
&
aDart
);
template
<
class
TopologyElementType
,
class
DartType
>
template
<
class
TOPOLOGY_ELEMENT_TYPE
,
class
DART_TYPE
>
static
bool
isMemberOfFace
(
const
TopologyElementType
&
topologyElement
,
const
DartType
&
dart
);
static
bool
isMemberOfFace
(
const
TOPOLOGY_ELEMENT_TYPE
&
aTopologyElement
,
const
DART_TYPE
&
aDart
);
template
<
class
TraitsType
,
class
NodeType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
NODE_TYPE
,
class
DART_TYPE
>
static
bool
locateFaceWithNode
(
const
NodeType
&
node
,
DartType
&
dart_iter
);
static
bool
locateFaceWithNode
(
const
NODE_TYPE
&
aNode
,
DART_TYPE
&
aDartIter
);
template
<
class
DartType
>
template
<
class
DART_TYPE
>
static
void
getAdjacentTriangles
(
const
DartType
&
dart
,
DartType
&
t1
,
DartType
&
t2
,
DartType
&
t3
);
static
void
getAdjacentTriangles
(
const
DART_TYPE
&
aDart
,
DART_TYPE
&
aT1
,
DART_TYPE
&
aT2
,
DART_TYPE
&
aT3
);
template
<
class
DartType
>
template
<
class
DART_TYPE
>
static
void
getNeighborNodes
(
const
DartType
&
dart
,
std
::
list
<
DartType
>&
node_list
,
bool
&
boundary
);
static
void
getNeighborNodes
(
const
DART_TYPE
&
aDart
,
std
::
list
<
DART_TYPE
>&
aNodeList
,
bool
&
aBoundary
);
template
<
class
TraitsType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
>
static
bool
degenerateTriangle
(
const
DartType
&
dart
);
static
bool
degenerateTriangle
(
const
DART_TYPE
&
aDart
);
};
};
#endif // DOXYGEN_SHOULD_SKIP_THIS
#endif // DOXYGEN_SHOULD_SKIP_THIS
//------------------------------------------------------------------------------------------------
// ------------------------------- Delaunay Triangulation Group ---------------------------------
//------------------------------------------------------------------------------------------------
/** @name Delaunay Triangulation */
/** @name Delaunay Triangulation */
//@{
//@{
/**
//------------------------------------------------------------------------------------------------
* Inserts a new node in an existing Delaunay triangulation and
/** Inserts a new node in an existing Delaunay triangulation and
* swaps edges to obtain a new Delaunay triangulation.
* swaps edges to obtain a new Delaunay triangulation.
* This is the basic function for incremental Delaunay triangulation.
* This is the basic function for incremental Delaunay triangulation.
* When starting from a set of points, an initial Delaunay triangulation
* When starting from a set of points, an initial Delaunay triangulation
...
@@ -270,11 +263,11 @@ private:
...
@@ -270,11 +263,11 @@ private:
* Note that this incremetal scheme will run much faster if the points
* Note that this incremetal scheme will run much faster if the points
* have been sorted lexicographically on \e x and \e y.
* have been sorted lexicographically on \e x and \e y.
*
*
* \param dart
* \param aDart
* An arbitrary CCW dart in the tringulation.\n
* An arbitrary CCW dart in the tringulation.\n
* Output: A CCW dart incident to the new node.
* Output: A CCW dart incident to the new node.
*
*
* \param point
* \param aPoint
* A point (node) to be inserted in the triangulation.
* A point (node) to be inserted in the triangulation.
*
*
* \retval bool
* \retval bool
...
@@ -283,11 +276,11 @@ private:
...
@@ -283,11 +276,11 @@ private:
* \c false is returned.
* \c false is returned.
*
*
* \require
* \require
* - \ref hed::TTLtraits::splitTriangle "TraitsType::splitTriangle" (DartType&, const PointType
&)
* - \ref hed::TTLtraits::splitTriangle "TRAITS_TYPE::splitTriangle" (DART_TYPE&, const POINT_TYPE
&)
*
*
* \using
* \using
* - locateTriangle
* - locateTriangle
* - r
ecSwapDelaunay
* - R
ecSwapDelaunay
*
*
* \note
* \note
* - For efficiency reasons \e dart should be close to the insertion \e point.
* - For efficiency reasons \e dart should be close to the insertion \e point.
...
@@ -295,11 +288,13 @@ private:
...
@@ -295,11 +288,13 @@ private:
* \see
* \see
* removeRectangularBoundary
* removeRectangularBoundary
*/
*/
template
<
class
TraitsType
,
class
DartType
,
class
PointType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
,
class
POINT_TYPE
>
bool
TriangulationHelper
::
insertNode
(
DartType
&
dart
,
PointType
&
point
)
{
bool
TRIANGULATION_HELPER
::
InsertNode
(
DART_TYPE
&
aDart
,
POINT_TYPE
&
aPoint
)
{
bool
found
=
LocateTriangle
<
TRAITS_TYPE
>
(
aPoint
,
aDart
);
bool
found
=
locateTriangle
<
TraitsType
>
(
point
,
dart
);
if
(
!
found
)
if
(
!
found
)
{
{
#ifdef DEBUG_TTL
#ifdef DEBUG_TTL
cout
<<
"ERROR: Triangulation::insertNode: NO triangle found. /n"
;
cout
<<
"ERROR: Triangulation::insertNode: NO triangle found. /n"
;
#endif
#endif
...
@@ -307,63 +302,67 @@ private:
...
@@ -307,63 +302,67 @@ private:
}
}
// ??? can we hide the dart? this is not possible if one triangle only
// ??? can we hide the dart? this is not possible if one triangle only
triangulation
.
splitTriangle
(
dart
,
point
);
m_triangulation
.
splitTriangle
(
aDart
,
aPoint
);
D
artType
d1
=
d
art
;
D
ART_TYPE
d1
=
aD
art
;
d1
.
alpha2
().
alpha1
().
alpha2
().
alpha0
().
a
lpha1
();
d1
.
Alpha2
().
Alpha1
().
Alpha2
().
Alpha0
().
A
lpha1
();
D
artType
d2
=
d
art
;
D
ART_TYPE
d2
=
aD
art
;
d2
.
alpha1
().
alpha0
().
a
lpha1
();
d2
.
Alpha1
().
Alpha0
().
A
lpha1
();
// Preserve a dart as output incident to the node and CCW
// Preserve a dart as output incident to the node and CCW
DartType
d3
=
dart
;
DART_TYPE
d3
=
aDart
;
d3
.
alpha2
();
d3
.
Alpha2
();
dart
=
d3
;
// and see below
aDart
=
d3
;
// and see below
//DartType dsav = d3;
//DART_TYPE dsav = d3;
d3
.
alpha0
().
alpha1
();
d3
.
Alpha0
().
Alpha1
();
//if (!TraitsType::fixedEdge(d1) && !isBoundaryEdge(d1)) {
//if (!TRAITS_TYPE::fixedEdge(d1) && !IsBoundaryEdge(d1)) {
if
(
!
isBoundaryEdge
(
d1
))
{
if
(
!
IsBoundaryEdge
(
d1
)
)
d1
.
alpha2
();
{
recSwapDelaunay
<
TraitsType
>
(
d1
);
d1
.
Alpha2
();
RecSwapDelaunay
<
TRAITS_TYPE
>
(
d1
);
}
}
//if (!TraitsType::fixedEdge(d2) && !isBoundaryEdge(d2)) {
//if (!TRAITS_TYPE::fixedEdge(d2) && !IsBoundaryEdge(d2)) {
if
(
!
isBoundaryEdge
(
d2
))
{
if
(
!
IsBoundaryEdge
(
d2
)
)
d2
.
alpha2
();
{
recSwapDelaunay
<
TraitsType
>
(
d2
);
d2
.
Alpha2
();
RecSwapDelaunay
<
TRAITS_TYPE
>
(
d2
);
}
}
// Preserve the incoming dart as output incident to the node and CCW
// Preserve the incoming dart as output incident to the node and CCW
//d = dsav.alpha2();
//d = dsav.Alpha2();
dart
.
alpha2
();
aDart
.
Alpha2
();
//if (!TraitsType::fixedEdge(d3) && !isBoundaryEdge(d3)) {
//if (!TRAITS_TYPE::fixedEdge(d3) && !IsBoundaryEdge(d3)) {
if
(
!
isBoundaryEdge
(
d3
))
{
if
(
!
IsBoundaryEdge
(
d3
)
)
d3
.
alpha2
();
{
recSwapDelaunay
<
TraitsType
>
(
d3
);
d3
.
Alpha2
();
RecSwapDelaunay
<
TRAITS_TYPE
>
(
d3
);
}
}
return
true
;
return
true
;
}
}
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
// Private/Hidden function (might change later)
// Private/Hidden function (might change later)
template
<
class
TRAITS_TYPE
,
class
FORWARD_ITERATOR
,
class
DART_TYPE
>
template
<
class
TraitsType
,
class
ForwardIterator
,
class
DartType
>
void
TRIANGULATION_HELPER
::
insertNodes
(
FORWARD_ITERATOR
aFirst
,
FORWARD_ITERATOR
aLast
,
void
TriangulationHelper
::
insertNodes
(
ForwardIterator
first
,
ForwardIterator
last
,
DartType
&
dart
)
{
DART_TYPE
&
aDart
)
{
// Assumes that the dereferenced point objects are pointers.
// Assumes that the dereferenced point objects are pointers.
// References to the point objects are then passed to TTL.
// References to the point objects are then passed to TTL.
F
orwardIterator
it
;
F
ORWARD_ITERATOR
it
;
for
(
it
=
first
;
it
!=
last
;
++
it
)
{
for
(
it
=
aFirst
;
it
!=
aLast
;
++
it
)
insertNode
<
TraitsType
>
(
dart
,
**
it
);
{
}
InsertNode
<
TRAITS_TYPE
>
(
aDart
,
**
it
);
}
}
}
//------------------------------------------------------------------------------------------------
/** Removes the rectangular boundary of a triangulation as a final step of an
/** Removes the rectangular boundary of a triangulation as a final step of an
* incremental Delaunay triangulation.
* incremental Delaunay triangulation.
* The four nodes at the corners will be removed and the resulting triangulation
* The four nodes at the corners will be removed and the resulting triangulation
* will have a convex boundary and be Delaunay.
* will have a convex boundary and be Delaunay.
...
@@ -373,129 +372,129 @@ private:
...
@@ -373,129 +372,129 @@ private:
* Output: A CCW dart at the new boundary
* Output: A CCW dart at the new boundary
*
*
* \using
* \using
* - r
emoveBoundaryNode
* - R
emoveBoundaryNode
*
*
* \note
* \note
* - This function requires that the boundary of the
triangulation is
* - This function requires that the boundary of the m_
triangulation is
* a rectangle with four nodes (one in each corner).
* a rectangle with four nodes (one in each corner).
*/
*/
template
<
class
TraitsType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
>
void
TriangulationHelper
::
removeRectangularBoundary
(
DartType
&
dart
)
{
void
TRIANGULATION_HELPER
::
RemoveRectangularBoundary
(
DART_TYPE
&
aDart
)
{
D
artType
d_next
=
d
art
;
D
ART_TYPE
d_next
=
aD
art
;
D
artType
d_iter
;
D
ART_TYPE
d_iter
;
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
d_iter
=
d_next
;
d_iter
=
d_next
;
d_next
.
a
lpha0
();
d_next
.
A
lpha0
();
positionAtNextBoundaryEdge
(
d_next
);
PositionAtNextBoundaryEdge
(
d_next
);
removeBoundaryNode
<
TraitsType
>
(
d_iter
);
RemoveBoundaryNode
<
TRAITS_TYPE
>
(
d_iter
);
}
}
d
art
=
d_next
;
// Return a dart at the new boundary
aD
art
=
d_next
;
// Return a dart at the new boundary
}
}
/** Removes the node associated with \e dart and
//------------------------------------------------------------------------------------------------
/** Removes the node associated with \e dart and
* updates the triangulation to be Delaunay.
* updates the triangulation to be Delaunay.
*
*
* \using
* \using
* - r
emoveBoundaryNode if \e dart represents a node at the boundary
* - R
emoveBoundaryNode if \e dart represents a node at the boundary
* - r
emoveInteriorNode if \e dart represents an interior node
* - R
emoveInteriorNode if \e dart represents an interior node
*
*
* \note
* \note
* - The node cannot belong to a fixed (constrained) edge that is not
* - The node cannot belong to a fixed (constrained) edge that is not
* swappable. (An endless loop is likely to occur in this case).
* swappable. (An endless loop is likely to occur in this case).
*/
*/
template
<
class
TraitsType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
>
void
TriangulationHelper
::
removeNode
(
DartType
&
dart
)
{
void
TRIANGULATION_HELPER
::
RemoveNode
(
DART_TYPE
&
aDart
)
{
if
(
isBoundaryNode
(
dart
)
)
if
(
isBoundaryNode
(
aDart
)
)
removeBoundaryNode
<
TraitsType
>
(
dart
);
RemoveBoundaryNode
<
TRAITS_TYPE
>
(
aDart
);
else
else
removeInteriorNode
<
TraitsType
>
(
dart
);
RemoveInteriorNode
<
TRAITS_TYPE
>
(
aDart
);
}
}
/** Removes the boundary node associated with \e dart and
//------------------------------------------------------------------------------------------------
/** Removes the boundary node associated with \e dart and
* updates the triangulation to be Delaunay.
* updates the triangulation to be Delaunay.
*
*
* \using
* \using
* - s
wapEdgesAwayFromBoundaryNode
* - S
wapEdgesAwayFromBoundaryNode
* - o
ptimizeDelaunay
* - O
ptimizeDelaunay
*
*
* \require
* \require
* - \ref hed::TTLtraits::removeBoundaryTriangle "TraitsType
::removeBoundaryTriangle" (Dart&)
* - \ref hed::TTLtraits::removeBoundaryTriangle "TRAITS_TYPE
::removeBoundaryTriangle" (Dart&)
*/
*/
template
<
class
TraitsType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
>
void
TriangulationHelper
::
removeBoundaryNode
(
DartType
&
dart
)
{
void
TRIANGULATION_HELPER
::
RemoveBoundaryNode
(
DART_TYPE
&
aDart
)
{
// ... and update Delaunay
// ... and update Delaunay
// - CCW dart must be given (for remove)
// - CCW dart must be given (for remove)
// - No dart is delivered back now (but this is possible if
// - No dart is delivered back now (but this is possible if
// we assume that there is not only one triangle left in the triangulation.
// we assume that there is not only one triangle left in the
m_
triangulation.
// Position at boundary edge and CCW
// Position at boundary edge and CCW
if
(
!
isBoundaryEdge
(
dart
))
{
if
(
!
IsBoundaryEdge
(
aDart
)
)
dart
.
alpha1
();
// ensures that next function delivers back a CCW dart (if the given dart is CCW)
{
positionAtNextBoundaryEdge
(
dart
);
aDart
.
Alpha1
();
// ensures that next function delivers back a CCW dart (if the given dart is CCW)
PositionAtNextBoundaryEdge
(
aDart
);
}
}
std
::
list
<
D
artType
>
swapped_edges
;
std
::
list
<
D
ART_TYPE
>
swapped_edges
;
swapEdgesAwayFromBoundaryNode
<
TraitsType
>
(
dart
,
swapped_edges
);
SwapEdgesAwayFromBoundaryNode
<
TRAITS_TYPE
>
(
aDart
,
swapped_edges
);
// Remove boundary triangles and remove the new boundary from the list
// Remove boundary triangles and remove the new boundary from the list
// of swapped edges, see below.
// of swapped edges, see below.
D
artType
d_iter
=
d
art
;
D
ART_TYPE
d_iter
=
aD
art
;
D
artType
dnext
=
d
art
;
D
ART_TYPE
dnext
=
aD
art
;
bool
bend
=
false
;
bool
bend
=
false
;
while
(
bend
==
false
)
{
while
(
bend
==
false
)
dnext
.
alpha1
().
alpha2
();
{
if
(
isBoundaryEdge
(
dnext
))
dnext
.
Alpha1
().
Alpha2
();
if
(
IsBoundaryEdge
(
dnext
)
)
bend
=
true
;
// Stop when boundary
bend
=
true
;
// Stop when boundary
// Generic: Also remove the new boundary from the list of swapped edges
// Generic: Also remove the new boundary from the list of swapped edges
DartType
n_bedge
=
d_iter
;
DART_TYPE
n_bedge
=
d_iter
;
n_bedge
.
alpha1
().
alpha0
().
alpha1
().
a
lpha2
();
// new boundary edge
n_bedge
.
Alpha1
().
Alpha0
().
Alpha1
().
A
lpha2
();
// new boundary edge
// ??? can we avoid find if we do this in swap away?
// ??? can we avoid find if we do this in swap away?
typename
std
::
list
<
DartType
>::
iterator
it
;
typename
std
::
list
<
DART_TYPE
>::
iterator
it
;
it
=
find
(
swapped_edges
.
begin
(),
swapped_edges
.
end
(),
n_bedge
);
it
=
find
(
swapped_edges
.
begin
(),
swapped_edges
.
end
(),
n_bedge
);
if
(
it
!=
swapped_edges
.
end
()
)
if
(
it
!=
swapped_edges
.
end
()
)
swapped_edges
.
erase
(
it
);
swapped_edges
.
erase
(
it
);
// Remove the boundary triangle
// Remove the boundary triangle
triangulation
.
removeBoundaryTriangle
(
d_iter
);
m_triangulation
.
removeBoundaryTriangle
(
d_iter
);
d_iter
=
dnext
;
d_iter
=
dnext
;
}
}
// Optimize Delaunay
// Optimize Delaunay
typedef
std
::
list
<
D
artType
>
DartListType
;
typedef
std
::
list
<
D
ART_TYPE
>
DART_LIST_TYPE
;
optimizeDelaunay
<
TraitsType
,
DartType
,
DartListType
>
(
swapped_edges
);
OptimizeDelaunay
<
TRAITS_TYPE
,
DART_TYPE
,
DART_LIST_TYPE
>
(
swapped_edges
);
}
}
//------------------------------------------------------------------------------------------------
/** Removes the interior node associated with \e dart and
/** Removes the interior node associated with \e dart and
* updates the triangulation to be Delaunay.
* updates the triangulation to be Delaunay.
*
*
* \using
* \using
* - s
wapEdgesAwayFromInteriorNode
* - S
wapEdgesAwayFromInteriorNode
* - o
ptimizeDelaunay
* - O
ptimizeDelaunay
*
*
* \require
* \require
* - \ref hed::TTLtraits::reverse_splitTriangle "TraitsType
::reverse_splitTriangle" (Dart&)
* - \ref hed::TTLtraits::reverse_splitTriangle "TRAITS_TYPE
::reverse_splitTriangle" (Dart&)
*
*
* \note
* \note
* - The node cannot belong to a fixed (constrained) edge that is not
* - The node cannot belong to a fixed (constrained) edge that is not
* swappable. (An endless loop is likely to occur in this case).
* swappable. (An endless loop is likely to occur in this case).
*/
*/
template
<
class
TraitsType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
>
void
TriangulationHelper
::
removeInteriorNode
(
DartType
&
dart
)
{
void
TRIANGULATION_HELPER
::
RemoveInteriorNode
(
DART_TYPE
&
aDart
)
{
// ... and update to Delaunay.
// ... and update to Delaunay.
// Must allow degeneracy temporarily, see comments in swap edges away
// Must allow degeneracy temporarily, see comments in swap edges away
// Assumes:
// Assumes:
...
@@ -505,18 +504,18 @@ private:
...
@@ -505,18 +504,18 @@ private:
// 1) Swaps edges away from the node until degree=3 (generic)
// 1) Swaps edges away from the node until degree=3 (generic)
// 2) Removes the remaining 3 triangles and creates a new to fill the hole
// 2) Removes the remaining 3 triangles and creates a new to fill the hole
// unsplitTriangle which is required
// unsplitTriangle which is required
// 3) Runs LOP on the platelet to obtain a Delaunay triangulation
// 3) Runs LOP on the platelet to obtain a Delaunay
m_
triangulation
// (No dart is delivered as output)
// (No dart is delivered as output)
// Assumes dart is counterclockwise
// Assumes dart is counterclockwise
std
::
list
<
D
artType
>
swapped_edges
;
std
::
list
<
D
ART_TYPE
>
swapped_edges
;
swapEdgesAwayFromInteriorNode
<
TraitsType
>
(
dart
,
swapped_edges
);
SwapEdgesAwayFromInteriorNode
<
TRAITS_TYPE
>
(
aDart
,
swapped_edges
);
// The reverse operation of split triangle:
// The reverse operation of split triangle:
// Make one triangle of the three triangles at the node associated with dart
// Make one triangle of the three triangles at the node associated with dart
// T
raitsType
::
// T
RAITS_TYPE
::
triangulation
.
reverse_splitTriangle
(
dart
);
m_triangulation
.
reverseSplitTriangle
(
aDart
);
// ???? Not generic yet if we are very strict:
// ???? Not generic yet if we are very strict:
// When calling unsplit triangle, darts at the three opposite sides may
// When calling unsplit triangle, darts at the three opposite sides may
...
@@ -529,75 +528,72 @@ private:
...
@@ -529,75 +528,72 @@ private:
// Note the theoretical result: if there are no edges in the list,
// Note the theoretical result: if there are no edges in the list,
// the triangulation is Delaunay already
// the triangulation is Delaunay already
optimizeDelaunay
<
TraitsType
,
DartType
>
(
swapped_edges
);
OptimizeDelaunay
<
TRAITS_TYPE
,
DART_TYPE
>
(
swapped_edges
);
}
}
//@} // End of Delaunay Triangulation Group
//------------------------------------------------------------------------------------------------
//@} // End of Delaunay Triangulation Group
// -------------------------- Topological and Geometric Queries Group ---------------------------
//------------------------------------------------------------------------------------------------
/** @name Topological and Geometric Queries */
//@{
//------------------------------------------------------------------------------------------------
// Private/Hidden function (might change later)
template
<
class
TopologyElementType
,
class
DartType
>
bool
TriangulationHelper
::
isMemberOfFace
(
const
TopologyElementType
&
topologyElement
,
const
DartType
&
dart
)
{
/** @name Topological and Geometric Queries */
//@{
//------------------------------------------------------------------------------------------------
// Private/Hidden function (might change later)
template
<
class
TOPOLOGY_ELEMENT_TYPE
,
class
DART_TYPE
>
bool
TRIANGULATION_HELPER
::
isMemberOfFace
(
const
TOPOLOGY_ELEMENT_TYPE
&
aTopologyElement
,
const
DART_TYPE
&
aDart
)
{
// Check if the given topology element (node, edge or face) is a member of the face
// Check if the given topology element (node, edge or face) is a member of the face
// Assumes:
// Assumes:
// - D
artType::isMember(TopologyElementType
)
// - D
ART_TYPE::isMember(TOPOLOGY_ELEMENT_TYPE
)
DartType
dart_iter
=
dart
;
DART_TYPE
dart_iter
=
aDart
;
do
{
if
(
dart_iter
.
isMember
(
topologyElement
))
return
true
;
dart_iter
.
alpha0
().
alpha1
();
}
while
(
dart_iter
!=
dart
);
return
false
;
do
{
if
(
dart_iter
.
isMember
(
aTopologyElement
)
)
return
true
;
dart_iter
.
Alpha0
().
Alpha1
();
}
}
while
(
dart_iter
!=
aDart
);
return
false
;
}
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
// Private/Hidden function (might change later)
// Private/Hidden function (might change later)
template
<
class
TraitsType
,
class
NodeType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
NODE_TYPE
,
class
DART_TYPE
>
bool
TriangulationHelper
::
locateFaceWithNode
(
const
NodeType
&
node
,
DartType
&
dart_iter
)
{
bool
TRIANGULATION_HELPER
::
locateFaceWithNode
(
const
NODE_TYPE
&
aNode
,
DART_TYPE
&
aDartIter
)
{
// Locate a face in the topology structure with the given node as a member
// Locate a face in the topology structure with the given node as a member
// Assumes:
// Assumes:
// - T
raitsType::orient2d(DartType, DartType, NodeType
)
// - T
RAITS_TYPE::Orient2D(DART_TYPE, DART_TYPE, NODE_TYPE
)
// - D
artType::isMember(NodeType
)
// - D
ART_TYPE::isMember(NODE_TYPE
)
// - Note that if false is returned, the node might still be in the
// - Note that if false is returned, the node might still be in the
// topology structure. Application programmer
// topology structure. Application programmer
// should check all if by hypothesis the node is in the topology structure;
// should check all if by hypothesis the node is in the topology structure;
// see doc. on
locateTriangle.
// see doc. on
LocateTriangle.
bool
status
=
locateFaceSimplest
<
TraitsType
>
(
node
,
dart_iter
);
bool
status
=
LocateFaceSimplest
<
TRAITS_TYPE
>
(
aNode
,
aDartIter
);
if
(
status
==
false
)
if
(
status
==
false
)
return
status
;
return
status
;
// True was returned from
l
ocateFaceSimplest, but if the located triangle is
// True was returned from
L
ocateFaceSimplest, but if the located triangle is
// degenerate and the node is on the extension of the edges,
// degenerate and the node is on the extension of the edges,
// the node might still be inside. Check if node is a member and return false
// the node might still be inside. Check if node is a member and return false
// if not. (Still the node might be in the topology structure, see doc. above
// if not. (Still the node might be in the topology structure, see doc. above
// and in locateTriangle(const PointType& point, DartType& dart_iter)
// and in locateTriangle(const POINT_TYPE& point, DART_TYPE& dart_iter)
return
isMemberOfFace
(
node
,
dart_iter
);
}
return
isMemberOfFace
(
aNode
,
aDartIter
);
}
//------------------------------------------------------------------------------------------------
/** Locates the face containing a given point.
/** Locates the face containing a given point.
* It is assumed that the tessellation (e.g. a triangulation) is \e regular in the sense that
* It is assumed that the tessellation (e.g. a triangulation) is \e regular in the sense that
* there are no holes, the boundary is convex and there are no degenerate faces.
* there are no holes, the boundary is convex and there are no degenerate faces.
*
*
* \param point
* \param aPoint
* A point to be located
* A point to be located
*
*
* \param d
art
* \param aD
art
* An arbitrary CCW dart in the triangulation\n
* An arbitrary CCW dart in the triangulation\n
* Output: A CCW dart in the located face
* Output: A CCW dart in the located face
*
*
...
@@ -605,17 +601,18 @@ private:
...
@@ -605,17 +601,18 @@ private:
* \c true if a face is found; \c false if not.
* \c true if a face is found; \c false if not.
*
*
* \require
* \require
* - \ref hed::TTLtraits::orient2d "TraitsType::orient2d" (DartType&, DartType&, PointType
&)
* - \ref hed::TTLtraits::Orient2D "TRAITS_TYPE::Orient2D" (DART_TYPE&, DART_TYPE&, POINT_TYPE
&)
*
*
* \note
* \note
* - If \c false is returned, \e point may still be inside a face if the tessellation is not
* - If \c false is returned, \e point may still be inside a face if the tessellation is not
* \e regular as explained above.
* \e regular as explained above.
*
*
* \see
* \see
* l
ocateTriangle
* L
ocateTriangle
*/
*/
template
<
class
TraitsType
,
class
PointType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
POINT_TYPE
,
class
DART_TYPE
>
bool
TriangulationHelper
::
locateFaceSimplest
(
const
PointType
&
point
,
DartType
&
dart
)
{
bool
TRIANGULATION_HELPER
::
LocateFaceSimplest
(
const
POINT_TYPE
&
aPoint
,
DART_TYPE
&
aDart
)
{
// Not degenerate triangles if point is on the extension of the edges
// Not degenerate triangles if point is on the extension of the edges
// But inTriangle may be called in case of true (may update to inFace2)
// But inTriangle may be called in case of true (may update to inFace2)
// Convex boundary
// Convex boundary
...
@@ -623,43 +620,47 @@ private:
...
@@ -623,43 +620,47 @@ private:
// convex faces (works for general convex faces)
// convex faces (works for general convex faces)
// Not specialized for triangles, but ok?
// Not specialized for triangles, but ok?
//
//
// T
raitsType::orint2d(PointType
) is the half open half-plane defined
// T
RAITS_TYPE::orint2d(POINT_TYPE
) is the half open half-plane defined
// by the dart:
// by the dart:
// n1 = dart.node()
// n1 = dart.node()
// n2 = dart.
a
lpha0().node
// n2 = dart.
A
lpha0().node
// Only the following gives true:
// Only the following gives true:
// ((n2->x()-n1->x())*(point.y()-n1->y()) >= (point.x()-n1->x())*(n2->y()-n1->y()))
// ((n2->x()-n1->x())*(point.y()-n1->y()) >= (point.x()-n1->x())*(n2->y()-n1->y()))
DartType
dart_start
;
DART_TYPE
dart_start
;
dart_start
=
dart
;
dart_start
=
aDart
;
DartType
dart_prev
;
DART_TYPE
dart_prev
;
DartType
d0
;
DART_TYPE
d0
;
for
(;;)
{
for
(
;;
)
d0
=
dart
;
{
d0
.
alpha0
();
d0
=
aDart
;
if
(
TraitsType
::
orient2d
(
dart
,
d0
,
point
)
>=
0
)
{
d0
.
Alpha0
();
dart
.
alpha0
().
alpha1
();
if
(
dart
==
dart_start
)
if
(
TRAITS_TYPE
::
Orient2D
(
aDart
,
d0
,
aPoint
)
>=
0
)
{
aDart
.
Alpha0
().
Alpha1
();
if
(
aDart
==
dart_start
)
return
true
;
// left to all edges in face
return
true
;
// left to all edges in face
}
}
else
{
else
dart_prev
=
dart
;
{
dart
.
alpha2
();
dart_prev
=
aDart
;
if
(
dart
==
dart_prev
)
aDart
.
Alpha2
();
if
(
aDart
==
dart_prev
)
return
false
;
// iteration to outside boundary
return
false
;
// iteration to outside boundary
dart_start
=
d
art
;
dart_start
=
aD
art
;
dart_start
.
a
lpha0
();
dart_start
.
A
lpha0
();
dart
.
alpha1
();
// avoid twice on same edge and ccw in next
aDart
.
Alpha1
();
// avoid twice on same edge and ccw in next
}
}
}
}
}
}
//------------------------------------------------------------------------------------------------
/** Locates the triangle containing a given point.
/** Locates the triangle containing a given point.
* It is assumed that the triangulation is \e regular in the sense that there
* It is assumed that the triangulation is \e regular in the sense that there
* are no holes and the boundary is convex.
* are no holes and the boundary is convex.
* This function deals with degeneracy to some extent, but round-off errors may still
* This function deals with degeneracy to some extent, but round-off errors may still
...
@@ -674,15 +675,16 @@ private:
...
@@ -674,15 +675,16 @@ private:
*
*
* \retval bool
* \retval bool
* \c true if a triangle is found; \c false if not.\n
* \c true if a triangle is found; \c false if not.\n
* If \e point is outside the
triangulation, in which case \c false is returned,
* If \e point is outside the m_
triangulation, in which case \c false is returned,
* then the edge associated with \e dart will be at the boundary of the
triangulation.
* then the edge associated with \e dart will be at the boundary of the m_
triangulation.
*
*
* \using
* \using
* - l
ocateFaceSimplest
* - L
ocateFaceSimplest
* - i
nTriangle
* - I
nTriangle
*/
*/
template
<
class
TraitsType
,
class
PointType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
POINT_TYPE
,
class
DART_TYPE
>
bool
TriangulationHelper
::
locateTriangle
(
const
PointType
&
point
,
DartType
&
dart
)
{
bool
TRIANGULATION_HELPER
::
LocateTriangle
(
const
POINT_TYPE
&
aPoint
,
DART_TYPE
&
aDart
)
{
// The purpose is to have a fast and stable procedure that
// The purpose is to have a fast and stable procedure that
// i) avoids concluding that a point is inside a triangle if it is not inside
// i) avoids concluding that a point is inside a triangle if it is not inside
// ii) avoids infinite loops
// ii) avoids infinite loops
...
@@ -690,7 +692,7 @@ private:
...
@@ -690,7 +692,7 @@ private:
// Thus, if false is returned, the point might still be inside a triangle in
// Thus, if false is returned, the point might still be inside a triangle in
// the triangulation. But this will probably only occur in the following cases:
// the triangulation. But this will probably only occur in the following cases:
// i) There are holes in the triangulation which causes the procedure to stop.
// i) There are holes in the triangulation which causes the procedure to stop.
// ii) The boundary of the triangulation is not convex.
// ii) The boundary of the
m_
triangulation is not convex.
// ii) There might be degenerate triangles interior to the triangulation, or on the
// ii) There might be degenerate triangles interior to the triangulation, or on the
// the boundary, which in some cases might cause the procedure to stop there due
// the boundary, which in some cases might cause the procedure to stop there due
// to the logic of the algorithm.
// to the logic of the algorithm.
...
@@ -700,14 +702,14 @@ private:
...
@@ -700,14 +702,14 @@ private:
// in the triangulation and and false is returned, then all triangles in the
// in the triangulation and and false is returned, then all triangles in the
// triangulation should be checked by the application. This can be done using
// triangulation should be checked by the application. This can be done using
// the function:
// the function:
// bool inTriangle(const PointType& point, const DartType& dart).
// bool inTriangle(const POINT_TYPE& point, const DART_TYPE& dart).
// Assumes:
// Assumes:
// - crossProduct2d, scalarProduct2d etc., see functions called
// - CrossProduct2D, ScalarProduct2D etc., see functions called
bool
status
=
LocateFaceSimplest
<
TRAITS_TYPE
>
(
aPoint
,
aDart
);
bool
status
=
locateFaceSimplest
<
TraitsType
>
(
point
,
dart
);
if
(
status
==
false
)
if
(
status
==
false
)
return
status
;
return
status
;
// There may be degeneracy, i.e., the point might be outside the triangle
// There may be degeneracy, i.e., the point might be outside the triangle
...
@@ -716,460 +718,453 @@ private:
...
@@ -716,460 +718,453 @@ private:
// The next call returns true if inside a non-degenerate or a degenerate triangle,
// The next call returns true if inside a non-degenerate or a degenerate triangle,
// but false if the point coincides with the "supernode" in the case where all
// but false if the point coincides with the "supernode" in the case where all
// edges are degenerate.
// edges are degenerate.
return
inTriangle
<
TraitsType
>
(
point
,
dart
);
return
InTriangle
<
TRAITS_TYPE
>
(
aPoint
,
aDart
);
}
}
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
/** Checks if \e point is inside the triangle associated with \e dart.
/** Checks if \e point is inside the triangle associated with \e dart.
* A fast and simple function that does not deal with degeneracy.
* A fast and simple function that does not deal with degeneracy.
*
*
* \param d
art
* \param aD
art
* A CCW dart in the triangle
* A CCW dart in the triangle
*
*
* \require
* \require
* - \ref hed::TTLtraits::orient2d "TraitsType::orient2d" (DartType&, DartType&, PointType
&)
* - \ref hed::TTLtraits::Orient2D "TRAITS_TYPE::Orient2D" (DART_TYPE&, DART_TYPE&, POINT_TYPE
&)
*
*
* \see
* \see
* i
nTriangle for a more robust function
* I
nTriangle for a more robust function
*/
*/
template
<
class
TraitsType
,
class
PointType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
POINT_TYPE
,
class
DART_TYPE
>
bool
TriangulationHelper
::
inTriangleSimplest
(
const
PointType
&
point
,
const
DartType
&
dart
)
{
bool
TRIANGULATION_HELPER
::
InTriangleSimplest
(
const
POINT_TYPE
&
aPoint
,
const
DART_TYPE
&
aDart
)
{
// Fast and simple: Do not deal with degenerate faces, i.e., if there is
// Fast and simple: Do not deal with degenerate faces, i.e., if there is
// degeneracy, true will be returned if the point is on the extension of the
// degeneracy, true will be returned if the point is on the extension of the
// edges of a degenerate triangle
// edges of a degenerate triangle
DartType
d_iter
=
dart
;
DART_TYPE
d_iter
=
aDart
;
DartType
d0
=
d_iter
;
DART_TYPE
d0
=
d_iter
;
d0
.
alpha0
();
d0
.
Alpha0
();
if
(
!
TraitsType
::
orient2d
(
d_iter
,
d0
,
point
)
>=
0
)
if
(
!
TRAITS_TYPE
::
Orient2D
(
d_iter
,
d0
,
aPoint
)
>=
0
)
return
false
;
return
false
;
d_iter
.
alpha0
().
a
lpha1
();
d_iter
.
Alpha0
().
A
lpha1
();
d0
=
d_iter
;
d0
=
d_iter
;
d0
.
alpha0
();
d0
.
Alpha0
();
if
(
!
TraitsType
::
orient2d
(
d_iter
,
d0
,
point
)
>=
0
)
if
(
!
TRAITS_TYPE
::
Orient2D
(
d_iter
,
d0
,
aPoint
)
>=
0
)
return
false
;
return
false
;
d_iter
.
alpha0
().
a
lpha1
();
d_iter
.
Alpha0
().
A
lpha1
();
d0
=
d_iter
;
d0
=
d_iter
;
d0
.
alpha0
();
d0
.
Alpha0
();
if
(
!
TraitsType
::
orient2d
(
d_iter
,
d0
,
point
)
>=
0
)
if
(
!
TRAITS_TYPE
::
Orient2D
(
d_iter
,
d0
,
aPoint
)
>=
0
)
return
false
;
return
false
;
return
true
;
return
true
;
}
}
/** Checks if \e point is inside the triangle associated with \e dart.
//------------------------------------------------------------------------------------------------
/** Checks if \e point is inside the triangle associated with \e dart.
* This function deals with degeneracy to some extent, but round-off errors may still
* This function deals with degeneracy to some extent, but round-off errors may still
* lead to wrong result if the triangle is degenerate.
* lead to wrong result if the triangle is degenerate.
*
*
* \param dart
* \param aDart
* A CCW dart in the triangle
* A CCW dart in the triangle
*
*
* \require
* \require
* - \ref hed::TTLtraits::crossProduct2d "TraitsType::crossProduct2d" (DartType&, PointType
&)
* - \ref hed::TTLtraits::CrossProduct2D "TRAITS_TYPE::CrossProduct2D" (DART_TYPE&, POINT_TYPE
&)
* - \ref hed::TTLtraits::scalarProduct2d "TraitsType::scalarProduct2d" (DartType&, PointType
&)
* - \ref hed::TTLtraits::ScalarProduct2D "TRAITS_TYPE::ScalarProduct2D" (DART_TYPE&, POINT_TYPE
&)
*
*
* \see
* \see
* i
nTriangleSimplest
* I
nTriangleSimplest
*/
*/
template
<
class
TraitsType
,
class
PointType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
POINT_TYPE
,
class
DART_TYPE
>
bool
TriangulationHelper
::
inTriangle
(
const
PointType
&
point
,
const
DartType
&
dart
)
{
bool
TRIANGULATION_HELPER
::
InTriangle
(
const
POINT_TYPE
&
aPoint
,
const
DART_TYPE
&
aDart
)
{
// SHOULD WE INCLUDE A STRATEGY WITH EDGE X e_1 ETC? TO GUARANTEE THAT
// SHOULD WE INCLUDE A STRATEGY WITH EDGE X e_1 ETC? TO GUARANTEE THAT
// ONLY ON ONE EDGE? BUT THIS DOES NOT SOLVE PROBLEMS WITH
// ONLY ON ONE EDGE? BUT THIS DOES NOT SOLVE PROBLEMS WITH
// notInE1 && notInE1.neghbour ?
// notInE1 && notInE1.neghbour ?
// Returns true if inside (but not necessarily strictly inside)
// Returns true if inside (but not necessarily strictly inside)
// Works for degenerate triangles, but not when all edges are degenerate,
// Works for degenerate triangles, but not when all edges are degenerate,
// and the
p
oint coincides with all nodes;
// and the
aP
oint coincides with all nodes;
// then false is always returned.
// then false is always returned.
typedef
typename
T
raitsType
::
real_type
real_type
;
typedef
typename
T
RAITS_TYPE
::
REAL_TYPE
REAL_TYPE
;
D
artType
dart_iter
=
d
art
;
D
ART_TYPE
dart_iter
=
aD
art
;
real_type
cr1
=
TraitsType
::
crossProduct2d
(
dart_iter
,
point
);
REAL_TYPE
cr1
=
TRAITS_TYPE
::
CrossProduct2D
(
dart_iter
,
aPoint
);
if
(
cr1
<
0
)
if
(
cr1
<
0
)
return
false
;
return
false
;
dart_iter
.
alpha0
().
a
lpha1
();
dart_iter
.
Alpha0
().
A
lpha1
();
real_type
cr2
=
TraitsType
::
crossProduct2d
(
dart_iter
,
point
);
REAL_TYPE
cr2
=
TRAITS_TYPE
::
CrossProduct2D
(
dart_iter
,
aPoint
);
if
(
cr2
<
0
)
if
(
cr2
<
0
)
return
false
;
return
false
;
dart_iter
.
alpha0
().
a
lpha1
();
dart_iter
.
Alpha0
().
A
lpha1
();
real_type
cr3
=
TraitsType
::
crossProduct2d
(
dart_iter
,
point
);
REAL_TYPE
cr3
=
TRAITS_TYPE
::
CrossProduct2D
(
dart_iter
,
aPoint
);
if
(
cr3
<
0
)
if
(
cr3
<
0
)
return
false
;
return
false
;
// All cross products are >= 0
// All cross products are >= 0
// Check for degeneracy
// Check for degeneracy
if
(
cr1
!=
0
||
cr2
!=
0
||
cr3
!=
0
)
if
(
cr1
!=
0
||
cr2
!=
0
||
cr3
!=
0
)
return
true
;
// inside non-degenerate face
return
true
;
// inside non-degenerate face
// All cross-products are zero, i.e. degenerate triangle, check if inside
// All cross-products are zero, i.e. degenerate triangle, check if inside
// Strategy: d.
scalarProduct2d >= 0 && alpha0(d).d.scalarProduct2d
>= 0 for one of
// Strategy: d.
ScalarProduct2D >= 0 && alpha0(d).d.ScalarProduct2D
>= 0 for one of
// the edges. But if all edges are degenerate and the
p
oint is on (all) the nodes,
// the edges. But if all edges are degenerate and the
aP
oint is on (all) the nodes,
// then "false is returned".
// then "false is returned".
D
artType
dart_tmp
=
dart_iter
;
D
ART_TYPE
dart_tmp
=
dart_iter
;
real_type
sc1
=
TraitsType
::
scalarProduct2d
(
dart_tmp
,
point
);
REAL_TYPE
sc1
=
TRAITS_TYPE
::
ScalarProduct2D
(
dart_tmp
,
aPoint
);
real_type
sc2
=
TraitsType
::
scalarProduct2d
(
dart_tmp
.
alpha0
(),
point
);
REAL_TYPE
sc2
=
TRAITS_TYPE
::
ScalarProduct2D
(
dart_tmp
.
Alpha0
(),
aPoint
);
if
(
sc1
>=
0
&&
sc2
>=
0
)
{
if
(
sc1
>=
0
&&
sc2
>=
0
)
{
// test for degenerate edge
// test for degenerate edge
if
(
sc1
!=
0
||
sc2
!=
0
)
if
(
sc1
!=
0
||
sc2
!=
0
)
return
true
;
// interior to this edge or on a node (but see comment above)
return
true
;
// interior to this edge or on a node (but see comment above)
}
}
dart_tmp
=
dart_iter
.
alpha0
().
alpha1
();
dart_tmp
=
dart_iter
.
Alpha0
().
Alpha1
();
sc1
=
TraitsType
::
scalarProduct2d
(
dart_tmp
,
point
);
sc1
=
TRAITS_TYPE
::
ScalarProduct2D
(
dart_tmp
,
aPoint
);
sc2
=
TraitsType
::
scalarProduct2d
(
dart_tmp
.
alpha0
(),
point
);
sc2
=
TRAITS_TYPE
::
ScalarProduct2D
(
dart_tmp
.
Alpha0
(),
aPoint
);
if
(
sc1
>=
0
&&
sc2
>=
0
)
{
if
(
sc1
>=
0
&&
sc2
>=
0
)
{
// test for degenerate edge
// test for degenerate edge
if
(
sc1
!=
0
||
sc2
!=
0
)
if
(
sc1
!=
0
||
sc2
!=
0
)
return
true
;
// interior to this edge or on a node (but see comment above)
return
true
;
// interior to this edge or on a node (but see comment above)
}
}
dart_tmp
=
dart_iter
.
alpha1
();
dart_tmp
=
dart_iter
.
Alpha1
();
sc1
=
TraitsType
::
scalarProduct2d
(
dart_tmp
,
point
);
sc1
=
TRAITS_TYPE
::
ScalarProduct2D
(
dart_tmp
,
aPoint
);
sc2
=
TraitsType
::
scalarProduct2d
(
dart_tmp
.
alpha0
(),
point
);
sc2
=
TRAITS_TYPE
::
ScalarProduct2D
(
dart_tmp
.
Alpha0
(),
aPoint
);
if
(
sc1
>=
0
&&
sc2
>=
0
)
{
if
(
sc1
>=
0
&&
sc2
>=
0
)
{
// test for degenerate edge
// test for degenerate edge
if
(
sc1
!=
0
||
sc2
!=
0
)
if
(
sc1
!=
0
||
sc2
!=
0
)
return
true
;
// interior to this edge or on a node (but see comment above)
return
true
;
// interior to this edge or on a node (but see comment above)
}
}
// Not on any of the edges of the degenerate triangle.
// Not on any of the edges of the degenerate triangle.
// The only possibility for the
p
oint to be "inside" is that all edges are degenerate
// The only possibility for the
aP
oint to be "inside" is that all edges are degenerate
// and the point coincide with all nodes. So false is returned in this case.
// and the point coincide with all nodes. So false is returned in this case.
return
false
;
return
false
;
}
}
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
// Private/Hidden function (might change later)
// Private/Hidden function (might change later)
template
<
class
DartType
>
template
<
class
DART_TYPE
>
void
TriangulationHelper
::
getAdjacentTriangles
(
const
DartType
&
dart
,
DartType
&
t1
,
DartType
&
t2
,
DartType
&
t3
)
{
void
TRIANGULATION_HELPER
::
getAdjacentTriangles
(
const
DART_TYPE
&
aDart
,
DART_TYPE
&
aT1
,
DART_TYPE
&
aT2
,
DART_TYPE
&
aT3
)
{
D
artType
dart_iter
=
d
art
;
D
ART_TYPE
dart_iter
=
aD
art
;
// add first
// add first
if
(
dart_iter
.
alpha2
()
!=
dart
)
{
if
(
dart_iter
.
Alpha2
()
!=
aDart
)
t1
=
dart_iter
;
{
dart_iter
=
dart
;
aT1
=
dart_iter
;
dart_iter
=
aDart
;
}
}
// add second
// add second
dart_iter
.
alpha0
();
dart_iter
.
Alpha0
();
dart_iter
.
alpha1
();
dart_iter
.
Alpha1
();
DartType
dart_prev
=
dart_iter
;
DART_TYPE
dart_prev
=
dart_iter
;
if
((
dart_iter
.
alpha2
())
!=
dart_prev
)
{
t2
=
dart_iter
;
if
(
(
dart_iter
.
Alpha2
()
)
!=
dart_prev
)
{
aT2
=
dart_iter
;
dart_iter
=
dart_prev
;
dart_iter
=
dart_prev
;
}
}
// add third
// add third
dart_iter
.
a
lpha0
();
dart_iter
.
A
lpha0
();
dart_iter
.
a
lpha1
();
dart_iter
.
A
lpha1
();
dart_prev
=
dart_iter
;
dart_prev
=
dart_iter
;
if
((
dart_iter
.
alpha2
())
!=
dart_prev
)
t3
=
dart_iter
;
}
if
(
(
dart_iter
.
Alpha2
()
)
!=
dart_prev
)
aT3
=
dart_iter
;
}
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
/** Gets the boundary as sequence of darts, where the edges associated with the darts are boundary
/** Gets the boundary as sequence of darts, where the edges associated with the darts are boundary
* edges, given a dart with an associating edge at the boundary of a topology structure.
* edges, given a dart with an associating edge at the boundary of a topology structure.
* The first dart in the sequence will be the given one, and the others will have the same
* The first dart in the sequence will be the given one, and the others will have the same
* orientation (CCW or CW) as the first.
* orientation (CCW or CW) as the first.
* Assumes that the given dart is at the boundary.
* Assumes that the given dart is at the boundary.
*
*
* \param dart
* \param aDart
* A dart at the boundary (CCW or CW)
* A dart at the boundary (CCW or CW)
*
*
* \param b
oundary
* \param aB
oundary
* A sequence of darts, where the associated edges are the boundary edges
* A sequence of darts, where the associated edges are the boundary edges
*
*
* \require
* \require
* - DartListType::push_back (DartType
&)
* - DART_LIST_TYPE::push_back (DART_TYPE
&)
*/
*/
template
<
class
DartType
,
class
DartListType
>
template
<
class
DART_TYPE
,
class
DART_LIST_TYPE
>
void
TriangulationHelper
::
getBoundary
(
const
DartType
&
dart
,
DartListType
&
boundary
)
{
void
TRIANGULATION_HELPER
::
GetBoundary
(
const
DART_TYPE
&
aDart
,
DART_LIST_TYPE
&
aBoundary
)
{
// assumes the given dart is at the boundary (by edge)
// assumes the given dart is at the boundary (by edge)
D
artType
dart_iter
(
dart
);
D
ART_TYPE
dart_iter
(
aDart
);
boundary
.
push_back
(
dart_iter
);
// Given dart as first element
aBoundary
.
push_back
(
dart_iter
);
// Given dart as first element
dart_iter
.
a
lpha0
();
dart_iter
.
A
lpha0
();
positionAtNextBoundaryEdge
(
dart_iter
);
PositionAtNextBoundaryEdge
(
dart_iter
);
while
(
dart_iter
!=
dart
)
{
while
(
dart_iter
!=
aDart
)
boundary
.
push_back
(
dart_iter
);
{
dart_iter
.
alpha0
(
);
aBoundary
.
push_back
(
dart_iter
);
positionAtNextBoundaryEdge
(
dart_iter
);
dart_iter
.
Alpha0
(
);
}
PositionAtNextBoundaryEdge
(
dart_iter
);
}
}
}
/** Checks if the edge associated with \e dart is at
//------------------------------------------------------------------------------------------------
* the boundary of the m_triangulation.
/*
// Asumes a fixed point (a boundary edge) is given
//
template <class DartType>
class boundary_1_Iterator { // i.e. "circulator"
DartType current_;
public:
boundaryEdgeIterator(const DartType& dart) {current_ = dart;}
DartType& operator * () const {return current_;}
void operator ++ () {current_.alpha0(); positionAtNextBoundaryEdge(current_);}
};
*/
//------------------------------------------------------------------------------------------------
/** Checks if the edge associated with \e dart is at
* the boundary of the triangulation.
*
*
* \par Implements:
* \par Implements:
* \code
* \code
* DartType
dart_iter = dart;
* DART_TYPE
dart_iter = dart;
* if (dart_iter.a
lpha2() == dart)
* if (dart_iter.A
lpha2() == dart)
* return true;
* return true;
* else
* else
* return false;
* return false;
* \endcode
* \endcode
*/
*/
template
<
class
DartType
>
template
<
class
DART_TYPE
>
bool
TriangulationHelper
::
isBoundaryEdge
(
const
DartType
&
dart
)
{
bool
TRIANGULATION_HELPER
::
IsBoundaryEdge
(
const
DART_TYPE
&
aDart
)
{
DART_TYPE
dart_iter
=
aDart
;
DartType
dart_iter
=
dart
;
if
(
dart_iter
.
Alpha2
()
==
aDart
)
if
(
dart_iter
.
alpha2
()
==
dart
)
return
true
;
return
true
;
else
else
return
false
;
return
false
;
}
}
/** Checks if the face associated with \e dart is at
//------------------------------------------------------------------------------------------------
* the boundary of the m_triangulation.
/** Checks if the face associated with \e dart is at
* the boundary of the triangulation.
*/
*/
template
<
class
DartType
>
template
<
class
DART_TYPE
>
bool
TriangulationHelper
::
isBoundaryFace
(
const
DartType
&
dart
)
{
bool
TRIANGULATION_HELPER
::
IsBoundaryFace
(
const
DART_TYPE
&
aDart
)
{
// Strategy: boundary if alpha2(d)=d
// Strategy: boundary if alpha2(d)=d
D
artType
dart_iter
(
dart
);
D
ART_TYPE
dart_iter
(
aDart
);
D
artType
dart_prev
;
D
ART_TYPE
dart_prev
;
do
{
do
{
dart_prev
=
dart_iter
;
dart_prev
=
dart_iter
;
if
(
dart_iter
.
alpha2
()
==
dart_prev
)
if
(
dart_iter
.
Alpha2
()
==
dart_prev
)
return
true
;
return
true
;
else
else
dart_iter
=
dart_prev
;
// back again
dart_iter
=
dart_prev
;
// back again
dart_iter
.
a
lpha0
();
dart_iter
.
A
lpha0
();
dart_iter
.
a
lpha1
();
dart_iter
.
A
lpha1
();
}
while
(
dart_iter
!=
dart
);
}
while
(
dart_iter
!=
aDart
);
return
false
;
return
false
;
}
}
//------------------------------------------------------------------------------------------------
/** Checks if the node associated with \e dart is at
/** Checks if the node associated with \e dart is at
* the boundary of the m_triangulation.
* the boundary of the triangulation.
*/
*/
template
<
class
DartType
>
template
<
class
DART_TYPE
>
bool
TriangulationHelper
::
isBoundaryNode
(
const
DartType
&
dart
)
{
bool
TRIANGULATION_HELPER
::
IsBoundaryNode
(
const
DART_TYPE
&
aDart
)
{
// Strategy: boundary if alpha2(d)=d
// Strategy: boundary if alpha2(d)=d
D
artType
dart_iter
(
dart
);
D
ART_TYPE
dart_iter
(
aDart
);
D
artType
dart_prev
;
D
ART_TYPE
dart_prev
;
// If input dart is reached again, then internal node
// If input dart is reached again, then internal node
// If alpha2(d)=d, then boundary
// If alpha2(d)=d, then boundary
do
{
do
dart_iter
.
alpha1
();
{
dart_iter
.
Alpha1
();
dart_prev
=
dart_iter
;
dart_prev
=
dart_iter
;
dart_iter
.
a
lpha2
();
dart_iter
.
A
lpha2
();
if
(
dart_iter
==
dart_prev
)
if
(
dart_iter
==
dart_prev
)
return
true
;
return
true
;
}
while
(
dart_iter
!=
dart
);
}
while
(
dart_iter
!=
aDart
);
return
false
;
return
false
;
}
}
/** Returns the degree of the node associated with \e dart.
//------------------------------------------------------------------------------------------------
/** Returns the degree of the node associated with \e dart.
*
*
* \par Definition:
* \par Definition:
* The \e degree (or valency) of a node \e V in a
triangulation,
* The \e degree (or valency) of a node \e V in a m_
triangulation,
* is defined as the number of edges incident with \e V, i.e.,
* is defined as the number of edges incident with \e V, i.e.,
* the number of edges joining \e V with another node in the triangulation.
* the number of edges joining \e V with another node in the triangulation.
*/
*/
template
<
class
DartType
>
template
<
class
DART_TYPE
>
int
TriangulationHelper
::
getDegreeOfNode
(
const
DartType
&
dart
)
{
int
TRIANGULATION_HELPER
::
GetDegreeOfNode
(
const
DART_TYPE
&
aDart
)
{
D
artType
dart_iter
(
dart
);
D
ART_TYPE
dart_iter
(
aDart
);
D
artType
dart_prev
;
D
ART_TYPE
dart_prev
;
// If input dart is reached again, then interior node
// If input dart is reached again, then interior node
// If alpha2(d)=d, then boundary
// If alpha2(d)=d, then boundary
int
degree
=
0
;
int
degree
=
0
;
bool
boundaryVisited
=
false
;
bool
boundaryVisited
=
false
;
do
{
do
dart_iter
.
alpha1
();
{
dart_iter
.
Alpha1
();
degree
++
;
degree
++
;
dart_prev
=
dart_iter
;
dart_prev
=
dart_iter
;
dart_iter
.
a
lpha2
();
dart_iter
.
A
lpha2
();
if
(
dart_iter
==
dart_prev
)
{
if
(
dart_iter
==
dart_prev
)
if
(
!
boundaryVisited
)
{
{
if
(
!
boundaryVisited
)
{
boundaryVisited
=
true
;
boundaryVisited
=
true
;
// boundary is reached first time, count in the reversed direction
// boundary is reached first time, count in the reversed direction
degree
++
;
// count the start since it is not done above
degree
++
;
// count the start since it is not done above
dart_iter
=
dart
;
dart_iter
=
aDart
;
dart_iter
.
alpha2
();
dart_iter
.
Alpha2
();
}
}
else
else
return
degree
;
return
degree
;
}
}
}
while
(
dart_iter
!=
dart
);
}
while
(
dart_iter
!=
aDart
);
return
degree
;
return
degree
;
}
}
// Modification of GetDegreeOfNode:
// Strategy, reverse the list and start in the other direction if the boundary
// is reached. NB. copying of darts but ok., or we could have collected pointers,
// but the memory management.
//------------------------------------------------------------------------------------------------
// NOTE: not symmetry if we choose to collect opposite edges
// Modification of getDegreeOfNode:
// now we collect darts with radiating edges
// Strategy, reverse the list and start in the other direction if the boundary
// is reached. NB. copying of darts but ok., or we could have collected pointers,
// but the memory management.
// NOTE: not symmetry if we choose to collect opposite edges
// now we collect darts with radiating edges
// Remember that we must also copy the node, but ok with push_back
// Remember that we must also copy the node, but ok with push_back
// The size of the list will be the degree of the node
// The size of the list will be the degree of the node
// No CW/CCW since topology only
// No CW/CCW since topology only
// Each dart consists of an incident edge and an adjacent node.
// But note that this is only how we interpret the dart in this implementation.
// Given this list, how can we find the opposite edges:
// We can perform alpha1 on each, but for boundary nodes we will get one edge twice.
// But this is will always be the last dart!
// The darts in the list are in sequence and starts with the alpha0(dart)
// alpha0, alpha1 and alpha2
// Each dart consists of an incident edge and an adjacent node.
// Private/Hidden function
// But note that this is only how we interpret the dart in this implementation.
template
<
class
DART_TYPE
>
// Given this list, how can we find the opposite edges:
void
TRIANGULATION_HELPER
::
getNeighborNodes
(
const
DART_TYPE
&
aDart
,
// We can perform alpha1 on each, but for boundary nodes we will get one edge twice.
std
::
list
<
DART_TYPE
>&
aNodeList
,
bool
&
aBoundary
)
// But this is will always be the last dart!
{
// The darts in the list are in sequence and starts with the alpha0(dart)
DART_TYPE
dart_iter
(
aDart
);
// alpha0, alpha1 and alpha2
dart_iter
.
Alpha0
();
// position the dart at an opposite node
// Private/Hidden function
template
<
class
DartType
>
void
TriangulationHelper
::
getNeighborNodes
(
const
DartType
&
dart
,
std
::
list
<
DartType
>&
node_list
,
bool
&
boundary
)
{
DartType
dart_iter
(
dart
);
dart_iter
.
alpha0
();
// position the dart at an opposite node
DartType
dart_prev
=
dart_iter
;
DART_TYPE
dart_prev
=
dart_iter
;
bool
start_at_boundary
=
false
;
bool
start_at_boundary
=
false
;
dart_iter
.
alpha2
();
dart_iter
.
Alpha2
();
if
(
dart_iter
==
dart_prev
)
if
(
dart_iter
==
dart_prev
)
start_at_boundary
=
true
;
start_at_boundary
=
true
;
else
else
dart_iter
=
dart_prev
;
// back again
dart_iter
=
dart_prev
;
// back again
D
artType
dart_start
=
dart_iter
;
D
ART_TYPE
dart_start
=
dart_iter
;
do
{
do
node_list
.
push_back
(
dart_iter
);
{
dart_iter
.
alpha1
();
aNodeList
.
push_back
(
dart_iter
);
dart_iter
.
alpha0
();
dart_iter
.
Alpha1
();
dart_iter
.
alpha1
();
dart_iter
.
Alpha0
();
dart_iter
.
Alpha1
();
dart_prev
=
dart_iter
;
dart_prev
=
dart_iter
;
dart_iter
.
alpha2
();
dart_iter
.
Alpha2
();
if
(
dart_iter
==
dart_prev
)
{
if
(
dart_iter
==
dart_prev
)
{
// boundary reached
// boundary reached
boundary
=
true
;
aBoundary
=
true
;
if
(
start_at_boundary
==
true
)
{
if
(
start_at_boundary
==
true
)
{
// add the dart which now is positioned at the opposite boundary
// add the dart which now is positioned at the opposite boundary
node_list
.
push_back
(
dart_iter
);
aNodeList
.
push_back
(
dart_iter
);
return
;
return
;
}
}
else
{
else
{
// call the function again such that we start at the boundary
// call the function again such that we start at the boundary
// first clear the list and reposition to the initial node
// first clear the list and reposition to the initial node
dart_iter
.
alpha0
();
dart_iter
.
Alpha0
();
node_list
.
clear
();
aNodeList
.
clear
();
getNeighborNodes
(
dart_iter
,
node_list
,
boundary
);
getNeighborNodes
(
dart_iter
,
aNodeList
,
aBoundary
);
return
;
// after one recursive step
return
;
// after one recursive step
}
}
}
}
}
while
(
dart_iter
!=
dart_start
);
boundary
=
false
;
}
}
while
(
dart_iter
!=
dart_start
);
aBoundary
=
false
;
}
//------------------------------------------------------------------------------------------------
/** Gets the 0-orbit around an interior node.
/** Gets the 0-orbit around an interior node.
*
*
* \param d
art
* \param aD
art
* A dart (CCW or CW) positioned at an \e interior node.
* A dart (CCW or CW) positioned at an \e interior node.
*
*
* \retval o
rbit
* \retval aO
rbit
* Sequence of darts with one orbit for each arc. All the darts have the same
* Sequence of darts with one orbit for each arc. All the darts have the same
* orientation (CCW or CW) as \e dart, and \e dart is the first element
* orientation (CCW or CW) as \e dart, and \e dart is the first element
* in the sequence.
* in the sequence.
*
*
* \require
* \require
* - DartListType::push_back (DartType
&)
* - DART_LIST_TYPE::push_back (DART_TYPE
&)
*
*
* \see
* \see
* get_0_orbit_b
oundary
* Get0OrbitB
oundary
*/
*/
template
<
class
DartType
,
class
DartListType
>
template
<
class
DART_TYPE
,
class
DART_LIST_TYPE
>
void
TriangulationHelper
::
get_0_orbit_interior
(
const
DartType
&
dart
,
DartListType
&
orbit
)
{
void
TRIANGULATION_HELPER
::
Get0OrbitInterior
(
const
DART_TYPE
&
aDart
,
DART_LIST_TYPE
&
aOrbit
)
{
D
artType
d_iter
=
d
art
;
D
ART_TYPE
d_iter
=
aD
art
;
orbit
.
push_back
(
d_iter
);
aOrbit
.
push_back
(
d_iter
);
d_iter
.
alpha1
().
a
lpha2
();
d_iter
.
Alpha1
().
A
lpha2
();
while
(
d_iter
!=
dart
)
{
while
(
d_iter
!=
aDart
)
orbit
.
push_back
(
d_iter
);
{
d_iter
.
alpha1
().
alpha2
(
);
aOrbit
.
push_back
(
d_iter
);
}
d_iter
.
Alpha1
().
Alpha2
();
}
}
}
/** Gets the 0-orbit around a node at the boundary
//------------------------------------------------------------------------------------------------
/** Gets the 0-orbit around a node at the boundary
*
*
* \param d
art
* \param aD
art
* A dart (CCW or CW) positioned at a \e boundary \e node and at a \e boundary \e edge.
* A dart (CCW or CW) positioned at a \e boundary \e node and at a \e boundary \e edge.
*
*
* \retval orbit
* \retval orbit
...
@@ -1178,32 +1173,33 @@ private:
...
@@ -1178,32 +1173,33 @@ private:
* in the sequence.
* in the sequence.
*
*
* \require
* \require
* - DartListType::push_back (DartType
&)
* - DART_LIST_TYPE::push_back (DART_TYPE
&)
*
*
* \note
* \note
* - The last dart in the sequence have opposite orientation compared to the others!
* - The last dart in the sequence have opposite orientation compared to the others!
*
*
* \see
* \see
* get_0_orbit_i
nterior
* Get0OrbitI
nterior
*/
*/
template
<
class
DartType
,
class
DartListType
>
template
<
class
DART_TYPE
,
class
DART_LIST_TYPE
>
void
TriangulationHelper
::
get_0_orbit_boundary
(
const
DartType
&
dart
,
DartListType
&
orbit
)
{
void
TRIANGULATION_HELPER
::
Get0OrbitBoundary
(
const
DART_TYPE
&
aDart
,
DART_LIST_TYPE
&
aOrbit
)
{
DartType
dart_prev
;
DART_TYPE
dart_prev
;
DartType
d_iter
=
dart
;
DART_TYPE
d_iter
=
aDart
;
do
{
orbit
.
push_back
(
d_iter
);
d_iter
.
alpha1
();
dart_prev
=
d_iter
;
d_iter
.
alpha2
();
}
while
(
d_iter
!=
dart_prev
);
orbit
.
push_back
(
d_iter
);
// the last one with opposite orientation
do
{
aOrbit
.
push_back
(
d_iter
);
d_iter
.
Alpha1
();
dart_prev
=
d_iter
;
d_iter
.
Alpha2
();
}
}
while
(
d_iter
!=
dart_prev
);
aOrbit
.
push_back
(
d_iter
);
// the last one with opposite orientation
}
//------------------------------------------------------------------------------------------------
/** Checks if the two darts belong to the same 0-orbit, i.e.,
/** Checks if the two darts belong to the same 0-orbit, i.e.,
* if they share a node.
* if they share a node.
* \e d1 and/or \e d2 can be CCW or CW.
* \e d1 and/or \e d2 can be CCW or CW.
*
*
...
@@ -1213,141 +1209,140 @@ private:
...
@@ -1213,141 +1209,140 @@ private:
* node and a faster version is needed, the user should implement his/her
* node and a faster version is needed, the user should implement his/her
* own version.)
* own version.)
*/
*/
template
<
class
DartType
>
template
<
class
DART_TYPE
>
bool
TriangulationHelper
::
same_0_orbit
(
const
DartType
&
d1
,
const
DartType
&
d2
)
{
bool
TRIANGULATION_HELPER
::
Same0Orbit
(
const
DART_TYPE
&
aD1
,
const
DART_TYPE
&
aD2
)
{
// Two copies of the same dart
// Two copies of the same dart
D
artType
d_iter
=
d
2
;
D
ART_TYPE
d_iter
=
aD
2
;
D
artType
d_end
=
d
2
;
D
ART_TYPE
d_end
=
aD
2
;
if
(
isBoundaryNode
(
d_iter
))
{
if
(
isBoundaryNode
(
d_iter
)
)
{
// position at both boundary edges
// position at both boundary edges
positionAtNextBoundaryEdge
(
d_iter
);
PositionAtNextBoundaryEdge
(
d_iter
);
d_end
.
a
lpha1
();
d_end
.
A
lpha1
();
positionAtNextBoundaryEdge
(
d_end
);
PositionAtNextBoundaryEdge
(
d_end
);
}
}
for
(;;)
{
for
(
;;
)
if
(
d_iter
==
d1
)
{
if
(
d_iter
==
aD1
)
return
true
;
return
true
;
d_iter
.
alpha1
();
if
(
d_iter
==
d1
)
d_iter
.
Alpha1
();
if
(
d_iter
==
aD1
)
return
true
;
return
true
;
d_iter
.
alpha2
();
if
(
d_iter
==
d_end
)
d_iter
.
Alpha2
();
if
(
d_iter
==
d_end
)
break
;
break
;
}
}
return
false
;
return
false
;
}
}
/** Checks if the two darts belong to the same 1-orbit, i.e.,
//------------------------------------------------------------------------------------------------
/** Checks if the two darts belong to the same 1-orbit, i.e.,
* if they share an edge.
* if they share an edge.
* \e d1 and/or \e d2 can be CCW or CW.
* \e d1 and/or \e d2 can be CCW or CW.
*/
*/
template
<
class
DartType
>
template
<
class
DART_TYPE
>
bool
TriangulationHelper
::
same_1_orbit
(
const
DartType
&
d1
,
const
DartType
&
d2
)
{
bool
TRIANGULATION_HELPER
::
Same1Orbit
(
const
DART_TYPE
&
aD1
,
const
DART_TYPE
&
aD2
)
{
DART_TYPE
d_iter
=
aD2
;
DartType
d_iter
=
d2
;
// (Also works at the boundary)
// (Also works at the boundary)
if
(
d_iter
==
d1
||
d_iter
.
alpha0
()
==
d1
||
d_iter
.
alpha2
()
==
d1
||
d_iter
.
alpha0
()
==
d1
)
return
(
d_iter
==
aD1
||
d_iter
.
Alpha0
()
==
aD1
||
return
true
;
d_iter
.
Alpha2
()
==
aD1
||
d_iter
.
Alpha0
()
==
aD1
);
return
false
;
}
}
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
/** Checks if the two darts belong to the same 2-orbit, i.e.,
/** Checks if the two darts belong to the same 2-orbit, i.e.,
* if they lie in the same triangle.
* if they lie in the same triangle.
* \e d1 and/or \e d2 can be CCW or CW
* \e d1 and/or \e d2 can be CCW or CW
*/
*/
template
<
class
DartType
>
template
<
class
DART_TYPE
>
bool
TriangulationHelper
::
same_2_orbit
(
const
DartType
&
d1
,
const
DartType
&
d2
)
{
bool
TRIANGULATION_HELPER
::
Same2Orbit
(
const
DART_TYPE
&
aD1
,
const
DART_TYPE
&
aD2
)
{
DartType
d_iter
=
d2
;
DART_TYPE
d_iter
=
aD2
;
if
(
d_iter
==
d1
||
d_iter
.
alpha0
()
==
d1
||
d_iter
.
alpha1
()
==
d1
||
d_iter
.
alpha0
()
==
d1
||
d_iter
.
alpha1
()
==
d1
||
d_iter
.
alpha0
()
==
d1
)
return
true
;
return
false
;
}
//------------------------------------------------------------------------------------------------
return
(
d_iter
==
aD1
||
d_iter
.
Alpha0
()
==
aD1
||
d_iter
.
Alpha1
()
==
aD1
||
// Private/Hidden function
d_iter
.
Alpha0
()
==
aD1
||
d_iter
.
Alpha1
()
==
aD1
||
d_iter
.
Alpha0
()
==
aD1
);
template
<
class
TraitsType
,
class
DartType
>
}
bool
TriangulationHelper
::
degenerateTriangle
(
const
DartType
&
dart
)
{
// Private/Hidden function
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
>
bool
TRIANGULATION_HELPER
::
degenerateTriangle
(
const
DART_TYPE
&
aDart
)
{
// Check if triangle is degenerate
// Check if triangle is degenerate
// Assumes CCW dart
// Assumes CCW dart
DartType
d1
=
dart
;
DART_TYPE
d1
=
aDart
;
DartType
d2
=
d1
;
DART_TYPE
d2
=
d1
;
d2
.
alpha1
();
d2
.
Alpha1
();
if
(
TraitsType
::
crossProduct2d
(
d1
,
d2
)
==
0
)
return
true
;
return
false
;
}
return
(
TRAITS_TYPE
::
CrossProduct2D
(
d1
,
d2
)
==
0
);
}
//------------------------------------------------------------------------------------------------
/** Checks if the edge associated with \e dart is swappable, i.e., if the edge
/** Checks if the edge associated with \e dart is swappable, i.e., if the edge
* is a diagonal in a \e strictly convex (or convex) quadrilateral.
* is a diagonal in a \e strictly convex (or convex) quadrilateral.
*
*
* \param a
llowDegeneracy
* \param aA
llowDegeneracy
* If set to true, the function will also return true if the numerical calculations
* If set to true, the function will also return true if the numerical calculations
* indicate that the quadrilateral is convex only, and not necessarily strictly
* indicate that the quadrilateral is convex only, and not necessarily strictly
* convex.
* convex.
*
*
* \require
* \require
* - \ref hed::TTLtraits::crossProduct2d "TraitsType::crossProduct2d
" (Dart&, Dart&)
* - \ref hed::TTLtraits::CrossProduct2D "TRAITS_TYPE::CrossProduct2D
" (Dart&, Dart&)
*/
*/
template
<
class
TraitsType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
>
bool
TriangulationHelper
::
swappableEdge
(
const
DartType
&
dart
,
bool
allowDegeneracy
)
{
bool
TRIANGULATION_HELPER
::
SwappableEdge
(
const
DART_TYPE
&
aDart
,
bool
aAllowDegeneracy
)
{
// How "safe" is it?
// How "safe" is it?
if
(
isBoundaryEdge
(
dart
)
)
if
(
IsBoundaryEdge
(
aDart
)
)
return
false
;
return
false
;
// "angles" are at the diagonal
// "angles" are at the diagonal
DartType
d1
=
dart
;
DART_TYPE
d1
=
aDart
;
d1
.
alpha2
().
alpha1
();
d1
.
Alpha2
().
Alpha1
();
DartType
d2
=
dart
;
DART_TYPE
d2
=
aDart
;
d2
.
alpha1
();
d2
.
Alpha1
();
if
(
allowDegeneracy
)
{
if
(
TraitsType
::
crossProduct2d
(
d1
,
d2
)
<
0
.
0
)
if
(
aAllowDegeneracy
)
{
if
(
TRAITS_TYPE
::
CrossProduct2D
(
d1
,
d2
)
<
0
.
0
)
return
false
;
return
false
;
}
}
else
{
else
if
(
TraitsType
::
crossProduct2d
(
d1
,
d2
)
<=
0
.
0
)
{
if
(
TRAITS_TYPE
::
CrossProduct2D
(
d1
,
d2
)
<=
0
.
0
)
return
false
;
return
false
;
}
}
// Opposite side (still angle at the diagonal)
// Opposite side (still angle at the diagonal)
d1
=
d
art
;
d1
=
aD
art
;
d1
.
a
lpha0
();
d1
.
A
lpha0
();
d2
=
d1
;
d2
=
d1
;
d1
.
a
lpha1
();
d1
.
A
lpha1
();
d2
.
alpha2
().
a
lpha1
();
d2
.
Alpha2
().
A
lpha1
();
if
(
allowDegeneracy
)
{
if
(
aAllowDegeneracy
)
if
(
TraitsType
::
crossProduct2d
(
d1
,
d2
)
<
0
.
0
)
{
if
(
TRAITS_TYPE
::
CrossProduct2D
(
d1
,
d2
)
<
0
.
0
)
return
false
;
return
false
;
}
}
else
{
else
if
(
TraitsType
::
crossProduct2d
(
d1
,
d2
)
<=
0
.
0
)
{
if
(
TRAITS_TYPE
::
CrossProduct2D
(
d1
,
d2
)
<=
0
.
0
)
return
false
;
return
false
;
}
}
return
true
;
}
return
true
;
}
//------------------------------------------------------------------------------------------------
/** Given a \e dart, CCW or CW, positioned in a 0-orbit at the boundary of a tessellation.
/** Given a \e dart, CCW or CW, positioned in a 0-orbit at the boundary of a tessellation.
* Position \e dart at a boundary edge in the same 0-orbit.\n
* Position \e dart at a boundary edge in the same 0-orbit.\n
* If the given \e dart is CCW, \e dart is positioned at the left boundary edge
* If the given \e dart is CCW, \e dart is positioned at the left boundary edge
* and will be CW.\n
* and will be CW.\n
...
@@ -1358,59 +1353,66 @@ private:
...
@@ -1358,59 +1353,66 @@ private:
* - The given \e dart must have a source node at the boundary, otherwise an
* - The given \e dart must have a source node at the boundary, otherwise an
* infinit loop occurs.
* infinit loop occurs.
*/
*/
template
<
class
DartType
>
template
<
class
DART_TYPE
>
void
TriangulationHelper
::
positionAtNextBoundaryEdge
(
DartType
&
dart
)
{
void
TRIANGULATION_HELPER
::
PositionAtNextBoundaryEdge
(
DART_TYPE
&
aDart
)
{
D
artType
dart_prev
;
D
ART_TYPE
dart_prev
;
// If alpha2(d)=d, then boundary
// If alpha2(d)=d, then boundary
//old convention: dart.
a
lpha0();
//old convention: dart.
A
lpha0();
do
{
do
dart
.
alpha1
();
{
dart_prev
=
dart
;
aDart
.
Alpha1
()
;
dart
.
alpha2
()
;
dart_prev
=
aDart
;
}
while
(
dart
!=
dart_prev
);
aDart
.
Alpha2
(
);
}
}
while
(
aDart
!=
dart_prev
);
}
/** Checks if the boundary of a triangulation is convex.
//------------------------------------------------------------------------------------------------
/** Checks if the boundary of a triangulation is convex.
*
*
* \param dart
* \param dart
* A CCW dart at the boundary of the
triangulation
* A CCW dart at the boundary of the m_
triangulation
*
*
* \require
* \require
* - \ref hed::TTLtraits::crossProduct2d "TraitsType::crossProduct2d
" (const Dart&, const Dart&)
* - \ref hed::TTLtraits::CrossProduct2D "TRAITS_TYPE::CrossProduct2D
" (const Dart&, const Dart&)
*/
*/
template
<
class
TraitsType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
>
bool
TriangulationHelper
::
convexBoundary
(
const
DartType
&
dart
)
{
bool
TRIANGULATION_HELPER
::
ConvexBoundary
(
const
DART_TYPE
&
aDart
)
{
std
::
list
<
D
artType
>
blist
;
std
::
list
<
D
ART_TYPE
>
blist
;
getBoundary
(
dart
,
blist
);
getBoundary
(
aDart
,
blist
);
int
no
;
int
no
;
no
=
(
int
)
blist
.
size
();
no
=
(
int
)
blist
.
size
();
typename
std
::
list
<
D
artType
>::
const_iterator
bit
=
blist
.
begin
();
typename
std
::
list
<
D
ART_TYPE
>::
const_iterator
bit
=
blist
.
begin
();
D
artType
d1
=
*
bit
;
D
ART_TYPE
d1
=
*
bit
;
++
bit
;
++
bit
;
D
artType
d2
;
D
ART_TYPE
d2
;
bool
convex
=
true
;
bool
convex
=
true
;
for
(;
bit
!=
blist
.
end
();
++
bit
)
{
for
(
;
bit
!=
blist
.
end
();
++
bit
)
{
d2
=
*
bit
;
d2
=
*
bit
;
double
crossProd
=
TraitsType
::
crossProduct2d
(
d1
,
d2
);
double
crossProd
=
TRAITS_TYPE
::
CrossProduct2D
(
d1
,
d2
);
if
(
crossProd
<
0
.
0
)
{
if
(
crossProd
<
0
.
0
)
{
//cout << "!!! Boundary is NOT convex: crossProd = " << crossProd << endl;
//cout << "!!! Boundary is NOT convex: crossProd = " << crossProd << endl;
convex
=
false
;
convex
=
false
;
return
convex
;
return
convex
;
}
}
d1
=
d2
;
d1
=
d2
;
}
}
// Check the last angle
// Check the last angle
d2
=
*
blist
.
begin
();
d2
=
*
blist
.
begin
();
double
crossProd
=
TraitsType
::
crossProduct2d
(
d1
,
d2
);
double
crossProd
=
TRAITS_TYPE
::
CrossProduct2D
(
d1
,
d2
);
if
(
crossProd
<
0
.
0
)
{
if
(
crossProd
<
0
.
0
)
{
//cout << "!!! Boundary is NOT convex: crossProd = " << crossProd << endl;
//cout << "!!! Boundary is NOT convex: crossProd = " << crossProd << endl;
convex
=
false
;
convex
=
false
;
}
}
...
@@ -1419,46 +1421,41 @@ private:
...
@@ -1419,46 +1421,41 @@ private:
// cout << "\n---> Boundary is convex\n" << endl;
// cout << "\n---> Boundary is convex\n" << endl;
//cout << endl;
//cout << endl;
return
convex
;
return
convex
;
}
}
//@} // End of Topological and Geometric Queries Group
//------------------------------------------------------------------------------------------------
// ------------------------ Utilities for Delaunay Triangulation Group --------------------------
//------------------------------------------------------------------------------------------------
/** @name Utilities for Delaunay Triangulation */
//@} // End of Topological and Geometric Queries Group
//@{
//------------------------------------------------------------------------------------------------
/** @name Utilities for Delaunay Triangulation */
/** Optimizes the edges in the given sequence according to the
//@{
//------------------------------------------------------------------------------------------------
/** Optimizes the edges in the given sequence according to the
* \e Delaunay criterion, i.e., such that the edge will fullfill the
* \e Delaunay criterion, i.e., such that the edge will fullfill the
* \e circumcircle criterion (or equivalently the \e MaxMin
* \e circumcircle criterion (or equivalently the \e MaxMin
* angle criterion) with respect to the quadrilaterals where
* angle criterion) with respect to the quadrilaterals where
* they are diagonals.
* they are diagonals.
*
*
* \param elist
* \param aElist
* The sequence of edges
* The sequence of edges
*
*
* \require
* \require
* - \ref hed::TTLtraits::swapEdge "TraitsType::swapEdge" (DartType
& \e dart)\n
* - \ref hed::TTLtraits::swapEdge "TRAITS_TYPE::swapEdge" (DART_TYPE
& \e dart)\n
* \b Note: Must be implemented such that \e dart is delivered back in a position as
* \b Note: Must be implemented such that \e dart is delivered back in a position as
* seen if it was glued to the edge when swapping (rotating) the edge CCW
* seen if it was glued to the edge when swapping (rotating) the edge CCW
*
*
* \using
* \using
* - swapTestDelaunay
* - swapTestDelaunay
*/
*/
template
<
class
TraitsType
,
class
DartType
,
class
DartListType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
,
class
DART_LIST_TYPE
>
void
TriangulationHelper
::
optimizeDelaunay
(
DartListType
&
elist
)
{
void
TRIANGULATION_HELPER
::
OptimizeDelaunay
(
DART_LIST_TYPE
&
aElist
)
optimizeDelaunay
<
TraitsType
,
DartType
,
DartListType
>
(
elist
,
elist
.
end
());
{
}
OptimizeDelaunay
<
TRAITS_TYPE
,
DART_TYPE
,
DART_LIST_TYPE
>
(
aElist
,
aElist
.
end
()
);
}
//------------------------------------------------------------------------------------------------
template
<
class
TraitsType
,
class
DartType
,
class
DartListType
>
void
TriangulationHelper
::
optimizeDelaunay
(
DartListType
&
elist
,
const
typename
DartListType
::
iterator
end
)
{
//------------------------------------------------------------------------------------------------
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
,
class
DART_LIST_TYPE
>
void
TRIANGULATION_HELPER
::
OptimizeDelaunay
(
DART_LIST_TYPE
&
aElist
,
const
typename
DART_LIST_TYPE
::
iterator
aEnd
)
{
// CCW darts
// CCW darts
// Optimize here means Delaunay, but could be any criterion by
// Optimize here means Delaunay, but could be any criterion by
// requiring a "should swap" in the traits class, or give
// requiring a "should swap" in the traits class, or give
...
@@ -1475,15 +1472,15 @@ private:
...
@@ -1475,15 +1472,15 @@ private:
// (A vector instead of a list may be better.)
// (A vector instead of a list may be better.)
// First check that elist is not empty
// First check that elist is not empty
if
(
elist
.
empty
()
)
if
(
aElist
.
empty
()
)
return
;
return
;
// Avoid cycling by more extensive circumcircle test
// Avoid cycling by more extensive circumcircle test
bool
cycling_check
=
true
;
bool
cycling_check
=
true
;
bool
optimal
=
false
;
bool
optimal
=
false
;
typename
D
artListType
::
iterator
it
;
typename
D
ART_LIST_TYPE
::
iterator
it
;
typename
D
artListType
::
iterator
end_opt
=
e
nd
;
typename
D
ART_LIST_TYPE
::
iterator
end_opt
=
aE
nd
;
// Hmm... The following code is trying to derefence an iterator that may
// Hmm... The following code is trying to derefence an iterator that may
// be invalid. This may lead to debug error on Windows, so we comment out
// be invalid. This may lead to debug error on Windows, so we comment out
...
@@ -1491,52 +1488,53 @@ private:
...
@@ -1491,52 +1488,53 @@ private:
// problems...
// problems...
//
//
// last_opt is passed the end of the "active list"
// last_opt is passed the end of the "active list"
//typename D
artListType
::iterator end_opt;
//typename D
ART_LIST_TYPE
::iterator end_opt;
//if (*end != NULL)
//if (*end != NULL)
// end_opt = end;
// end_opt = end;
//else
//else
// end_opt = elist.end();
// end_opt = elist.end();
while
(
!
optimal
)
{
while
(
!
optimal
)
{
optimal
=
true
;
optimal
=
true
;
for
(
it
=
elist
.
begin
();
it
!=
end_opt
;
++
it
)
{
for
(
it
=
aElist
.
begin
();
it
!=
end_opt
;
++
it
)
if
(
swapTestDelaunay
<
TraitsType
>
(
*
it
,
cycling_check
))
{
{
if
(
SwapTestDelaunay
<
TRAITS_TYPE
>
(
*
it
,
cycling_check
)
)
{
// Preserve darts. Potential darts in the list are:
// Preserve darts. Potential darts in the list are:
// - The current dart
// - The current dart
// - the four CCW darts on the boundary of the quadrilateral
// - the four CCW darts on the boundary of the quadrilateral
// (the current arc has only one dart)
// (the current arc has only one dart)
swapEdgeInList
<
TraitsType
,
DartType
>
(
it
,
elist
);
SwapEdgeInList
<
TRAITS_TYPE
,
DART_TYPE
>
(
it
,
aElist
);
optimal
=
false
;
optimal
=
false
;
}
// end if should swap
}
// end if should swap
}
// end for
}
// end for
}
// end pass
}
// end pass
}
}
//------------------------------------------------------------------------------------------------
/** Checks if the edge associated with \e dart should be swapped according
/** Checks if the edge associated with \e dart should be swapped according
* to the \e Delaunay criterion, i.e., the \e circumcircle criterion (or
* to the \e Delaunay criterion, i.e., the \e circumcircle criterion (or
* equivalently the \e MaxMin angle criterion).
* equivalently the \e MaxMin angle criterion).
*
*
* \param cycling_c
heck
* \param aCyclingC
heck
* Must be set to \c true when used in connection with optimization algorithms,
* Must be set to \c true when used in connection with optimization algorithms,
* e.g., o
ptimizeDelaunay. This will avoid cycling and infinite loops in nearly
* e.g., O
ptimizeDelaunay. This will avoid cycling and infinite loops in nearly
* neutral cases.
* neutral cases.
*
*
* \require
* \require
* - \ref hed::TTLtraits::scalarProduct2d "TraitsType::scalarProduct2d" (DartType&, DartType
&)
* - \ref hed::TTLtraits::ScalarProduct2D "TRAITS_TYPE::ScalarProduct2D" (DART_TYPE&, DART_TYPE
&)
* - \ref hed::TTLtraits::crossProduct2d "TraitsType::crossProduct2d" (DartType&, DartType
&)
* - \ref hed::TTLtraits::CrossProduct2D "TRAITS_TYPE::CrossProduct2D" (DART_TYPE&, DART_TYPE
&)
*/
*/
template
<
class
TraitsType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
>
#if ((_MSC_VER > 0) && (_MSC_VER < 1300))//#ifdef _MSC_VER
#if ((_MSC_VER > 0) && (_MSC_VER < 1300))//#ifdef _MSC_VER
bool
TriangulationHelper
::
swapTestDelaunay
(
const
DartType
&
dart
,
bool
cycling_check
=
false
)
const
{
bool
TRIANGULATION_HELPER
::
SwapTestDelaunay
(
const
DART_TYPE
&
aDart
,
bool
aCyclingCheck
=
false
)
const
{
#else
#else
bool
TriangulationHelper
::
swapTestDelaunay
(
const
DartType
&
dart
,
bool
cycling_check
)
const
{
bool
TRIANGULATION_HELPER
::
SwapTestDelaunay
(
const
DART_TYPE
&
aDart
,
bool
aCyclingCheck
)
const
{
#endif
#endif
// The general strategy is taken from Cline & Renka. They claim that
// The general strategy is taken from Cline & Renka. They claim that
// their algorithm insure numerical stability, but experiments show
// their algorithm insure numerical stability, but experiments show
// that this is not correct for neutral, or almost neutral cases.
// that this is not correct for neutral, or almost neutral cases.
...
@@ -1544,41 +1542,44 @@ private:
...
@@ -1544,41 +1542,44 @@ private:
// cycling and infinit loops when used in connection with LOP algorithms;
// cycling and infinit loops when used in connection with LOP algorithms;
// see the comments below.
// see the comments below.
typedef
typename
T
raitsType
::
real_type
real_type
;
typedef
typename
T
RAITS_TYPE
::
REAL_TYPE
REAL_TYPE
;
if
(
isBoundaryEdge
(
dart
)
)
if
(
IsBoundaryEdge
(
aDart
)
)
return
false
;
return
false
;
D
artType
v11
=
d
art
;
D
ART_TYPE
v11
=
aD
art
;
v11
.
alpha1
().
a
lpha0
();
v11
.
Alpha1
().
A
lpha0
();
D
artType
v12
=
v11
;
D
ART_TYPE
v12
=
v11
;
v12
.
a
lpha1
();
v12
.
A
lpha1
();
D
artType
v22
=
d
art
;
D
ART_TYPE
v22
=
aD
art
;
v22
.
alpha2
().
alpha1
().
a
lpha0
();
v22
.
Alpha2
().
Alpha1
().
A
lpha0
();
D
artType
v21
=
v22
;
D
ART_TYPE
v21
=
v22
;
v21
.
a
lpha1
();
v21
.
A
lpha1
();
real_type
cos1
=
TraitsType
::
scalarProduct2d
(
v11
,
v12
);
REAL_TYPE
cos1
=
TRAITS_TYPE
::
ScalarProduct2D
(
v11
,
v12
);
real_type
cos2
=
TraitsType
::
scalarProduct2d
(
v21
,
v22
);
REAL_TYPE
cos2
=
TRAITS_TYPE
::
ScalarProduct2D
(
v21
,
v22
);
// "Angles" are opposite to the diagonal.
// "Angles" are opposite to the diagonal.
// The diagonals should be swapped iff (t1+t2) .gt. 180
// The diagonals should be swapped iff (t1+t2) .gt. 180
// degrees. The following two tests insure numerical
// degrees. The following two tests insure numerical
// stability according to Cline & Renka. But experiments show
// stability according to Cline & Renka. But experiments show
// that cycling may still happen; see the aditional test below.
// that cycling may still happen; see the aditional test below.
if
(
cos1
>=
0
&&
cos2
>=
0
)
// both angles are grater or equual 90
if
(
cos1
>=
0
&&
cos2
>=
0
)
// both angles are grater or equual 90
return
false
;
return
false
;
if
(
cos1
<
0
&&
cos2
<
0
)
// both angles are less than 90
if
(
cos1
<
0
&&
cos2
<
0
)
// both angles are less than 90
return
true
;
return
true
;
real_type
sin1
=
TraitsType
::
crossProduct2d
(
v11
,
v12
);
REAL_TYPE
sin1
=
TRAITS_TYPE
::
CrossProduct2D
(
v11
,
v12
);
real_type
sin2
=
TraitsType
::
crossProduct2d
(
v21
,
v22
);
REAL_TYPE
sin2
=
TRAITS_TYPE
::
CrossProduct2D
(
v21
,
v22
);
real_type
sin12
=
sin1
*
cos2
+
cos1
*
sin2
;
REAL_TYPE
sin12
=
sin1
*
cos2
+
cos1
*
sin2
;
if
(
sin12
>=
0
)
// equality represents a neutral case
if
(
sin12
>=
0
)
// equality represents a neutral case
return
false
;
return
false
;
if
(
cycling_check
)
{
if
(
aCyclingCheck
)
{
// situation so far is sin12 < 0. Test if this also
// situation so far is sin12 < 0. Test if this also
// happens for the swapped edge.
// happens for the swapped edge.
...
@@ -1587,108 +1588,111 @@ private:
...
@@ -1587,108 +1588,111 @@ private:
// in neutral cases, or almost neutral cases, it may happen that
// in neutral cases, or almost neutral cases, it may happen that
// the swapped edge may again be found to be not Delaunay and thus
// the swapped edge may again be found to be not Delaunay and thus
// be swapped if we return true here. This may lead to cycling and
// be swapped if we return true here. This may lead to cycling and
// an infinte loop when used, e.g., in connection with o
ptimizeDelaunay.
// an infinte loop when used, e.g., in connection with O
ptimizeDelaunay.
//
//
// In an attempt to avoid this we test if the swapped edge will
// In an attempt to avoid this we test if the swapped edge will
// also be found to be not Delaunay by repeating the last test above
// also be found to be not Delaunay by repeating the last test above
// for the swapped edge.
// for the swapped edge.
// We now rely on the general requirement for TraitsType
::swapEdge which
// We now rely on the general requirement for TRAITS_TYPE
::swapEdge which
// should deliver CCW dart back in "the same position"; see the general
// should deliver CCW dart back in "the same position"; see the general
// description. This will insure numerical stability as the next calculation
// description. This will insure numerical stability as the next calculation
// is the same as if this function was called again with the swapped edge.
// is the same as if this function was called again with the swapped edge.
// Cycling is thus impossible provided that the initial tests above does
// Cycling is thus impossible provided that the initial tests above does
// not result in ambiguity (and they should probably not do so).
// not result in ambiguity (and they should probably not do so).
v11
.
a
lpha0
();
v11
.
A
lpha0
();
v12
.
a
lpha0
();
v12
.
A
lpha0
();
v21
.
a
lpha0
();
v21
.
A
lpha0
();
v22
.
a
lpha0
();
v22
.
A
lpha0
();
// as if the edge was swapped/rotated CCW
// as if the edge was swapped/rotated CCW
cos1
=
TraitsType
::
scalarProduct2d
(
v22
,
v11
);
cos1
=
TRAITS_TYPE
::
ScalarProduct2D
(
v22
,
v11
);
cos2
=
TraitsType
::
scalarProduct2d
(
v12
,
v21
);
cos2
=
TRAITS_TYPE
::
ScalarProduct2D
(
v12
,
v21
);
sin1
=
TraitsType
::
crossProduct2d
(
v22
,
v11
);
sin1
=
TRAITS_TYPE
::
CrossProduct2D
(
v22
,
v11
);
sin2
=
TraitsType
::
crossProduct2d
(
v12
,
v21
);
sin2
=
TRAITS_TYPE
::
CrossProduct2D
(
v12
,
v21
);
sin12
=
sin1
*
cos2
+
cos1
*
sin2
;
sin12
=
sin1
*
cos2
+
cos1
*
sin2
;
if
(
sin12
<
0
)
{
if
(
sin12
<
0
)
{
// A neutral case, but the tests above lead to swapping
// A neutral case, but the tests above lead to swapping
return
false
;
return
false
;
}
}
}
}
return
true
;
return
true
;
}
}
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//
//
// x
// x
//" / \ "
//" / \ "
// / | \ Darts:
// / | \ Darts:
//oe2 / | \ oe2 = oppEdge2
//oe2 / | \ oe2 = oppEdge2
// x....|....x
// x....|....x
// \ d| d/ d = diagonal (input and output)
// \ d| d/ d = diagonal (input and output)
// \ | /
// \ | /
// oe1 \ / oe1 = oppEdge1
// oe1 \ / oe1 = oppEdge1
// x
// x
//
//
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
/** Recursively swaps edges in the triangulation according to the \e Delaunay criterion.
/** Recursively swaps edges in the triangulation according to the \e Delaunay criterion.
*
*
* \param aDiagonal
* \param diagonal
* A CCW dart representing the edge where the recursion starts from.
* A CCW dart representing the edge where the recursion starts from.
*
*
* \require
* \require
* - \ref hed::TTLtraits::swapEdge "TraitsType::swapEdge" (DartType
&)\n
* - \ref hed::TTLtraits::swapEdge "TRAITS_TYPE::swapEdge" (DART_TYPE
&)\n
* \b Note: Must be implemented such that the darts outside the quadrilateral
* \b Note: Must be implemented such that the darts outside the quadrilateral
* are not affected by the swap.
* are not affected by the swap.
*
*
* \using
* \using
* - Calls itself recursively
* - Calls itself recursively
*/
*/
template
<
class
TraitsType
,
class
DartType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
>
void
TriangulationHelper
::
recSwapDelaunay
(
DartType
&
diagonal
)
{
void
TRIANGULATION_HELPER
::
RecSwapDelaunay
(
DART_TYPE
&
aDiagonal
)
{
if
(
!
swapTestDelaunay
<
TraitsType
>
(
diagonal
)
)
if
(
!
SwapTestDelaunay
<
TRAITS_TYPE
>
(
aDiagonal
)
)
// ??? swapTestDelaunay also checks if boundary, so this can be optimized
// ??? swapTestDelaunay also checks if boundary, so this can be optimized
return
;
return
;
// Get the other "edges" of the current triangle; see illustration above.
// Get the other "edges" of the current triangle; see illustration above.
D
artType
oppEdge1
=
diagonal
;
D
ART_TYPE
oppEdge1
=
aDiagonal
;
oppEdge1
.
a
lpha1
();
oppEdge1
.
A
lpha1
();
bool
b1
;
bool
b1
;
if
(
isBoundaryEdge
(
oppEdge1
))
if
(
IsBoundaryEdge
(
oppEdge1
)
)
b1
=
true
;
b1
=
true
;
else
{
else
{
b1
=
false
;
b1
=
false
;
oppEdge1
.
a
lpha2
();
oppEdge1
.
A
lpha2
();
}
}
DART_TYPE
oppEdge2
=
aDiagonal
;
DartType
oppEdge2
=
diagonal
;
oppEdge2
.
Alpha0
().
Alpha1
().
Alpha0
();
oppEdge2
.
alpha0
().
alpha1
().
alpha0
();
bool
b2
;
bool
b2
;
if
(
isBoundaryEdge
(
oppEdge2
))
if
(
IsBoundaryEdge
(
oppEdge2
)
)
b2
=
true
;
b2
=
true
;
else
{
else
{
b2
=
false
;
b2
=
false
;
oppEdge2
.
a
lpha2
();
oppEdge2
.
A
lpha2
();
}
}
// Swap the given diagonal
// Swap the given diagonal
triangulation
.
swapEdge
(
diagonal
);
m_triangulation
.
swapEdge
(
aDiagonal
);
if
(
!
b1
)
if
(
!
b1
)
recSwapDelaunay
<
TraitsType
>
(
oppEdge1
);
RecSwapDelaunay
<
TRAITS_TYPE
>
(
oppEdge1
);
if
(
!
b2
)
recSwapDelaunay
<
TraitsType
>
(
oppEdge2
);
}
if
(
!
b2
)
RecSwapDelaunay
<
TRAITS_TYPE
>
(
oppEdge2
);
}
//------------------------------------------------------------------------------------------------
/** Swaps edges away from the (interior) node associated with
/** Swaps edges away from the (interior) node associated with
* \e dart such that that exactly three edges remain incident
* \e dart such that that exactly three edges remain incident
* with the node.
* with the node.
* This function is used as a first step in r
emoveInteriorNode
* This function is used as a first step in R
emoveInteriorNode
*
*
* \retval dart
* \retval dart
* A CCW dart incident with the node
* A CCW dart incident with the node
...
@@ -1698,7 +1702,7 @@ private:
...
@@ -1698,7 +1702,7 @@ private:
* triangulation.
* triangulation.
*
*
* \require
* \require
* - \ref hed::TTLtraits::swapEdge "TraitsType::swapEdge" (DartType
& \e dart)\n
* - \ref hed::TTLtraits::swapEdge "TRAITS_TYPE::swapEdge" (DART_TYPE
& \e dart)\n
* \b Note: Must be implemented such that \e dart is delivered back in a position as
* \b Note: Must be implemented such that \e dart is delivered back in a position as
* seen if it was glued to the edge when swapping (rotating) the edge CCW
* seen if it was glued to the edge when swapping (rotating) the edge CCW
*
*
...
@@ -1708,13 +1712,15 @@ private:
...
@@ -1708,13 +1712,15 @@ private:
* at the node that is given as input.
* at the node that is given as input.
*
*
* \see
* \see
* s
wapEdgesAwayFromBoundaryNode
* S
wapEdgesAwayFromBoundaryNode
*/
*/
template
<
class
TraitsType
,
class
DartType
,
class
ListType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
,
class
LIST_TYPE
>
void
TriangulationHelper
::
swapEdgesAwayFromInteriorNode
(
DartType
&
dart
,
ListType
&
swapped_edges
)
{
void
TRIANGULATION_HELPER
::
SwapEdgesAwayFromInteriorNode
(
DART_TYPE
&
aDart
,
LIST_TYPE
&
aSwappedEdges
)
{
// Same iteration as in fixEdgesAtCorner, but not boundary
// Same iteration as in fixEdgesAtCorner, but not boundary
D
artType
dnext
=
d
art
;
D
ART_TYPE
dnext
=
aD
art
;
// Allow degeneracy, otherwise we might end up with degree=4.
// Allow degeneracy, otherwise we might end up with degree=4.
// For example, the reverse operation of inserting a point on an
// For example, the reverse operation of inserting a point on an
...
@@ -1725,52 +1731,55 @@ private:
...
@@ -1725,52 +1731,55 @@ private:
// infinite loop with degree > 3.
// infinite loop with degree > 3.
bool
allowDegeneracy
=
true
;
bool
allowDegeneracy
=
true
;
int
degree
=
getDegreeOfNode
(
dart
);
int
degree
=
getDegreeOfNode
(
aDart
);
DartType
d_iter
;
DART_TYPE
d_iter
;
while
(
degree
>
3
)
{
while
(
degree
>
3
)
{
d_iter
=
dnext
;
d_iter
=
dnext
;
dnext
.
alpha1
().
a
lpha2
();
dnext
.
Alpha1
().
A
lpha2
();
if
(
swappableEdge
<
TraitsType
>
(
d_iter
,
allowDegeneracy
))
{
if
(
SwappableEdge
<
TRAITS_TYPE
>
(
d_iter
,
allowDegeneracy
)
)
triangulation
.
swapEdge
(
d_iter
);
// swap the edge away
{
m_triangulation
.
swapEdge
(
d_iter
);
// swap the edge away
// Collect swapped edges in the list
// Collect swapped edges in the list
// "Hide" the dart on the other side of the edge to avoid it being changed for
// "Hide" the dart on the other side of the edge to avoid it being changed for
// other swaps
// other swaps
DartType
swapped_edge
=
d_iter
;
// it was delivered back
DART_TYPE
swapped_edge
=
d_iter
;
// it was delivered back
swapped_edge
.
alpha2
().
a
lpha0
();
// CCW (if not at boundary)
swapped_edge
.
Alpha2
().
A
lpha0
();
// CCW (if not at boundary)
swapped_edges
.
push_back
(
swapped_edge
);
aSwappedEdges
.
push_back
(
swapped_edge
);
degree
--
;
degree
--
;
}
}
}
}
// Output, incident to the node
dart
=
dnext
;
}
// Output, incident to the node
aDart
=
dnext
;
}
//------------------------------------------------------------------------------------------------
/** Swaps edges away from the (boundary) node associated with
/** Swaps edges away from the (boundary) node associated with
* \e dart in such a way that when removing the edges that remain incident
* \e dart in such a way that when removing the edges that remain incident
* with the node, the boundary of the triangulation will be convex.
* with the node, the boundary of the triangulation will be convex.
* This function is used as a first step in r
emoveBoundaryNode
* This function is used as a first step in R
emoveBoundaryNode
*
*
* \retval dart
* \retval dart
* A CCW dart incident with the node
* A CCW dart incident with the node
*
*
* \require
* \require
* - \ref hed::TTLtraits::swapEdge "TraitsType::swapEdge" (DartType
& \e dart)\n
* - \ref hed::TTLtraits::swapEdge "TRAITS_TYPE::swapEdge" (DART_TYPE
& \e dart)\n
* \b Note: Must be implemented such that \e dart is delivered back in a position as
* \b Note: Must be implemented such that \e dart is delivered back in a position as
* seen if it was glued to the edge when swapping (rotating) the edge CCW
* seen if it was glued to the edge when swapping (rotating) the edge CCW
*
*
* \par Assumes:
* \par Assumes:
* - The node associated with \e dart is at the boundary of the
triangulation.
* - The node associated with \e dart is at the boundary of the m_
triangulation.
*
*
* \see
* \see
* s
wapEdgesAwayFromInteriorNode
* S
wapEdgesAwayFromInteriorNode
*/
*/
template
<
class
TraitsType
,
class
DartType
,
class
ListType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
,
class
LIST_TYPE
>
void
TriangulationHelper
::
swapEdgesAwayFromBoundaryNode
(
DartType
&
dart
,
ListType
&
swapped_edges
)
{
void
TRIANGULATION_HELPER
::
SwapEdgesAwayFromBoundaryNode
(
DART_TYPE
&
aDart
,
LIST_TYPE
&
aSwappedEdges
)
{
// All darts that are swappable.
// All darts that are swappable.
// To treat collinear nodes at an existing boundary, we must allow degeneracy
// To treat collinear nodes at an existing boundary, we must allow degeneracy
// when swapping to the boundary.
// when swapping to the boundary.
...
@@ -1783,94 +1792,104 @@ private:
...
@@ -1783,94 +1792,104 @@ private:
//int degree = getDegreeOfNode(dart);
//int degree = getDegreeOfNode(dart);
passes
:
passes
:
// Swap swappable edges that radiate from the node away
// Swap swappable edges that radiate from the node away
DartType
d_iter
=
d
art
;
// ???? can simply use dart
DART_TYPE
d_iter
=
aD
art
;
// ???? can simply use dart
d_iter
.
alpha1
().
a
lpha2
();
// first not at boundary
d_iter
.
Alpha1
().
A
lpha2
();
// first not at boundary
DartType
d_next
=
d_iter
;
DART_TYPE
d_next
=
d_iter
;
bool
bend
=
false
;
bool
bend
=
false
;
bool
swapped_next_to_boundary
=
false
;
bool
swapped_next_to_boundary
=
false
;
bool
swapped_in_pass
=
false
;
bool
swapped_in_pass
=
false
;
bool
allowDegeneracy
;
// = true;
bool
allowDegeneracy
;
// = true;
DartType
tmp1
,
tmp2
;
DART_TYPE
tmp1
,
tmp2
;
while
(
!
bend
)
{
while
(
!
bend
)
{
d_next
.
Alpha1
().
Alpha2
();
d_next
.
alpha1
().
alpha2
();
if
(
IsBoundaryEdge
(
d_next
)
)
if
(
isBoundaryEdge
(
d_next
))
bend
=
true
;
// then it is CW since alpha2
bend
=
true
;
// then it is CW since alpha2
// To allow removing among collinear nodes at the boundary,
// To allow removing among collinear nodes at the boundary,
// degenerate triangles must be allowed
// degenerate triangles must be allowed
// (they will be removed when used in connection with removeBoundaryNode)
// (they will be removed when used in connection with RemoveBoundaryNode)
tmp1
=
d_iter
;
tmp1
.
alpha1
();
tmp1
=
d_iter
;
tmp2
=
d_iter
;
tmp2
.
alpha2
().
alpha1
();
// don't bother with boundary (checked later)
tmp1
.
Alpha1
();
tmp2
=
d_iter
;
tmp2
.
Alpha2
().
Alpha1
();
// don't bother with boundary (checked later)
if
(
isBoundaryEdge
(
tmp1
)
&&
isBoundaryEdge
(
tmp2
)
)
if
(
IsBoundaryEdge
(
tmp1
)
&&
IsBoundaryEdge
(
tmp2
)
)
allowDegeneracy
=
true
;
allowDegeneracy
=
true
;
else
else
allowDegeneracy
=
false
;
allowDegeneracy
=
false
;
if
(
swappableEdge
<
TraitsType
>
(
d_iter
,
allowDegeneracy
))
{
if
(
SwappableEdge
<
TRAITS_TYPE
>
(
d_iter
,
allowDegeneracy
)
)
triangulation
.
swapEdge
(
d_iter
);
{
m_triangulation
.
swapEdge
(
d_iter
);
// Collect swapped edges in the list
// Collect swapped edges in the list
// "Hide" the dart on the other side of the edge to avoid it being changed for
// "Hide" the dart on the other side of the edge to avoid it being changed for
// other swapps
// other swapps
DartType
swapped_edge
=
d_iter
;
// it was delivered back
DART_TYPE
swapped_edge
=
d_iter
;
// it was delivered back
swapped_edge
.
alpha2
().
a
lpha0
();
// CCW
swapped_edge
.
Alpha2
().
A
lpha0
();
// CCW
swapped_edges
.
push_back
(
swapped_edge
);
aSwappedEdges
.
push_back
(
swapped_edge
);
//degree--; // if degree is 2, or bend=true, we are done
//degree--; // if degree is 2, or bend=true, we are done
swapped_in_pass
=
true
;
swapped_in_pass
=
true
;
if
(
bend
)
if
(
bend
)
swapped_next_to_boundary
=
true
;
swapped_next_to_boundary
=
true
;
}
}
if
(
!
bend
)
if
(
!
bend
)
d_iter
=
d_next
;
d_iter
=
d_next
;
}
}
// Deliver a dart as output in the same position as the incoming dart
// Deliver a dart as output in the same position as the incoming dart
if
(
swapped_next_to_boundary
)
{
if
(
swapped_next_to_boundary
)
{
// Assume that "swapping is CCW and dart is preserved in the same position
// Assume that "swapping is CCW and dart is preserved in the same position
d_iter
.
alpha1
().
alpha0
().
a
lpha1
();
// CW and see below
d_iter
.
Alpha1
().
Alpha0
().
A
lpha1
();
// CW and see below
}
}
else
{
else
d_iter
.
alpha1
();
// CW and see below
{
d_iter
.
Alpha1
();
// CW and see below
}
}
positionAtNextBoundaryEdge
(
d_iter
);
// CCW
PositionAtNextBoundaryEdge
(
d_iter
);
// CCW
d
art
=
d_iter
;
// for next pass or output
aD
art
=
d_iter
;
// for next pass or output
// If a dart was swapped in this iteration we must run it more
// If a dart was swapped in this iteration we must run it more
if
(
swapped_in_pass
)
if
(
swapped_in_pass
)
goto
passes
;
goto
passes
;
}
}
//------------------------------------------------------------------------------------------------
/** Swap the the edge associated with iterator \e it and update affected darts
/** Swap the the edge associated with iterator \e it and update affected darts
* in \e elist accordingly.
* in \e elist accordingly.
* The darts affected by the swap are those in the same quadrilateral.
* The darts affected by the swap are those in the same quadrilateral.
* Thus, if one want to preserve one or more of these darts on should
* Thus, if one want to preserve one or more of these darts on should
* keep them in \e elist.
* keep them in \e elist.
*/
*/
template
<
class
TraitsType
,
class
DartType
,
class
DartListType
>
template
<
class
TRAITS_TYPE
,
class
DART_TYPE
,
class
DART_LIST_TYPE
>
void
TriangulationHelper
::
swapEdgeInList
(
const
typename
DartListType
::
iterator
&
it
,
DartListType
&
elist
)
{
void
TRIANGULATION_HELPER
::
SwapEdgeInList
(
const
typename
DART_LIST_TYPE
::
iterator
&
aIt
,
DART_LIST_TYPE
&
aElist
)
typename
DartListType
::
iterator
it1
,
it2
,
it3
,
it4
;
{
DartType
dart
(
*
it
);
//typename TraitsType::DartType d1 = dart; d1.alpha2().alpha1();
typename
DART_LIST_TYPE
::
iterator
it1
,
it2
,
it3
,
it4
;
//typename TraitsType::DartType d2 = d1; d2.alpha0().alpha1();
DART_TYPE
dart
(
*
aIt
);
//typename TraitsType::DartType d3 = dart; d3.alpha0().alpha1();
//typename TraitsType::DartType d4 = d3; d4.alpha0().alpha1();
//typename TRAITS_TYPE::DART_TYPE d1 = dart; d1.Alpha2().Alpha1();
DartType
d1
=
dart
;
d1
.
alpha2
().
alpha1
();
//typename TRAITS_TYPE::DART_TYPE d2 = d1; d2.Alpha0().Alpha1();
DartType
d2
=
d1
;
d2
.
alpha0
().
alpha1
();
//typename TRAITS_TYPE::DART_TYPE d3 = dart; d3.Alpha0().Alpha1();
DartType
d3
=
dart
;
d3
.
alpha0
().
alpha1
();
//typename TRAITS_TYPE::DART_TYPE d4 = d3; d4.Alpha0().Alpha1();
DartType
d4
=
d3
;
d4
.
alpha0
().
alpha1
();
DART_TYPE
d1
=
dart
;
d1
.
Alpha2
().
Alpha1
();
DART_TYPE
d2
=
d1
;
d2
.
Alpha0
().
Alpha1
();
DART_TYPE
d3
=
dart
;
d3
.
Alpha0
().
Alpha1
();
DART_TYPE
d4
=
d3
;
d4
.
Alpha0
().
Alpha1
();
// Find pinters to the darts that may change.
// Find pinters to the darts that may change.
// ??? Note, this is not very efficient since we must use find, which is O(N),
// ??? Note, this is not very efficient since we must use find, which is O(N),
...
@@ -1881,37 +1900,49 @@ passes:
...
@@ -1881,37 +1900,49 @@ passes:
// - sould we use another container type or,
// - sould we use another container type or,
// - erase them and reinsert?
// - erase them and reinsert?
// - or use two lists?
// - or use two lists?
it1
=
find
(
elist
.
begin
(),
elist
.
end
(),
d1
);
it1
=
find
(
aElist
.
begin
(),
aElist
.
end
(),
d1
);
it2
=
find
(
elist
.
begin
(),
elist
.
end
(),
d2
);
it2
=
find
(
aElist
.
begin
(),
aElist
.
end
(),
d2
);
it3
=
find
(
elist
.
begin
(),
elist
.
end
(),
d3
);
it3
=
find
(
aElist
.
begin
(),
aElist
.
end
(),
d3
);
it4
=
find
(
elist
.
begin
(),
elist
.
end
(),
d4
);
it4
=
find
(
aElist
.
begin
(),
aElist
.
end
(),
d4
);
triangulation
.
swapEdge
(
dart
);
m_triangulation
.
swapEdge
(
dart
);
// Update the current dart which may have changed
// Update the current dart which may have changed
*
i
t
=
dart
;
*
aI
t
=
dart
;
// Update darts that may have changed again (if they were present)
// Update darts that may have changed again (if they were present)
// Note that dart is delivered back after swapping
// Note that dart is delivered back after swapping
if
(
it1
!=
elist
.
end
())
{
if
(
it1
!=
aElist
.
end
()
)
d1
=
dart
;
d1
.
alpha1
().
alpha0
();
{
d1
=
dart
;
d1
.
Alpha1
().
Alpha0
();
*
it1
=
d1
;
*
it1
=
d1
;
}
}
if
(
it2
!=
elist
.
end
())
{
d2
=
dart
;
d2
.
alpha2
().
alpha1
();
if
(
it2
!=
aElist
.
end
()
)
{
d2
=
dart
;
d2
.
Alpha2
().
Alpha1
();
*
it2
=
d2
;
*
it2
=
d2
;
}
}
if
(
it3
!=
elist
.
end
())
{
d3
=
dart
;
d3
.
alpha2
().
alpha1
().
alpha0
().
alpha1
();
if
(
it3
!=
aElist
.
end
()
)
{
d3
=
dart
;
d3
.
Alpha2
().
Alpha1
().
Alpha0
().
Alpha1
();
*
it3
=
d3
;
*
it3
=
d3
;
}
}
if
(
it4
!=
elist
.
end
())
{
d4
=
dart
;
d4
.
alpha0
().
alpha1
();
if
(
it4
!=
aElist
.
end
()
)
{
d4
=
dart
;
d4
.
Alpha0
().
Alpha1
();
*
it4
=
d4
;
*
it4
=
d4
;
}
}
}
}
//@} // End of Utilities for Delaunay Triangulation Group
//@} // End of Utilities for Delaunay Triangulation Group
};
// End of ttl namespace scope (but other files may also contain functions for ttl)
}
// End of ttl namespace scope (but other files may also contain functions for ttl)
#endif // _TTL_H_
#endif // _TTL_H_
include/ttl/ttl_util.h
View file @
6fa2f060
...
@@ -3,11 +3,11 @@
...
@@ -3,11 +3,11 @@
* Applied Mathematics, Norway.
* Applied Mathematics, Norway.
*
*
* Contact information: E-mail: tor.dokken@sintef.no
* Contact information: E-mail: tor.dokken@sintef.no
* SINTEF ICT, De
partment of Applied Mathematics,
* SINTEF ICT, De
aPArtment of Applied Mathematics,
* P.O. Box 124 Blindern,
* P.O. Box 124 Blindern,
* 0314 Oslo, Norway.
* 0314 Oslo, Norway.
*
*
* This file is
pa
rt of TTL.
* This file is
aPA
rt of TTL.
*
*
* TTL is free software: you can redistribute it and/or modify
* TTL is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* it under the terms of the GNU Affero General Public License as
...
@@ -16,7 +16,7 @@
...
@@ -16,7 +16,7 @@
*
*
* TTL is distributed in the hope that it will be useful,
* TTL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A
aPARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* GNU Affero General Public License for more details.
*
*
* You should have received a copy of the GNU Affero General Public
* You should have received a copy of the GNU Affero General Public
...
@@ -40,28 +40,22 @@
...
@@ -40,28 +40,22 @@
#ifndef _TTL_UTIL_H_
#ifndef _TTL_UTIL_H_
#define _TTL_UTIL_H_
#define _TTL_UTIL_H_
#include <vector>
#include <vector>
#include <algorithm>
#include <algorithm>
#ifdef _MSC_VER
#ifdef _MSC_VER
# if _MSC_VER < 1300
# if _MSC_VER < 1300
# include <minmax.h>
# include <minmax.h>
# endif
# endif
#endif
#endif
//using namespace std;
/** \brief Utilities
/** \brief Utilities
*
*
* This name s
pa
ce contains utility functions for TTL.\n
* This name s
aPA
ce contains utility functions for TTL.\n
*
*
* Point and vector algebra such as scalar product and cross product
* Point and vector algebra such as scalar product and cross product
* between vectors are implemented here.
* between vectors are implemented here.
* These functions are required by functions in the \ref ttl names
pa
ce,
* These functions are required by functions in the \ref ttl names
aPA
ce,
* where they are assumed to be present in the \ref hed::TTLtraits "TTLtraits" class.
* where they are assumed to be present in the \ref hed::TTLtraits "TTLtraits" class.
* Thus, the user can call these functions from the traits class.
* Thus, the user can call these functions from the traits class.
* For efficiency reasons, the user may consider implementing these
* For efficiency reasons, the user may consider implementing these
...
@@ -77,51 +71,41 @@
...
@@ -77,51 +71,41 @@
* ttl and \ref api
* ttl and \ref api
*
*
* \author
* \author
* Øyvind Hjelle, oyvindhj@ifi.uio.no
*
�
yvind Hjelle, oyvindhj@ifi.uio.no
*/
*/
namespace
ttl_util
namespace
ttl_util
{
{
/** @name Computational geometry */
//@{
//------------------------------------------------------------------------------------------------
/** Scalar product between two 2D vectors.
// ------------------------------ Computational Geometry Group ----------------------------------
//------------------------------------------------------------------------------------------------
/** @name Computational geometry */
//@{
//------------------------------------------------------------------------------------------------
/** Scalar product between two 2D vectors.
*
*
* \pa
r Returns:
* \aPA
r Returns:
* \code
* \code
* dx1*dx2 + dy1*dy
2
* aDX1*aDX2 + aDY1*aDY
2
* \endcode
* \endcode
*/
*/
template
<
class
real_type
>
template
<
class
REAL_TYPE
>
real_type
scalarProduct2d
(
real_type
dx1
,
real_type
dy1
,
real_type
dx2
,
real_type
dy2
)
{
REAL_TYPE
ScalarProduct2D
(
REAL_TYPE
aDX1
,
REAL_TYPE
aDY1
,
REAL_TYPE
aDX2
,
REAL_TYPE
aDY2
)
return
dx1
*
dx2
+
dy1
*
dy2
;
{
}
return
aDX1
*
aDX2
+
aDY1
*
aDY2
;
}
//------------------------------------------------------------------------------------------------
/** Cross product between two 2D vectors. (The z-component of the actual cross product.)
/** Cross product between two 2D vectors. (The z-component of the actual cross product.)
*
*
* \pa
r Returns:
* \aPA
r Returns:
* \code
* \code
* dx1*dy2 - dy1*dx
2
* aDX1*aDY2 - aDY1*aDX
2
* \endcode
* \endcode
*/
*/
template
<
class
real_type
>
template
<
class
REAL_TYPE
>
real_type
crossProduct2d
(
real_type
dx1
,
real_type
dy1
,
real_type
dx2
,
real_type
dy2
)
{
REAL_TYPE
CrossProduct2D
(
REAL_TYPE
aDX1
,
REAL_TYPE
aDY1
,
REAL_TYPE
aDX2
,
REAL_TYPE
aDY2
)
return
dx1
*
dy2
-
dy1
*
dx2
;
{
}
return
aDX1
*
aDY2
-
aDY1
*
aDX2
;
}
//------------------------------------------------------------------------------------------------
/** Returns a positive value if the 2D nodes/points \e aPA, \e aPB, and
/** Returns a positive value if the 2D nodes/points \e pa, \e pb, and
* \e aPC occur in counterclockwise order; a negative value if they occur
* \e pc occur in counterclockwise order; a negative value if they occur
* in clockwise order; and zero if they are collinear.
* in clockwise order; and zero if they are collinear.
*
*
* \note
* \note
...
@@ -129,15 +113,17 @@ namespace ttl_util {
...
@@ -129,15 +113,17 @@ namespace ttl_util {
* exact arithmetic schemes by Jonathan Richard Shewchuk. See
* exact arithmetic schemes by Jonathan Richard Shewchuk. See
* http://www-2.cs.cmu.edu/~quake/robust.html
* http://www-2.cs.cmu.edu/~quake/robust.html
*/
*/
template
<
class
real_type
>
template
<
class
REAL_TYPE
>
real_type
orient2dfast
(
real_type
pa
[
2
],
real_type
pb
[
2
],
real_type
pc
[
2
])
{
REAL_TYPE
Orient2DFast
(
REAL_TYPE
aPA
[
2
],
REAL_TYPE
aPB
[
2
],
REAL_TYPE
aPC
[
2
]
)
real_type
acx
=
pa
[
0
]
-
pc
[
0
];
{
real_type
bcx
=
pb
[
0
]
-
pc
[
0
];
REAL_TYPE
acx
=
aPA
[
0
]
-
aPC
[
0
];
real_type
acy
=
pa
[
1
]
-
pc
[
1
];
REAL_TYPE
bcx
=
aPB
[
0
]
-
aPC
[
0
];
real_type
bcy
=
pb
[
1
]
-
pc
[
1
];
REAL_TYPE
acy
=
aPA
[
1
]
-
aPC
[
1
];
REAL_TYPE
bcy
=
aPB
[
1
]
-
aPC
[
1
];
return
acx
*
bcy
-
acy
*
bcx
;
return
acx
*
bcy
-
acy
*
bcx
;
}
}
}
;
// End of ttl_util namespace scope
}
// namespace ttl_util
#endif // _TTL_UTIL_H_
#endif // _TTL_UTIL_H_
pcbnew/ratsnest_data.cpp
View file @
6fa2f060
...
@@ -68,7 +68,7 @@ bool sortDistance( const RN_NODE_PTR& aOrigin, const RN_NODE_PTR& aNode1,
...
@@ -68,7 +68,7 @@ bool sortDistance( const RN_NODE_PTR& aOrigin, const RN_NODE_PTR& aNode1,
bool
sortWeight
(
const
RN_EDGE_PTR
&
aEdge1
,
const
RN_EDGE_PTR
&
aEdge2
)
bool
sortWeight
(
const
RN_EDGE_PTR
&
aEdge1
,
const
RN_EDGE_PTR
&
aEdge2
)
{
{
return
aEdge1
->
getWeight
()
<
aEdge2
->
g
etWeight
();
return
aEdge1
->
GetWeight
()
<
aEdge2
->
G
etWeight
();
}
}
...
@@ -92,7 +92,7 @@ bool operator!=( const RN_NODE_PTR& aFirst, const RN_NODE_PTR& aSecond )
...
@@ -92,7 +92,7 @@ bool operator!=( const RN_NODE_PTR& aFirst, const RN_NODE_PTR& aSecond )
bool
isEdgeConnectingNode
(
const
RN_EDGE_PTR
&
aEdge
,
const
RN_NODE_PTR
&
aNode
)
bool
isEdgeConnectingNode
(
const
RN_EDGE_PTR
&
aEdge
,
const
RN_NODE_PTR
&
aNode
)
{
{
return
aEdge
->
getSourceNode
()
==
aNode
||
aEdge
->
g
etTargetNode
()
==
aNode
;
return
aEdge
->
GetSourceNode
()
==
aNode
||
aEdge
->
G
etTargetNode
()
==
aNode
;
}
}
...
@@ -125,8 +125,8 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
...
@@ -125,8 +125,8 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
{
{
RN_EDGE_PTR
&
dt
=
*
aEdges
.
begin
();
RN_EDGE_PTR
&
dt
=
*
aEdges
.
begin
();
int
srcTag
=
tags
[
dt
->
g
etSourceNode
()];
int
srcTag
=
tags
[
dt
->
G
etSourceNode
()];
int
trgTag
=
tags
[
dt
->
g
etTargetNode
()];
int
trgTag
=
tags
[
dt
->
G
etTargetNode
()];
// Check if by adding this edge we are going to join two different forests
// Check if by adding this edge we are going to join two different forests
if
(
srcTag
!=
trgTag
)
if
(
srcTag
!=
trgTag
)
...
@@ -139,7 +139,7 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
...
@@ -139,7 +139,7 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
// Move nodes that were marked with old tag to the list marked with the new tag
// Move nodes that were marked with old tag to the list marked with the new tag
cycles
[
srcTag
].
splice
(
cycles
[
srcTag
].
end
(),
cycles
[
trgTag
]
);
cycles
[
srcTag
].
splice
(
cycles
[
srcTag
].
end
(),
cycles
[
trgTag
]
);
if
(
dt
->
g
etWeight
()
==
0
)
// Skip already existing connections (weight == 0)
if
(
dt
->
G
etWeight
()
==
0
)
// Skip already existing connections (weight == 0)
{
{
mstExpectedSize
--
;
mstExpectedSize
--
;
}
}
...
@@ -148,9 +148,9 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
...
@@ -148,9 +148,9 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
// Do a copy of edge, but make it RN_EDGE_MST. In contrary to RN_EDGE,
// Do a copy of edge, but make it RN_EDGE_MST. In contrary to RN_EDGE,
// RN_EDGE_MST saves both source and target node and does not require any other
// RN_EDGE_MST saves both source and target node and does not require any other
// edges to exist for getting source/target nodes
// edges to exist for getting source/target nodes
RN_EDGE_MST_PTR
newEdge
=
boost
::
make_shared
<
RN_EDGE_MST
>
(
dt
->
g
etSourceNode
(),
RN_EDGE_MST_PTR
newEdge
=
boost
::
make_shared
<
RN_EDGE_MST
>
(
dt
->
G
etSourceNode
(),
dt
->
g
etTargetNode
(),
dt
->
G
etTargetNode
(),
dt
->
g
etWeight
()
);
dt
->
G
etWeight
()
);
mst
->
push_back
(
newEdge
);
mst
->
push_back
(
newEdge
);
++
mstSize
;
++
mstSize
;
}
}
...
@@ -169,8 +169,8 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
...
@@ -169,8 +169,8 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
void
RN_NET
::
validateEdge
(
RN_EDGE_PTR
&
aEdge
)
void
RN_NET
::
validateEdge
(
RN_EDGE_PTR
&
aEdge
)
{
{
RN_NODE_PTR
source
=
aEdge
->
g
etSourceNode
();
RN_NODE_PTR
source
=
aEdge
->
G
etSourceNode
();
RN_NODE_PTR
target
=
aEdge
->
g
etTargetNode
();
RN_NODE_PTR
target
=
aEdge
->
G
etTargetNode
();
bool
valid
=
true
;
bool
valid
=
true
;
// If any of nodes belonging to the edge has the flag set,
// If any of nodes belonging to the edge has the flag set,
...
@@ -280,13 +280,13 @@ void RN_NET::compute()
...
@@ -280,13 +280,13 @@ void RN_NET::compute()
std
::
partial_sort_copy
(
boardNodes
.
begin
(),
boardNodes
.
end
(),
nodes
.
begin
(),
nodes
.
end
()
);
std
::
partial_sort_copy
(
boardNodes
.
begin
(),
boardNodes
.
end
(),
nodes
.
begin
(),
nodes
.
end
()
);
TRIANGULATOR
triangulator
;
TRIANGULATOR
triangulator
;
triangulator
.
c
reateDelaunay
(
nodes
.
begin
(),
nodes
.
end
()
);
triangulator
.
C
reateDelaunay
(
nodes
.
begin
(),
nodes
.
end
()
);
boost
::
scoped_ptr
<
RN_LINKS
::
RN_EDGE_LIST
>
triangEdges
(
triangulator
.
g
etEdges
()
);
boost
::
scoped_ptr
<
RN_LINKS
::
RN_EDGE_LIST
>
triangEdges
(
triangulator
.
G
etEdges
()
);
// Compute weight/distance for edges resulting from triangulation
// Compute weight/distance for edges resulting from triangulation
RN_LINKS
::
RN_EDGE_LIST
::
iterator
eit
,
eitEnd
;
RN_LINKS
::
RN_EDGE_LIST
::
iterator
eit
,
eitEnd
;
for
(
eit
=
(
*
triangEdges
).
begin
(),
eitEnd
=
(
*
triangEdges
).
end
();
eit
!=
eitEnd
;
++
eit
)
for
(
eit
=
(
*
triangEdges
).
begin
(),
eitEnd
=
(
*
triangEdges
).
end
();
eit
!=
eitEnd
;
++
eit
)
(
*
eit
)
->
setWeight
(
getDistance
(
(
*
eit
)
->
getSourceNode
(),
(
*
eit
)
->
g
etTargetNode
()
)
);
(
*
eit
)
->
SetWeight
(
getDistance
(
(
*
eit
)
->
GetSourceNode
(),
(
*
eit
)
->
G
etTargetNode
()
)
);
// Add the currently existing connections list to the results of triangulation
// Add the currently existing connections list to the results of triangulation
std
::
copy
(
boardEdges
.
begin
(),
boardEdges
.
end
(),
std
::
front_inserter
(
*
triangEdges
)
);
std
::
copy
(
boardEdges
.
begin
(),
boardEdges
.
end
(),
std
::
front_inserter
(
*
triangEdges
)
);
...
@@ -508,8 +508,8 @@ void RN_NET::RemoveItem( const TRACK* aTrack )
...
@@ -508,8 +508,8 @@ void RN_NET::RemoveItem( const TRACK* aTrack )
RN_EDGE_PTR
&
edge
=
m_tracks
.
at
(
aTrack
);
RN_EDGE_PTR
&
edge
=
m_tracks
.
at
(
aTrack
);
// Save nodes, so they can be cleared later
// Save nodes, so they can be cleared later
RN_NODE_PTR
aBegin
=
edge
->
g
etSourceNode
();
RN_NODE_PTR
aBegin
=
edge
->
G
etSourceNode
();
RN_NODE_PTR
aEnd
=
edge
->
g
etTargetNode
();
RN_NODE_PTR
aEnd
=
edge
->
G
etTargetNode
();
m_links
.
RemoveConnection
(
edge
);
m_links
.
RemoveConnection
(
edge
);
// Remove nodes associated with the edge. It is done in a safe way, there is a check
// Remove nodes associated with the edge. It is done in a safe way, there is a check
...
@@ -696,8 +696,8 @@ std::list<RN_NODE_PTR> RN_NET::GetNodes( const BOARD_CONNECTED_ITEM* aItem ) con
...
@@ -696,8 +696,8 @@ std::list<RN_NODE_PTR> RN_NET::GetNodes( const BOARD_CONNECTED_ITEM* aItem ) con
const
TRACK
*
track
=
static_cast
<
const
TRACK
*>
(
aItem
);
const
TRACK
*
track
=
static_cast
<
const
TRACK
*>
(
aItem
);
RN_EDGE_PTR
edge
=
m_tracks
.
at
(
track
);
RN_EDGE_PTR
edge
=
m_tracks
.
at
(
track
);
nodes
.
push_back
(
edge
->
g
etSourceNode
()
);
nodes
.
push_back
(
edge
->
G
etSourceNode
()
);
nodes
.
push_back
(
edge
->
g
etTargetNode
()
);
nodes
.
push_back
(
edge
->
G
etTargetNode
()
);
}
}
break
;
break
;
...
...
pcbnew/ratsnest_data.h
View file @
6fa2f060
...
@@ -50,13 +50,13 @@ class ZONE_CONTAINER;
...
@@ -50,13 +50,13 @@ class ZONE_CONTAINER;
class
CPolyPt
;
class
CPolyPt
;
// Preserve KiCad coding style policy
// Preserve KiCad coding style policy
typedef
hed
::
N
ode
RN_NODE
;
typedef
hed
::
N
ODE
RN_NODE
;
typedef
hed
::
N
odePtr
RN_NODE_PTR
;
typedef
hed
::
N
ODE_PTR
RN_NODE_PTR
;
typedef
hed
::
E
dge
RN_EDGE
;
typedef
hed
::
E
DGE
RN_EDGE
;
typedef
hed
::
E
dgePtr
RN_EDGE_PTR
;
typedef
hed
::
E
DGE_PTR
RN_EDGE_PTR
;
typedef
hed
::
E
dgeMST
RN_EDGE_MST
;
typedef
hed
::
E
DGE_MST
RN_EDGE_MST
;
typedef
boost
::
shared_ptr
<
hed
::
EdgeMST
>
RN_EDGE_MST_PT
R
;
typedef
hed
::
TRIANGULATION
TRIANGULATO
R
;
typedef
hed
::
Triangulation
TRIANGULATO
R
;
typedef
boost
::
shared_ptr
<
hed
::
EDGE_MST
>
RN_EDGE_MST_PT
R
;
bool
operator
==
(
const
RN_NODE_PTR
&
aFirst
,
const
RN_NODE_PTR
&
aSecond
);
bool
operator
==
(
const
RN_NODE_PTR
&
aFirst
,
const
RN_NODE_PTR
&
aSecond
);
bool
operator
!=
(
const
RN_NODE_PTR
&
aFirst
,
const
RN_NODE_PTR
&
aSecond
);
bool
operator
!=
(
const
RN_NODE_PTR
&
aFirst
,
const
RN_NODE_PTR
&
aSecond
);
...
...
pcbnew/ratsnest_viewitem.cpp
View file @
6fa2f060
...
@@ -97,8 +97,8 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const
...
@@ -97,8 +97,8 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const
BOOST_FOREACH
(
const
RN_EDGE_PTR
&
edge
,
*
edges
)
BOOST_FOREACH
(
const
RN_EDGE_PTR
&
edge
,
*
edges
)
{
{
const
RN_NODE_PTR
&
sourceNode
=
edge
->
g
etSourceNode
();
const
RN_NODE_PTR
&
sourceNode
=
edge
->
G
etSourceNode
();
const
RN_NODE_PTR
&
targetNode
=
edge
->
g
etTargetNode
();
const
RN_NODE_PTR
&
targetNode
=
edge
->
G
etTargetNode
();
VECTOR2D
source
(
sourceNode
->
GetX
(),
sourceNode
->
GetY
()
);
VECTOR2D
source
(
sourceNode
->
GetX
(),
sourceNode
->
GetY
()
);
VECTOR2D
target
(
targetNode
->
GetX
(),
targetNode
->
GetY
()
);
VECTOR2D
target
(
targetNode
->
GetX
(),
targetNode
->
GetY
()
);
...
...
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