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
Hide 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,685 +48,681 @@
#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>
using
namespace
hed
;
using
namespace
std
;
#ifdef TTL_USE_NODE_ID
int
N
ode
::
id_count
=
0
;
int
N
ODE
::
id_count
=
0
;
#endif
//#define DEBUG_HE
#ifdef DEBUG_HE
#include <iostream>
static
void
errorAndExit
(
char
*
message
)
{
cout
<<
"
\n
!!! ERROR: "
<<
message
<<
" !!!
\n
"
<<
endl
;
exit
(
-
1
);
}
static
void
errorAndExit
(
char
*
aMessage
)
{
cout
<<
"
\n
!!! ERROR: "
<<
aMessage
<<
" !!!
\n
"
<<
endl
;
exit
(
-
1
);
}
#endif
//--------------------------------------------------------------------------------------------------
static
EdgePtr
getLeadingEdgeInTriangle
(
const
EdgePtr
&
e
)
{
EdgePtr
edge
=
e
;
// Code: 3EF (assumes triangle)
if
(
!
edge
->
isLeadingEdge
())
{
edge
=
edge
->
getNextEdgeInFace
();
if
(
!
edge
->
isLeadingEdge
())
edge
=
edge
->
getNextEdgeInFace
();
}
if
(
!
edge
->
isLeadingEdge
())
{
return
EdgePtr
();
}
return
edge
;
static
EDGE_PTR
getLeadingEdgeInTriangle
(
const
EDGE_PTR
&
aEdge
)
{
EDGE_PTR
edge
=
aEdge
;
// Code: 3EF (assumes triangle)
if
(
!
edge
->
IsLeadingEdge
()
)
{
edge
=
edge
->
GetNextEdgeInFace
();
if
(
!
edge
->
IsLeadingEdge
()
)
edge
=
edge
->
GetNextEdgeInFace
();
}
if
(
!
edge
->
IsLeadingEdge
()
)
{
return
EDGE_PTR
();
}
return
edge
;
}
//--------------------------------------------------------------------------------------------------
static
void
getLimits
(
NodesContainer
::
iterator
first
,
NodesContainer
::
iterator
last
,
int
&
xmin
,
int
&
ymin
,
int
&
xmax
,
int
&
ymax
)
{
xmin
=
ymin
=
std
::
numeric_limits
<
int
>::
min
();
xmax
=
ymax
=
std
::
numeric_limits
<
int
>::
max
();
NodesContainer
::
iterator
it
;
for
(
it
=
first
;
it
!=
last
;
++
it
)
{
xmin
=
min
(
xmin
,
(
*
it
)
->
GetX
());
ymin
=
min
(
ymin
,
(
*
it
)
->
GetY
());
xmax
=
max
(
xmax
,
(
*
it
)
->
GetX
());
ymax
=
max
(
ymax
,
(
*
it
)
->
GetY
());
}
static
void
getLimits
(
NODES_CONTAINER
::
iterator
aFirst
,
NODES_CONTAINER
::
iterator
aLast
,
int
&
aXmin
,
int
&
aYmin
,
int
&
aXmax
,
int
&
aYmax
)
{
aXmin
=
aYmin
=
std
::
numeric_limits
<
int
>::
min
();
aXmax
=
aYmax
=
std
::
numeric_limits
<
int
>::
max
();
NODES_CONTAINER
::
iterator
it
;
for
(
it
=
aFirst
;
it
!=
aLast
;
++
it
)
{
aXmin
=
std
::
min
(
aXmin
,
(
*
it
)
->
GetX
()
);
aYmin
=
std
::
min
(
aYmin
,
(
*
it
)
->
GetY
()
);
aXmax
=
std
::
max
(
aXmax
,
(
*
it
)
->
GetX
()
);
aYmax
=
std
::
max
(
aYmax
,
(
*
it
)
->
GetY
()
);
}
}
//--------------------------------------------------------------------------------------------------
EdgePtr
Triangulation
::
initTwoEnclosingTriangles
(
NodesContainer
::
iterator
first
,
NodesContainer
::
iterator
last
)
{
int
xmin
,
ymin
,
xmax
,
ymax
;
getLimits
(
first
,
last
,
xmin
,
ymin
,
xmax
,
ymax
);
// Add 10% of range:
double
fac
=
10.0
;
double
dx
=
(
xmax
-
xmin
)
/
fac
;
double
dy
=
(
ymax
-
ymin
)
/
fac
;
NodePtr
n1
=
boost
::
make_shared
<
Node
>
(
xmin
-
dx
,
ymin
-
dy
);
NodePtr
n2
=
boost
::
make_shared
<
Node
>
(
xmax
+
dx
,
ymin
-
dy
);
NodePtr
n3
=
boost
::
make_shared
<
Node
>
(
xmax
+
dx
,
ymax
+
dy
);
NodePtr
n4
=
boost
::
make_shared
<
Node
>
(
xmin
-
dx
,
ymax
+
dy
);
// diagonal
EdgePtr
e1d
=
boost
::
make_shared
<
Edge
>
();
EdgePtr
e2d
=
boost
::
make_shared
<
Edge
>
();
// lower triangle
EdgePtr
e11
=
boost
::
make_shared
<
Edge
>
();
EdgePtr
e12
=
boost
::
make_shared
<
Edge
>
();
// upper triangle
EdgePtr
e21
=
boost
::
make_shared
<
Edge
>
();
EdgePtr
e22
=
boost
::
make_shared
<
Edge
>
();
// lower triangle
e1d
->
setSourceNode
(
n3
);
e1d
->
setNextEdgeInFace
(
e11
);
e1d
->
setTwinEdge
(
e2d
);
addLeadingEdge
(
e1d
);
e11
->
setSourceNode
(
n1
);
e11
->
setNextEdgeInFace
(
e12
);
e12
->
setSourceNode
(
n2
);
e12
->
setNextEdgeInFace
(
e1d
);
// upper triangle
e2d
->
setSourceNode
(
n1
);
e2d
->
setNextEdgeInFace
(
e21
);
e2d
->
setTwinEdge
(
e1d
);
addLeadingEdge
(
e2d
);
e21
->
setSourceNode
(
n3
);
e21
->
setNextEdgeInFace
(
e22
);
e22
->
setSourceNode
(
n4
);
e22
->
setNextEdgeInFace
(
e2d
);
return
e11
;
EDGE_PTR
TRIANGULATION
::
InitTwoEnclosingTriangles
(
NODES_CONTAINER
::
iterator
aFirst
,
NODES_CONTAINER
::
iterator
aLast
)
{
int
xmin
,
ymin
,
xmax
,
ymax
;
getLimits
(
aFirst
,
aLast
,
xmin
,
ymin
,
xmax
,
ymax
);
// Add 10% of range:
double
fac
=
10.0
;
double
dx
=
(
xmax
-
xmin
)
/
fac
;
double
dy
=
(
ymax
-
ymin
)
/
fac
;
NODE_PTR
n1
=
boost
::
make_shared
<
NODE
>
(
xmin
-
dx
,
ymin
-
dy
);
NODE_PTR
n2
=
boost
::
make_shared
<
NODE
>
(
xmax
+
dx
,
ymin
-
dy
);
NODE_PTR
n3
=
boost
::
make_shared
<
NODE
>
(
xmax
+
dx
,
ymax
+
dy
);
NODE_PTR
n4
=
boost
::
make_shared
<
NODE
>
(
xmin
-
dx
,
ymax
+
dy
);
// diagonal
EDGE_PTR
e1d
=
boost
::
make_shared
<
EDGE
>
();
EDGE_PTR
e2d
=
boost
::
make_shared
<
EDGE
>
();
// lower triangle
EDGE_PTR
e11
=
boost
::
make_shared
<
EDGE
>
();
EDGE_PTR
e12
=
boost
::
make_shared
<
EDGE
>
();
// upper triangle
EDGE_PTR
e21
=
boost
::
make_shared
<
EDGE
>
();
EDGE_PTR
e22
=
boost
::
make_shared
<
EDGE
>
();
// lower triangle
e1d
->
SetSourceNode
(
n3
);
e1d
->
SetNextEdgeInFace
(
e11
);
e1d
->
SetTwinEdge
(
e2d
);
addLeadingEdge
(
e1d
);
e11
->
SetSourceNode
(
n1
);
e11
->
SetNextEdgeInFace
(
e12
);
e12
->
SetSourceNode
(
n2
);
e12
->
SetNextEdgeInFace
(
e1d
);
// upper triangle
e2d
->
SetSourceNode
(
n1
);
e2d
->
SetNextEdgeInFace
(
e21
);
e2d
->
SetTwinEdge
(
e1d
);
addLeadingEdge
(
e2d
);
e21
->
SetSourceNode
(
n3
);
e21
->
SetNextEdgeInFace
(
e22
);
e22
->
SetSourceNode
(
n4
);
e22
->
SetNextEdgeInFace
(
e2d
);
return
e11
;
}
//--------------------------------------------------------------------------------------------------
Triangulation
::
Triangulation
()
{
helper
=
new
ttl
::
TriangulationHelper
(
*
this
);
TRIANGULATION
::
TRIANGULATION
()
{
m_helper
=
new
ttl
::
TRIANGULATION_HELPER
(
*
this
);
}
//--------------------------------------------------------------------------------------------------
Triangulation
::
Triangulation
(
const
Triangulation
&
tr
)
{
std
::
cout
<<
"Triangulation: Copy constructor not present - EXIT."
;
exit
(
-
1
);
TRIANGULATION
::
TRIANGULATION
(
const
TRIANGULATION
&
aTriangulation
)
{
// Triangulation: Copy constructor not present
assert
(
false
);
}
//--------------------------------------------------------------------------------------------------
Triangulation
::~
Triangulation
()
{
cleanAll
();
delete
helper
;
TRIANGULATION
::~
TRIANGULATION
()
{
cleanAll
();
delete
m_
helper
;
}
//--------------------------------------------------------------------------------------------------
void
Triangulation
::
createDelaunay
(
NodesContainer
::
iterator
first
,
NodesContainer
::
iterator
last
)
{
cleanAll
();
EdgePtr
bedge
=
initTwoEnclosingTriangles
(
first
,
last
);
Dart
dc
(
bedge
);
Dart
d_iter
=
dc
;
NodesContainer
::
iterator
it
;
for
(
it
=
first
;
it
!=
last
;
++
it
)
{
helper
->
insertNode
<
TTLtraits
>
(
d_iter
,
*
it
);
}
// In general (e.g. for the triangle based data structure), the initial dart
// may have been changed.
// It is the users responsibility to get a valid boundary dart here.
// The half-edge data structure preserves the initial dart.
// (A dart at the boundary can also be found by trying to locate a
// triangle "outside" the triangulation.)
// Assumes rectangular domain
helper
->
removeRectangularBoundary
<
TTLtraits
>
(
dc
);
void
TRIANGULATION
::
CreateDelaunay
(
NODES_CONTAINER
::
iterator
aFirst
,
NODES_CONTAINER
::
iterator
aLast
)
{
cleanAll
();
EDGE_PTR
bedge
=
InitTwoEnclosingTriangles
(
aFirst
,
aLast
);
DART
dc
(
bedge
);
DART
d_iter
=
dc
;
NODES_CONTAINER
::
iterator
it
;
for
(
it
=
aFirst
;
it
!=
aLast
;
++
it
)
{
m_helper
->
InsertNode
<
TTLtraits
>
(
d_iter
,
*
it
);
}
// In general (e.g. for the triangle based data structure), the initial dart
// may have been changed.
// It is the users responsibility to get a valid boundary dart here.
// The half-edge data structure preserves the initial dart.
// (A dart at the boundary can also be found by trying to locate a
// triangle "outside" the triangulation.)
// Assumes rectangular domain
m_helper
->
RemoveRectangularBoundary
<
TTLtraits
>
(
dc
);
}
//--------------------------------------------------------------------------------------------------
void
Triangulation
::
removeTriangle
(
EdgePtr
&
edge
)
{
EdgePtr
e1
=
getLeadingEdgeInTriangle
(
edge
);
void
TRIANGULATION
::
RemoveTriangle
(
EDGE_PTR
&
aEdge
)
{
EDGE_PTR
e1
=
getLeadingEdgeInTriangle
(
aEdge
);
#ifdef DEBUG_HE
if
(
!
e1
)
errorAndExit
(
"Triangulation::removeTriangle: could not find leading edge"
);
if
(
!
e1
)
errorAndExit
(
"Triangulation::removeTriangle: could not find leading aEdge"
);
#endif
removeLeadingEdgeFromList
(
e1
);
// cout << "No leading edges = " << leadingEdges_.size() << endl;
// Remove the triangle
EdgePtr
e2
(
e1
->
getNextEdgeInFace
()
);
EdgePtr
e3
(
e2
->
getNextEdgeInFace
()
);
e1
->
c
lear
();
e2
->
c
lear
();
e3
->
c
lear
();
removeLeadingEdgeFromList
(
e1
);
// cout << "No leading edges = " << leadingEdges_.size() << endl;
// Remove the triangle
EDGE_PTR
e2
(
e1
->
GetNextEdgeInFace
()
);
EDGE_PTR
e3
(
e2
->
GetNextEdgeInFace
()
);
e1
->
C
lear
();
e2
->
C
lear
();
e3
->
C
lear
();
}
//--------------------------------------------------------------------------------------------------
void
Triangulation
::
reverse_splitTriangle
(
EdgePtr
&
edge
)
{
// Reverse operation of splitTriangle
EdgePtr
e1
(
edge
->
getNextEdgeInFace
());
EdgePtr
le
(
getLeadingEdgeInTriangle
(
e1
));
void
TRIANGULATION
::
ReverseSplitTriangle
(
EDGE_PTR
&
aEdge
)
{
// Reverse operation of splitTriangle
EDGE_PTR
e1
(
aEdge
->
GetNextEdgeInFace
()
);
EDGE_PTR
le
(
getLeadingEdgeInTriangle
(
e1
)
);
#ifdef DEBUG_HE
if
(
!
le
)
if
(
!
le
)
errorAndExit
(
"Triangulation::removeTriangle: could not find leading edge"
);
#endif
removeLeadingEdgeFromList
(
le
);
EdgePtr
e2
(
e1
->
getNextEdgeInFace
()
->
getTwinEdge
()
->
getNextEdgeInFace
()
);
le
=
getLeadingEdgeInTriangle
(
e2
);
removeLeadingEdgeFromList
(
le
);
EDGE_PTR
e2
(
e1
->
GetNextEdgeInFace
()
->
GetTwinEdge
()
->
GetNextEdgeInFace
()
);
le
=
getLeadingEdgeInTriangle
(
e2
);
#ifdef DEBUG_HE
if
(
!
le
)
if
(
!
le
)
errorAndExit
(
"Triangulation::removeTriangle: could not find leading edge"
);
#endif
removeLeadingEdgeFromList
(
le
);
EdgePtr
e3
(
edge
->
getTwinEdge
()
->
getNextEdgeInFace
()
->
getNextEdgeInFace
()
);
le
=
getLeadingEdgeInTriangle
(
e3
);
removeLeadingEdgeFromList
(
le
);
EDGE_PTR
e3
(
aEdge
->
GetTwinEdge
()
->
GetNextEdgeInFace
()
->
GetNextEdgeInFace
()
);
le
=
getLeadingEdgeInTriangle
(
e3
);
#ifdef DEBUG_HE
if
(
!
le
)
if
(
!
le
)
errorAndExit
(
"Triangulation::removeTriangle: could not find leading edge"
);
#endif
removeLeadingEdgeFromList
(
le
);
// The three triangles at the node have now been removed
// from the triangulation, but the arcs have not been deleted.
// Next delete the 6 half edges radiating from the node
// The node is maintained by handle and need not be deleted explicitly
EdgePtr
estar
=
edge
;
EdgePtr
enext
=
estar
->
getTwinEdge
()
->
getNextEdgeInFace
();
estar
->
getTwinEdge
()
->
clear
();
estar
->
clear
();
estar
=
enext
;
enext
=
estar
->
getTwinEdge
()
->
getNextEdgeInFace
();
estar
->
getTwinEdge
()
->
clear
();
estar
->
clear
();
enext
->
getTwinEdge
()
->
clear
();
enext
->
clear
();
// Create the new triangle
e1
->
setNextEdgeInFace
(
e2
);
e2
->
setNextEdgeInFace
(
e3
);
e3
->
setNextEdgeInFace
(
e1
);
addLeadingEdge
(
e1
);
removeLeadingEdgeFromList
(
le
);
// The three triangles at the node have now been removed
// from the triangulation, but the arcs have not been deleted.
// Next delete the 6 half edges radiating from the node
// The node is maintained by handle and need not be deleted explicitly
EDGE_PTR
estar
=
aEdge
;
EDGE_PTR
enext
=
estar
->
GetTwinEdge
()
->
GetNextEdgeInFace
();
estar
->
GetTwinEdge
()
->
Clear
();
estar
->
Clear
();
estar
=
enext
;
enext
=
estar
->
GetTwinEdge
()
->
GetNextEdgeInFace
();
estar
->
GetTwinEdge
()
->
Clear
();
estar
->
Clear
();
enext
->
GetTwinEdge
()
->
Clear
();
enext
->
Clear
();
// Create the new triangle
e1
->
SetNextEdgeInFace
(
e2
);
e2
->
SetNextEdgeInFace
(
e3
);
e3
->
SetNextEdgeInFace
(
e1
);
addLeadingEdge
(
e1
);
}
//--------------------------------------------------------------------------------------------------
Dart
Triangulation
::
createDart
()
{
DART
TRIANGULATION
::
CreateDart
()
{
// Return an arbitrary CCW dart
return
Dart
(
*
leadingEdges_
.
begin
()
);
return
DART
(
*
m_leadingEdges
.
begin
()
);
}
//--------------------------------------------------------------------------------------------------
bool
Triangulation
::
removeLeadingEdgeFromList
(
EdgePtr
&
leadingEdge
)
{
// Remove the edge from the list of leading edges,
// but don't delete it.
// Also set flag for leading edge to false.
// Must search from start of list. Since edges are added to the
// start of the list during triangulation, this operation will
// normally be fast (when used in the triangulation algorithm)
list
<
EdgePtr
>::
iterator
it
;
for
(
it
=
leadingEdges_
.
begin
();
it
!=
leadingEdges_
.
end
();
++
it
)
{
EdgePtr
edge
=
*
it
;
if
(
edge
==
leadingEdge
)
{
edge
->
setAsLeadingEdge
(
false
);
it
=
leadingEdges_
.
erase
(
it
);
return
true
;
bool
TRIANGULATION
::
removeLeadingEdgeFromList
(
EDGE_PTR
&
aLeadingEdge
)
{
// Remove the edge from the list of leading edges,
// but don't delete it.
// Also set flag for leading edge to false.
// Must search from start of list. Since edges are added to the
// start of the list during triangulation, this operation will
// normally be fast (when used in the triangulation algorithm)
std
::
list
<
EDGE_PTR
>::
iterator
it
;
for
(
it
=
m_leadingEdges
.
begin
();
it
!=
m_leadingEdges
.
end
();
++
it
)
{
EDGE_PTR
edge
=
*
it
;
if
(
edge
==
aLeadingEdge
)
{
edge
->
SetAsLeadingEdge
(
false
);
it
=
m_leadingEdges
.
erase
(
it
);
return
true
;
}
}
}
return
false
;
return
false
;
}
//--------------------------------------------------------------------------------------------------
void
Triangulation
::
cleanAll
()
{
BOOST_FOREACH
(
EdgePtr
&
edge
,
leadingEdges_
)
edge
->
setNextEdgeInFace
(
EdgePtr
()
);
void
TRIANGULATION
::
cleanAll
()
{
BOOST_FOREACH
(
EDGE_PTR
&
edge
,
m_leadingEdges
)
edge
->
SetNextEdgeInFace
(
EDGE_PTR
()
);
}
//--------------------------------------------------------------------------------------------------
void
Triangulation
::
swapEdge
(
Dart
&
dart
)
{
swapEdge
(
dart
.
getEdge
()
);
void
TRIANGULATION
::
swapEdge
(
DART
&
aDart
)
{
SwapEdge
(
aDart
.
GetEdge
()
);
}
//--------------------------------------------------------------------------------------------------
void
Triangulation
::
splitTriangle
(
Dart
&
dart
,
const
NodePtr
&
point
)
{
EdgePtr
edge
=
splitTriangle
(
dart
.
getEdge
(),
point
);
dart
.
init
(
edge
);
void
TRIANGULATION
::
splitTriangle
(
DART
&
aDart
,
const
NODE_PTR
&
aPoint
)
{
EDGE_PTR
edge
=
SplitTriangle
(
aDart
.
GetEdge
(),
aPoint
);
aDart
.
Init
(
edge
);
}
//--------------------------------------------------------------------------------------------------
void
Triangulation
::
reverse_splitTriangle
(
Dart
&
dart
)
{
reverse_splitTriangle
(
dart
.
getEdge
()
);
void
TRIANGULATION
::
reverseSplitTriangle
(
DART
&
aDart
)
{
ReverseSplitTriangle
(
aDart
.
GetEdge
()
);
}
//--------------------------------------------------------------------------------------------------
void
Triangulation
::
removeBoundaryTriangle
(
Dart
&
d
)
{
removeTriangle
(
d
.
getEdge
()
);
void
TRIANGULATION
::
removeBoundaryTriangle
(
DART
&
aDart
)
{
RemoveTriangle
(
aDart
.
GetEdge
()
);
}
#ifdef TTL_USE_NODE_FLAG
//--------------------------------------------------------------------------------------------------
// This is a "template" for accessing all nodes (but multiple tests)
void
Triangulation
::
flagNodes
(
bool
flag
)
const
{
list
<
EdgePtr
>::
const_iterator
it
;
for
(
it
=
leadingEdges_
.
begin
();
it
!=
leadingEdges_
.
end
();
++
it
)
{
EdgePtr
edge
=
*
it
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
edge
->
getSourceNode
()
->
SetFlag
(
flag
);
edge
=
edge
->
getNextEdgeInFace
();
void
TRIANGULATION
::
FlagNodes
(
bool
aFlag
)
const
{
std
::
list
<
EDGE_PTR
>::
const_iterator
it
;
for
(
it
=
m_leadingEdges
.
begin
();
it
!=
m_leadingEdges
.
end
();
++
it
)
{
EDGE_PTR
edge
=
*
it
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
edge
->
GetSourceNode
()
->
SetFlag
(
aFlag
);
edge
=
edge
->
GetNextEdgeInFace
();
}
}
}
}
//--------------------------------------------------------------------------------------------------
list
<
NodePtr
>*
Triangulation
::
getNodes
()
const
{
flagNodes
(
false
);
list
<
NodePtr
>*
nodeList
=
new
list
<
NodePtr
>
;
list
<
EdgePtr
>::
const_iterator
it
;
for
(
it
=
leadingEdges_
.
begin
();
it
!=
leadingEdges_
.
end
();
++
it
)
{
EdgePtr
edge
=
*
it
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
const
NodePtr
&
node
=
edge
->
getSourceNode
();
if
(
node
->
GetFlag
()
==
false
)
{
nodeList
->
push_back
(
node
);
node
->
SetFlag
(
true
);
}
edge
=
edge
->
getNextEdgeInFace
();
std
::
list
<
NODE_PTR
>*
TRIANGULATION
::
GetNodes
()
const
{
FlagNodes
(
false
);
std
::
list
<
NODE_PTR
>*
nodeList
=
new
std
::
list
<
NODE_PTR
>
;
std
::
list
<
EDGE_PTR
>::
const_iterator
it
;
for
(
it
=
m_leadingEdges
.
begin
();
it
!=
m_leadingEdges
.
end
();
++
it
)
{
EDGE_PTR
edge
=
*
it
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
const
NODE_PTR
&
node
=
edge
->
GetSourceNode
();
if
(
node
->
GetFlag
()
==
false
)
{
nodeList
->
push_back
(
node
);
node
->
SetFlag
(
true
);
}
edge
=
edge
->
GetNextEdgeInFace
();
}
}
}
return
nodeList
;
return
nodeList
;
}
#endif
//--------------------------------------------------------------------------------------------------
list
<
EdgePtr
>*
Triangulation
::
getEdges
(
bool
skip_boundary_edges
)
const
{
// collect all arcs (one half edge for each arc)
// (boundary edges are also collected).
list
<
EdgePtr
>::
const_iterator
it
;
list
<
EdgePtr
>*
elist
=
new
list
<
EdgePtr
>
;
for
(
it
=
leadingEdges_
.
begin
();
it
!=
leadingEdges_
.
end
();
++
it
)
{
EdgePtr
edge
=
*
it
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
EdgePtr
twinedge
=
edge
->
getTwinEdge
();
// only one of the half-edges
if
(
(
!
twinedge
&&
!
skip_boundary_edges
)
||
(
twinedge
&&
((
size_t
)
edge
.
get
()
>
(
size_t
)
twinedge
.
get
()))
)
elist
->
push_front
(
edge
);
edge
=
edge
->
getNextEdgeInFace
();
std
::
list
<
EDGE_PTR
>*
TRIANGULATION
::
GetEdges
(
bool
aSkipBoundaryEdges
)
const
{
// collect all arcs (one half edge for each arc)
// (boundary edges are also collected).
std
::
list
<
EDGE_PTR
>::
const_iterator
it
;
std
::
list
<
EDGE_PTR
>*
elist
=
new
std
::
list
<
EDGE_PTR
>
;
for
(
it
=
m_leadingEdges
.
begin
();
it
!=
m_leadingEdges
.
end
();
++
it
)
{
EDGE_PTR
edge
=
*
it
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
EDGE_PTR
twinedge
=
edge
->
GetTwinEdge
();
// only one of the half-edges
if
(
(
!
twinedge
&&
!
aSkipBoundaryEdges
)
||
(
twinedge
&&
(
(
size_t
)
edge
.
get
()
>
(
size_t
)
twinedge
.
get
()
)
)
)
elist
->
push_front
(
edge
);
edge
=
edge
->
GetNextEdgeInFace
();
}
}
}
return
elist
;
return
elist
;
}
//--------------------------------------------------------------------------------------------------
EdgePtr
Triangulation
::
splitTriangle
(
EdgePtr
&
edge
,
const
NodePtr
&
point
)
{
// Add a node by just splitting a triangle into three triangles
// Assumes the half edge is located in the triangle
// Returns a half edge 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# are existing edges
// e#_n and e##_n are new twin edges
// e##_n are edges incident to the new node
// Add the node to the structure
//NodePtr new_node(new Node(x,y,z));
NodePtr
n1
(
edge
->
getSourceNode
());
EdgePtr
e1
(
edge
);
EdgePtr
e2
(
edge
->
getNextEdgeInFace
());
NodePtr
n2
(
e2
->
getSourceNode
());
EdgePtr
e3
(
e2
->
getNextEdgeInFace
());
NodePtr
n3
(
e3
->
getSourceNode
());
EdgePtr
e1_n
=
boost
::
make_shared
<
Edge
>
();
EdgePtr
e11_n
=
boost
::
make_shared
<
Edge
>
();
EdgePtr
e2_n
=
boost
::
make_shared
<
Edge
>
();
EdgePtr
e22_n
=
boost
::
make_shared
<
Edge
>
();
EdgePtr
e3_n
=
boost
::
make_shared
<
Edge
>
();
EdgePtr
e33_n
=
boost
::
make_shared
<
Edge
>
();
e1_n
->
setSourceNode
(
n1
);
e11_n
->
setSourceNode
(
point
);
e2_n
->
setSourceNode
(
n2
);
e22_n
->
setSourceNode
(
point
);
e3_n
->
setSourceNode
(
n3
);
e33_n
->
setSourceNode
(
point
);
e1_n
->
setTwinEdge
(
e11_n
);
e11_n
->
setTwinEdge
(
e1_n
);
e2_n
->
setTwinEdge
(
e22_n
);
e22_n
->
setTwinEdge
(
e2_n
);
e3_n
->
setTwinEdge
(
e33_n
);
e33_n
->
setTwinEdge
(
e3_n
);
e1_n
->
setNextEdgeInFace
(
e33_n
);
e2_n
->
setNextEdgeInFace
(
e11_n
);
e3_n
->
setNextEdgeInFace
(
e22_n
);
e11_n
->
setNextEdgeInFace
(
e1
);
e22_n
->
setNextEdgeInFace
(
e2
);
e33_n
->
setNextEdgeInFace
(
e3
);
// and update old's next edge
e1
->
setNextEdgeInFace
(
e2_n
);
e2
->
setNextEdgeInFace
(
e3_n
);
e3
->
setNextEdgeInFace
(
e1_n
);
// add the three new leading edges,
// Must remove the old leading edge from the list.
// Use the field telling if an edge is a leading edge
// NOTE: Must search in the list!!!
if
(
e1
->
isLeadingEdge
())
removeLeadingEdgeFromList
(
e1
);
else
if
(
e2
->
isLeadingEdge
())
removeLeadingEdgeFromList
(
e2
);
else
if
(
e3
->
isLeadingEdge
())
removeLeadingEdgeFromList
(
e3
);
else
assert
(
false
);
// one of the edges should be leading
addLeadingEdge
(
e1_n
);
addLeadingEdge
(
e2_n
);
addLeadingEdge
(
e3_n
);
// Return a half edge incident to the new node (with the new node as source node)
return
e11_n
;
EDGE_PTR
TRIANGULATION
::
SplitTriangle
(
EDGE_PTR
&
aEdge
,
const
NODE_PTR
&
aPoint
)
{
// Add a node by just splitting a triangle into three triangles
// Assumes the half aEdge is located in the triangle
// Returns a half aEdge with source node as the new node
// e#_n are new edges
// e# are existing edges
// e#_n and e##_n are new twin edges
// e##_n are edges incident to the new node
// Add the node to the structure
//NODE_PTR new_node(new Node(x,y,z));
NODE_PTR
n1
(
aEdge
->
GetSourceNode
()
);
EDGE_PTR
e1
(
aEdge
);
EDGE_PTR
e2
(
aEdge
->
GetNextEdgeInFace
()
);
NODE_PTR
n2
(
e2
->
GetSourceNode
()
);
EDGE_PTR
e3
(
e2
->
GetNextEdgeInFace
()
);
NODE_PTR
n3
(
e3
->
GetSourceNode
()
);
EDGE_PTR
e1_n
=
boost
::
make_shared
<
EDGE
>
();
EDGE_PTR
e11_n
=
boost
::
make_shared
<
EDGE
>
();
EDGE_PTR
e2_n
=
boost
::
make_shared
<
EDGE
>
();
EDGE_PTR
e22_n
=
boost
::
make_shared
<
EDGE
>
();
EDGE_PTR
e3_n
=
boost
::
make_shared
<
EDGE
>
();
EDGE_PTR
e33_n
=
boost
::
make_shared
<
EDGE
>
();
e1_n
->
SetSourceNode
(
n1
);
e11_n
->
SetSourceNode
(
aPoint
);
e2_n
->
SetSourceNode
(
n2
);
e22_n
->
SetSourceNode
(
aPoint
);
e3_n
->
SetSourceNode
(
n3
);
e33_n
->
SetSourceNode
(
aPoint
);
e1_n
->
SetTwinEdge
(
e11_n
);
e11_n
->
SetTwinEdge
(
e1_n
);
e2_n
->
SetTwinEdge
(
e22_n
);
e22_n
->
SetTwinEdge
(
e2_n
);
e3_n
->
SetTwinEdge
(
e33_n
);
e33_n
->
SetTwinEdge
(
e3_n
);
e1_n
->
SetNextEdgeInFace
(
e33_n
);
e2_n
->
SetNextEdgeInFace
(
e11_n
);
e3_n
->
SetNextEdgeInFace
(
e22_n
);
e11_n
->
SetNextEdgeInFace
(
e1
);
e22_n
->
SetNextEdgeInFace
(
e2
);
e33_n
->
SetNextEdgeInFace
(
e3
);
// and update old's next aEdge
e1
->
SetNextEdgeInFace
(
e2_n
);
e2
->
SetNextEdgeInFace
(
e3_n
);
e3
->
SetNextEdgeInFace
(
e1_n
);
// add the three new leading edges,
// Must remove the old leading aEdge from the list.
// Use the field telling if an aEdge is a leading aEdge
// NOTE: Must search in the list!!!
if
(
e1
->
IsLeadingEdge
()
)
removeLeadingEdgeFromList
(
e1
);
else
if
(
e2
->
IsLeadingEdge
()
)
removeLeadingEdgeFromList
(
e2
);
else
if
(
e3
->
IsLeadingEdge
()
)
removeLeadingEdgeFromList
(
e3
);
else
assert
(
false
);
// one of the edges should be leading
addLeadingEdge
(
e1_n
);
addLeadingEdge
(
e2_n
);
addLeadingEdge
(
e3_n
);
// Return a half aEdge incident to the new node (with the new node as source node)
return
e11_n
;
}
//--------------------------------------------------------------------------------------------------
void
Triangulation
::
swapEdge
(
EdgePtr
&
diagonal
)
{
// Note that diagonal is both input and output and it is always
// kept in counterclockwise direction (this is not required by all
// functions in TriangulationHelper now)
// Swap by rotating counterclockwise
// Use the same objects - no deletion or new objects
EdgePtr
eL
(
diagonal
);
EdgePtr
eR
(
eL
->
getTwinEdge
());
EdgePtr
eL_1
(
eL
->
getNextEdgeInFace
());
EdgePtr
eL_2
(
eL_1
->
getNextEdgeInFace
());
EdgePtr
eR_1
(
eR
->
getNextEdgeInFace
());
EdgePtr
eR_2
(
eR_1
->
getNextEdgeInFace
());
// avoid node to be dereferenced to zero and deleted
NodePtr
nR
(
eR_2
->
getSourceNode
());
NodePtr
nL
(
eL_2
->
getSourceNode
());
eL
->
setSourceNode
(
nR
);
eR
->
setSourceNode
(
nL
);
// and now 6 1-sewings
eL
->
setNextEdgeInFace
(
eL_2
);
eL_2
->
setNextEdgeInFace
(
eR_1
);
eR_1
->
setNextEdgeInFace
(
eL
);
eR
->
setNextEdgeInFace
(
eR_2
);
eR_2
->
setNextEdgeInFace
(
eL_1
);
eL_1
->
setNextEdgeInFace
(
eR
);
if
(
eL
->
isLeadingEdge
())
removeLeadingEdgeFromList
(
eL
);
else
if
(
eL_1
->
isLeadingEdge
())
removeLeadingEdgeFromList
(
eL_1
);
else
if
(
eL_2
->
isLeadingEdge
())
removeLeadingEdgeFromList
(
eL_2
);
if
(
eR
->
isLeadingEdge
())
removeLeadingEdgeFromList
(
eR
);
else
if
(
eR_1
->
isLeadingEdge
())
removeLeadingEdgeFromList
(
eR_1
);
else
if
(
eR_2
->
isLeadingEdge
())
removeLeadingEdgeFromList
(
eR_2
);
addLeadingEdge
(
eL
);
addLeadingEdge
(
eR
);
void
TRIANGULATION
::
SwapEdge
(
EDGE_PTR
&
aDiagonal
)
{
// Note that diagonal is both input and output and it is always
// kept in counterclockwise direction (this is not required by all
// functions in TriangulationHelper now)
// Swap by rotating counterclockwise
// Use the same objects - no deletion or new objects
EDGE_PTR
eL
(
aDiagonal
);
EDGE_PTR
eR
(
eL
->
GetTwinEdge
()
);
EDGE_PTR
eL_1
(
eL
->
GetNextEdgeInFace
()
);
EDGE_PTR
eL_2
(
eL_1
->
GetNextEdgeInFace
()
);
EDGE_PTR
eR_1
(
eR
->
GetNextEdgeInFace
()
);
EDGE_PTR
eR_2
(
eR_1
->
GetNextEdgeInFace
()
);
// avoid node to be dereferenced to zero and deleted
NODE_PTR
nR
(
eR_2
->
GetSourceNode
()
);
NODE_PTR
nL
(
eL_2
->
GetSourceNode
()
);
eL
->
SetSourceNode
(
nR
);
eR
->
SetSourceNode
(
nL
);
// and now 6 1-sewings
eL
->
SetNextEdgeInFace
(
eL_2
);
eL_2
->
SetNextEdgeInFace
(
eR_1
);
eR_1
->
SetNextEdgeInFace
(
eL
);
eR
->
SetNextEdgeInFace
(
eR_2
);
eR_2
->
SetNextEdgeInFace
(
eL_1
);
eL_1
->
SetNextEdgeInFace
(
eR
);
if
(
eL
->
IsLeadingEdge
()
)
removeLeadingEdgeFromList
(
eL
);
else
if
(
eL_1
->
IsLeadingEdge
()
)
removeLeadingEdgeFromList
(
eL_1
);
else
if
(
eL_2
->
IsLeadingEdge
()
)
removeLeadingEdgeFromList
(
eL_2
);
if
(
eR
->
IsLeadingEdge
()
)
removeLeadingEdgeFromList
(
eR
);
else
if
(
eR_1
->
IsLeadingEdge
()
)
removeLeadingEdgeFromList
(
eR_1
);
else
if
(
eR_2
->
IsLeadingEdge
()
)
removeLeadingEdgeFromList
(
eR_2
);
addLeadingEdge
(
eL
);
addLeadingEdge
(
eR
);
}
////--------------------------------------------------------------------------
//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 !!!!
// ofstream os("qweND.dat");
const
list
<
EdgePtr
>&
leadingEdges
=
getLeadingEdges
();
list
<
EdgePtr
>::
const_iterator
it
;
bool
ok
=
true
;
int
noNotDelaunay
=
0
;
for
(
it
=
leadingEdges
.
begin
();
it
!=
leadingEdges
.
end
();
++
it
)
{
EdgePtr
edge
=
*
it
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
EdgePtr
twinedge
=
edge
->
getTwinEdge
();
// only one of the half-edges
if
(
!
twinedge
||
(
size_t
)
edge
.
get
()
>
(
size_t
)
twinedge
.
get
())
{
Dart
dart
(
edge
);
if
(
helper
->
swapTestDelaunay
<
TTLtraits
>
(
dart
))
{
noNotDelaunay
++
;
//printEdge(dart,os); os << "\n";
ok
=
false
;
//cout << "............. not Delaunay .... " << endl;
bool
TRIANGULATION
::
CheckDelaunay
()
const
{
// ???? outputs !!!!
// ofstream os("qweND.dat");
const
std
::
list
<
EDGE_PTR
>&
leadingEdges
=
GetLeadingEdges
();
std
::
list
<
EDGE_PTR
>::
const_iterator
it
;
bool
ok
=
true
;
int
noNotDelaunay
=
0
;
for
(
it
=
leadingEdges
.
begin
();
it
!=
leadingEdges
.
end
();
++
it
)
{
EDGE_PTR
edge
=
*
it
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
EDGE_PTR
twinedge
=
edge
->
GetTwinEdge
();
// only one of the half-edges
if
(
!
twinedge
||
(
size_t
)
edge
.
get
()
>
(
size_t
)
twinedge
.
get
()
)
{
DART
dart
(
edge
);
if
(
m_helper
->
SwapTestDelaunay
<
TTLtraits
>
(
dart
)
)
{
noNotDelaunay
++
;
//printEdge(dart,os); os << "\n";
ok
=
false
;
//cout << "............. not Delaunay .... " << endl;
}
}
edge
=
edge
->
GetNextEdgeInFace
();
}
}
edge
=
edge
->
getNextEdgeInFace
();
}
}
#ifdef DEBUG_HE
cout
<<
"!!! Triangulation is NOT Delaunay: "
<<
noNotDelaunay
<<
" edges
\n
"
<<
endl
;
cout
<<
"!!! Triangulation is NOT Delaunay: "
<<
noNotDelaunay
<<
" edges
\n
"
<<
endl
;
#endif
return
ok
;
return
ok
;
}
//--------------------------------------------------------------------------------------------------
void
Triangulation
::
optimizeDelaunay
()
{
// This function is also present in ttl where it is implemented
// generically.
// The implementation below is tailored for the half-edge data structure,
// and is thus more efficient
// Collect all interior edges (one half edge for each arc)
bool
skip_boundary_edges
=
true
;
list
<
EdgePtr
>*
elist
=
getEdges
(
skip_boundary_edges
);
// Assumes that elist has only one half-edge for each arc.
bool
cycling_check
=
true
;
bool
optimal
=
false
;
list
<
EdgePtr
>::
const_iterator
it
;
while
(
!
optimal
)
{
optimal
=
true
;
for
(
it
=
elist
->
begin
();
it
!=
elist
->
end
();
++
it
)
{
EdgePtr
edge
=
*
it
;
Dart
dart
(
edge
);
// Constrained edges should not be swapped
if
(
helper
->
swapTestDelaunay
<
TTLtraits
>
(
dart
,
cycling_check
))
{
optimal
=
false
;
swapEdge
(
edge
);
}
void
TRIANGULATION
::
OptimizeDelaunay
()
{
// This function is also present in ttl where it is implemented
// generically.
// The implementation below is tailored for the half-edge data structure,
// and is thus more efficient
// Collect all interior edges (one half edge for each arc)
bool
skip_boundary_edges
=
true
;
std
::
list
<
EDGE_PTR
>*
elist
=
GetEdges
(
skip_boundary_edges
);
// Assumes that elist has only one half-edge for each arc.
bool
cycling_check
=
true
;
bool
optimal
=
false
;
std
::
list
<
EDGE_PTR
>::
const_iterator
it
;
while
(
!
optimal
)
{
optimal
=
true
;
for
(
it
=
elist
->
begin
();
it
!=
elist
->
end
();
++
it
)
{
EDGE_PTR
edge
=
*
it
;
DART
dart
(
edge
);
// Constrained edges should not be swapped
if
(
m_helper
->
SwapTestDelaunay
<
TTLtraits
>
(
dart
,
cycling_check
)
)
{
optimal
=
false
;
SwapEdge
(
edge
);
}
}
}
}
delete
elist
;
delete
elist
;
}
//--------------------------------------------------------------------------------------------------
EdgePtr
Triangulation
::
getInteriorNode
()
const
{
const
list
<
EdgePtr
>&
leadingEdges
=
getLeadingEdges
();
list
<
EdgePtr
>::
const_iterator
it
;
for
(
it
=
leadingEdges
.
begin
();
it
!=
leadingEdges
.
end
();
++
it
)
{
EdgePtr
edge
=
*
it
;
EDGE_PTR
TRIANGULATION
::
GetInteriorNode
()
const
{
const
std
::
list
<
EDGE_PTR
>&
leadingEdges
=
GetLeadingEdges
();
std
::
list
<
EDGE_PTR
>::
const_iterator
it
;
// multiple checks, but only until found
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
if
(
edge
->
getTwinEdge
())
{
if
(
!
helper
->
isBoundaryNode
(
Dart
(
edge
)))
return
edge
;
}
edge
=
edge
->
getNextEdgeInFace
();
for
(
it
=
leadingEdges
.
begin
();
it
!=
leadingEdges
.
end
();
++
it
)
{
EDGE_PTR
edge
=
*
it
;
// multiple checks, but only until found
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
if
(
edge
->
GetTwinEdge
()
)
{
if
(
!
m_helper
->
IsBoundaryNode
(
DART
(
edge
)
)
)
return
edge
;
}
edge
=
edge
->
GetNextEdgeInFace
();
}
}
}
return
EdgePtr
();
// no boundary nodes
return
EDGE_PTR
();
// no boundary nodes
}
//--------------------------------------------------------------------------------------------------
EdgePtr
Triangulation
::
getBoundaryEdgeInTriangle
(
const
EdgePtr
&
e
)
const
{
EdgePtr
edge
=
e
;
if
(
helper
->
isBoundaryEdge
(
Dart
(
edge
)))
return
edge
;
EDGE_PTR
TRIANGULATION
::
GetBoundaryEdgeInTriangle
(
const
EDGE_PTR
&
aEdge
)
const
{
EDGE_PTR
edge
=
aEdge
;
edge
=
edge
->
getNextEdgeInFace
();
if
(
helper
->
isBoundaryEdge
(
Dart
(
edge
)))
return
edge
;
if
(
m_helper
->
IsBoundaryEdge
(
DART
(
edge
)
)
)
return
edge
;
edge
=
edge
->
getNextEdgeInFace
();
if
(
helper
->
isBoundaryEdge
(
Dart
(
edge
)))
return
edge
;
return
EdgePtr
();
edge
=
edge
->
GetNextEdgeInFace
();
if
(
m_helper
->
IsBoundaryEdge
(
DART
(
edge
)
)
)
return
edge
;
edge
=
edge
->
GetNextEdgeInFace
();
if
(
m_helper
->
IsBoundaryEdge
(
DART
(
edge
)
)
)
return
edge
;
return
EDGE_PTR
();
}
//--------------------------------------------------------------------------------------------------
EdgePtr
Triangulation
::
getBoundaryEdge
()
const
{
EDGE_PTR
TRIANGULATION
::
GetBoundaryEdge
()
const
{
// Get an arbitrary (CCW) boundary edge
// 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
;
// Get an arbitrary (CCW) boundary edge
// If the triangulation is closed, NULL is returned
for
(
it
=
leadingEdges
.
begin
();
it
!=
leadingEdges
.
end
();
++
it
)
{
edge
=
GetBoundaryEdgeInTriangle
(
*
it
);
const
list
<
EdgePtr
>&
leadingEdges
=
getLeadingEdges
();
list
<
EdgePtr
>::
const_iterator
it
;
EdgePtr
edge
;
for
(
it
=
leadingEdges
.
begin
();
it
!=
leadingEdges
.
end
();
++
it
)
{
edge
=
getBoundaryEdgeInTriangle
(
*
it
);
if
(
edge
)
return
edge
;
}
return
EdgePtr
();
if
(
edge
)
return
edge
;
}
return
EDGE_PTR
();
}
//--------------------------------------------------------------------------------------------------
void
Triangulation
::
printEdges
(
ofstream
&
os
)
const
{
// Print source node and target node for each edge face by face,
// but only one of the half-edges.
const
list
<
EdgePtr
>&
leadingEdges
=
getLeadingEdges
();
list
<
EdgePtr
>::
const_iterator
it
;
for
(
it
=
leadingEdges
.
begin
();
it
!=
leadingEdges
.
end
();
++
it
)
{
EdgePtr
edge
=
*
it
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
EdgePtr
twinedge
=
edge
->
getTwinEdge
();
// Print only one edge (the highest value of the pointer)
if
(
!
twinedge
||
(
size_t
)
edge
.
get
()
>
(
size_t
)
twinedge
.
get
())
{
// Print source node and target node
NodePtr
node
=
edge
->
getSourceNode
();
os
<<
node
->
GetX
()
<<
" "
<<
node
->
GetY
()
<<
endl
;
node
=
edge
->
getTargetNode
();
os
<<
node
->
GetX
()
<<
" "
<<
node
->
GetY
()
<<
endl
;
os
<<
'\n'
;
// blank line
}
edge
=
edge
->
getNextEdgeInFace
();
void
TRIANGULATION
::
PrintEdges
(
std
::
ofstream
&
aOutput
)
const
{
// Print source node and target node for each edge face by face,
// but only one of the half-edges.
const
std
::
list
<
EDGE_PTR
>&
leadingEdges
=
GetLeadingEdges
();
std
::
list
<
EDGE_PTR
>::
const_iterator
it
;
for
(
it
=
leadingEdges
.
begin
();
it
!=
leadingEdges
.
end
();
++
it
)
{
EDGE_PTR
edge
=
*
it
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
EDGE_PTR
twinedge
=
edge
->
GetTwinEdge
();
// Print only one edge (the highest value of the pointer)
if
(
!
twinedge
||
(
size_t
)
edge
.
get
()
>
(
size_t
)
twinedge
.
get
()
)
{
// Print source node and target node
NODE_PTR
node
=
edge
->
GetSourceNode
();
aOutput
<<
node
->
GetX
()
<<
" "
<<
node
->
GetY
()
<<
std
::
endl
;
node
=
edge
->
GetTargetNode
();
aOutput
<<
node
->
GetX
()
<<
" "
<<
node
->
GetY
()
<<
std
::
endl
;
aOutput
<<
'\n'
;
// blank line
}
edge
=
edge
->
GetNextEdgeInFace
();
}
}
}
}
include/ttl/halfedge/hedart.h
View file @
6fa2f060
...
...
@@ -40,111 +40,152 @@
#ifndef _HALF_EDGE_DART_
#define _HALF_EDGE_DART_
#include <ttl/halfedge/hetriang.h>
namespace
hed
{
/**
* \class Dart
* \brief \b %Dart class for the half-edge data structure.
*
* See \ref api for a detailed description of how the member functions
* should be implemented.
*/
class
DART
{
EDGE_PTR
m_edge
;
namespace
hed
{
//------------------------------------------------------------------------------------------------
// Dart class for the half-edge data structure
//------------------------------------------------------------------------------------------------
/** \class Dart
* \brief \b %Dart class for the half-edge data structure.
*
* See \ref api for a detailed description of how the member functions
* should be implemented.
*/
class
Dart
{
EdgePtr
edge_
;
bool
dir_
;
// true if dart is counterclockwise in face
/// Dart direction: true if dart is counterclockwise in face
bool
m_dir
;
public
:
public
:
/// Default constructor
Dart
()
{
dir_
=
true
;
}
DART
()
{
m_dir
=
true
;
}
/// 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
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
~
Dart
()
{}
~
DART
()
{
}
/// Assignment operator
Dart
&
operator
=
(
const
Dart
&
dart
)
{
if
(
this
==
&
dart
)
DART
&
operator
=
(
const
DART
&
aDart
)
{
if
(
this
==
&
aDart
)
return
*
this
;
m_edge
=
aDart
.
m_edge
;
m_dir
=
aDart
.
m_dir
;
return
*
this
;
edge_
=
dart
.
edge_
;
dir_
=
dart
.
dir_
;
return
*
this
;
}
/// Comparing dart objects
bool
operator
==
(
const
Dart
&
dart
)
const
{
if
(
dart
.
edge_
==
edge_
&&
dart
.
dir_
==
dir_
)
return
true
;
return
false
;
bool
operator
==
(
const
DART
&
aDart
)
const
{
return
(
aDart
.
m_edge
==
m_edge
&&
aDart
.
m_dir
==
m_dir
);
}
/// Comparing dart objects
bool
operator
!=
(
const
Dart
&
dart
)
const
{
return
!
(
dart
==*
this
);
bool
operator
!=
(
const
DART
&
aDart
)
const
{
return
!
(
aDart
==
*
this
);
}
/// 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
Dart
&
alpha1
()
{
if
(
dir_
)
{
edge_
=
edge_
->
getNextEdgeInFace
()
->
getNextEdgeInFace
();
dir_
=
false
;
}
else
{
edge_
=
edge_
->
getNextEdgeInFace
();
dir_
=
true
;
}
return
*
this
;
DART
&
Alpha1
()
{
if
(
m_dir
)
{
m_edge
=
m_edge
->
GetNextEdgeInFace
()
->
GetNextEdgeInFace
();
m_dir
=
false
;
}
else
{
m_edge
=
m_edge
->
GetNextEdgeInFace
();
m_dir
=
true
;
}
return
*
this
;
}
/// Maps the dart to a different triangle. \b Note: the dart is not changed if it is at the boundary!
Dart
&
alpha2
()
{
if
(
edge_
->
getTwinEdge
())
{
edge_
=
edge_
->
getTwinEdge
();
dir_
=
!
dir_
;
}
// else, the dart is at the boundary and should not be changed
return
*
this
;
DART
&
Alpha2
()
{
if
(
m_edge
->
GetTwinEdge
()
)
{
m_edge
=
m_edge
->
GetTwinEdge
();
m_dir
=
!
m_dir
;
}
// else, the dart is at the boundary and should not be changed
return
*
this
;
}
// 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
;
}
void
init
(
const
EdgePtr
&
edge
,
bool
dir
=
true
)
{
edge_
=
edge
;
dir_
=
dir
;
}
double
X
()
const
{
return
GetNode
()
->
GetX
();
}
double
x
()
const
{
return
getNode
()
->
GetX
();
}
// x-coordinate of source node
double
y
()
const
{
return
getNode
()
->
GetY
();
}
// y-coordinate of source node
double
Y
()
const
{
return
GetNode
()
->
GetY
();
}
bool
isCounterClockWise
()
const
{
return
dir_
;
}
bool
IsCCW
()
const
{
return
m_dir
;
}
const
NodePtr
&
getNode
()
const
{
return
dir_
?
edge_
->
getSourceNode
()
:
edge_
->
getTargetNode
();
}
const
NodePtr
&
getOppositeNode
()
const
{
return
dir_
?
edge_
->
getTargetNode
()
:
edge_
->
getSourceNode
();
}
EdgePtr
&
getEdge
()
{
return
edge_
;
}
const
NODE_PTR
&
GetNode
()
const
{
return
m_dir
?
m_edge
->
GetSourceNode
()
:
m_edge
->
GetTargetNode
();
}
//@} // End of Utilities not required by TTL
const
NODE_PTR
&
GetOppositeNode
()
const
{
return
m_dir
?
m_edge
->
GetTargetNode
()
:
m_edge
->
GetSourceNode
();
}
};
EDGE_PTR
&
GetEdge
()
{
return
m_edge
;
}
//@} // End of Utilities not required by TTL
};
}
;
// End of hed namespace
}
// End of hed namespace
#endif
include/ttl/halfedge/hetraits.h
View file @
6fa2f060
...
...
@@ -40,136 +40,149 @@
#ifndef _HALF_EDGE_TRAITS_
#define _HALF_EDGE_TRAITS_
#include <ttl/halfedge/hetriang.h>
#include <ttl/halfedge/hedart.h>
namespace
hed
{
//------------------------------------------------------------------------------------------------
// Traits class for the half-edge data structure
//------------------------------------------------------------------------------------------------
/** \struct TTLtraits
* \brief \b Traits class (static struct) for the half-edge data structure.
*
* The member functions are those required by different function templates
* in the TTL. Documentation is given here to explain what actions
* should be carried out on the actual data structure as required by the functions
* in the \ref ttl namespace.
*
* The source code of \c %HeTraits.h shows how the traits class is implemented for the
* half-edge data structure.
*
* \see \ref api
*
*/
struct
TTLtraits
{
namespace
hed
{
/**
* \struct TTLtraits
* \brief \b Traits class (static struct) for the half-edge data structure.
*
* The member functions are those required by different function templates
* in the TTL. Documentation is given here to explain what actions
* should be carried out on the actual data structure as required by the functions
* in the \ref ttl namespace.
*
* The source code of \c %HeTraits.h shows how the traits class is implemented for the
* half-edge data structure.
*
* \see \ref api
*/
struct
TTLtraits
{
/**
* The floating point type used in calculations involving scalar products and cross products.
*/
typedef
double
REAL_TYPE
;
/** The floating point type used in calculations
* involving scalar products and cross products.
*/
typedef
double
real_type
;
//----------------------------------------------------------------------------------------------
// ------------------------------- Geometric Predicates Group ---------------------------------
//----------------------------------------------------------------------------------------------
/** @name Geometric Predicates */
//@{
//----------------------------------------------------------------------------------------------
/** Scalar product between two 2D vectors represented as darts.\n
*
* ttl_util::scalarProduct2d can be used.
*/
static
real_type
scalarProduct2d
(
const
Dart
&
v1
,
const
Dart
&
v2
)
{
Dart
v10
=
v1
;
v10
.
alpha0
();
Dart
v20
=
v2
;
v20
.
alpha0
();
return
ttl_util
::
scalarProduct2d
(
v10
.
x
()
-
v1
.
x
(),
v10
.
y
()
-
v1
.
y
(),
v20
.
x
()
-
v2
.
x
(),
v20
.
y
()
-
v2
.
y
());
/**
* Scalar product between two 2D vectors represented as darts.\n
*
* ttl_util::scalarProduct2d can be used.
*/
static
REAL_TYPE
ScalarProduct2D
(
const
DART
&
aV1
,
const
DART
&
aV2
)
{
DART
v10
=
aV1
;
v10
.
Alpha0
();
DART
v20
=
aV2
;
v20
.
Alpha0
();
return
ttl_util
::
ScalarProduct2D
(
v10
.
X
()
-
aV1
.
X
(),
v10
.
Y
()
-
aV1
.
Y
(),
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
* vector has direction from the source node of \e v to the point \e p.\n
*
* ttl_util::scalarProduct2d can be used.
*/
static
real_type
scalarProduct2d
(
const
Dart
&
v
,
const
NodePtr
&
p
)
{
Dart
d0
=
v
;
d0
.
alpha0
();
return
ttl_util
::
scalarProduct2d
(
d0
.
x
()
-
v
.
x
(),
d0
.
y
()
-
v
.
y
(),
p
->
GetX
()
-
v
.
x
(),
p
->
GetY
()
-
v
.
y
());
/**
* Scalar product between two 2D vectors.
* 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
*
* ttl_util::ScalarProduct2D can be used.
*/
static
REAL_TYPE
ScalarProduct2D
(
const
DART
&
aV
,
const
NODE_PTR
&
aP
)
{
DART
d0
=
aV
;
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.
* The z-component of the cross product is returned.\n
*
* ttl_util::crossProduct2d can be used.
*/
static
real_type
crossProduct2d
(
const
Dart
&
v1
,
const
Dart
&
v2
)
{
Dart
v10
=
v1
;
v10
.
alpha0
();
Dart
v20
=
v2
;
v20
.
alpha0
();
return
ttl_util
::
crossProduct2d
(
v10
.
x
()
-
v1
.
x
(),
v10
.
y
()
-
v1
.
y
(),
v20
.
x
()
-
v2
.
x
(),
v20
.
y
()
-
v2
.
y
());
/**
* Cross product between two vectors in the plane represented as darts.
* The z-component of the cross product is returned.\n
*
* ttl_util::CrossProduct2D can be used.
*/
static
REAL_TYPE
CrossProduct2D
(
const
DART
&
aV1
,
const
DART
&
aV2
)
{
DART
v10
=
aV1
;
v10
.
Alpha0
();
DART
v20
=
aV2
;
v20
.
Alpha0
();
return
ttl_util
::
CrossProduct2D
(
v10
.
X
()
-
aV1
.
X
(),
v10
.
Y
()
-
aV1
.
Y
(),
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
* 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
*
* ttl_util::crossProduct2d can be used.
*/
static
real_type
crossProduct2d
(
const
Dart
&
v
,
const
NodePtr
&
p
)
{
Dart
d0
=
v
;
d0
.
alpha0
();
return
ttl_util
::
crossProduct2d
(
d0
.
x
()
-
v
.
x
(),
d0
.
y
()
-
v
.
y
(),
p
->
GetX
()
-
v
.
x
(),
p
->
GetY
()
-
v
.
y
());
/**
* Cross product between two vectors in the plane.
* 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.
* The z-component of the cross product is returned.\n
*
* ttl_util::CrossProduct2d can be used.
*/
static
REAL_TYPE
CrossProduct2D
(
const
DART
&
aV
,
const
NODE_PTR
&
aP
)
{
DART
d0
=
aV
;
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
* 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
* in clockwise order; and zero if they are collinear.
*/
static
real_type
orient2d
(
const
Dart
&
n1
,
const
Dart
&
n2
,
const
NodePtr
&
p
)
{
real_type
pa
[
2
];
real_type
pb
[
2
];
real_type
pc
[
2
];
pa
[
0
]
=
n1
.
x
();
pa
[
1
]
=
n1
.
y
();
pb
[
0
]
=
n2
.
x
();
pb
[
1
]
=
n2
.
y
();
pc
[
0
]
=
p
->
GetX
();
pc
[
1
]
=
p
->
GetY
();
return
ttl_util
::
orient2dfast
(
pa
,
pb
,
pc
);
/**
* 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,
* and \e p occur in counterclockwise order; a negative value if they occur
* in clockwise order; and zero if they are collinear.
*/
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
]
=
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,
* but with a slighty different interface:
* The last parameter is given as a dart where the source node of the dart
* represents a point in the plane.
* This function is required for constrained triangulation.
*/
static
real_type
orient2d
(
const
Dart
&
n1
,
const
Dart
&
n2
,
const
Dart
&
p
)
{
real_type
pa
[
2
];
real_type
pb
[
2
];
real_type
pc
[
2
];
pa
[
0
]
=
n1
.
x
();
pa
[
1
]
=
n1
.
y
();
pb
[
0
]
=
n2
.
x
();
pb
[
1
]
=
n2
.
y
();
pc
[
0
]
=
p
.
x
();
pc
[
1
]
=
p
.
y
();
return
ttl_util
::
orient2dfast
(
pa
,
pb
,
pc
);
/**
* This is the same predicate as represented with the function above,
* but with a slighty different interface:
* The last parameter is given as a dart where the source node of the dart
* represents a point in the plane.
* This function is required for constrained triangulation.
*/
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
]
=
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 hed namespace
...
...
include/ttl/halfedge/hetriang.h
View file @
6fa2f060
...
...
@@ -42,11 +42,9 @@
#ifndef _HE_TRIANG_H_
#define _HE_TRIANG_H_
#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)
#include <list>
#include <vector>
#include <iostream>
...
...
@@ -55,43 +53,40 @@
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
namespace
ttl
{
class
TriangulationHelper
;
namespace
ttl
{
class
TRIANGULATION_HELPER
;
};
//--------------------------------------------------------------------------------------------------
// The half-edge data structure
//--------------------------------------------------------------------------------------------------
namespace
hed
{
// Helper typedefs
class
Node
;
class
Edge
;
typedef
boost
::
shared_ptr
<
Node
>
NodePtr
;
typedef
boost
::
shared_ptr
<
Edge
>
EdgePtr
;
typedef
boost
::
weak_ptr
<
Edge
>
EdgeWeakPtr
;
typedef
std
::
vector
<
NodePtr
>
NodesContainer
;
//------------------------------------------------------------------------------------------------
// Node class for data structures
//------------------------------------------------------------------------------------------------
/** \class Node
* \brief \b Node class for data structures (Inherits from HandleId)
*
* \note
* - To enable node IDs, TTL_USE_NODE_ID must be defined.
* - To enable node flags, TTL_USE_NODE_FLAG must be defined.
* - 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.
*/
class
Node
{
/**
* The half-edge data structure
*/
namespace
hed
{
// Helper typedefs
class
NODE
;
class
EDGE
;
typedef
boost
::
shared_ptr
<
NODE
>
NODE_PTR
;
typedef
boost
::
shared_ptr
<
EDGE
>
EDGE_PTR
;
typedef
boost
::
weak_ptr
<
EDGE
>
EDGE_WEAK_PTR
;
typedef
std
::
vector
<
NODE_PTR
>
NODES_CONTAINER
;
/**
* \class NODE
* \brief \b Node class for data structures (Inherits from HandleId)
*
* \note
* - To enable node IDs, TTL_USE_NODE_ID must be defined.
* - To enable node flags, TTL_USE_NODE_FLAG must be defined.
* - 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.
*/
class
NODE
{
protected
:
#ifdef TTL_USE_NODE_FLAG
/// TTL_USE_NODE_FLAG must be defined
bool
flag_
;
bool
m_flag
;
#endif
#ifdef TTL_USE_NODE_ID
...
...
@@ -99,303 +94,378 @@ protected:
static
int
id_count
;
/// A unique id for each node (TTL_USE_NODE_ID must be defined)
int
id_
;
int
m_id
;
#endif
int
x_
,
y_
;
/// Node coordinates
int
m_x
,
m_y
;
unsigned
int
refCount_
;
/// Reference count
unsigned
int
m_refCount
;
public
:
/// Constructor
N
ode
(
int
x
=
0
,
int
y
=
0
)
:
N
ODE
(
int
aX
=
0
,
int
aY
=
0
)
:
#ifdef TTL_USE_NODE_FLAG
flag_
(
false
),
m_flag
(
false
),
#endif
#ifdef TTL_USE_NODE_ID
id_
(
id_count
++
),
m_id
(
id_count
++
),
#endif
x_
(
x
),
y_
(
y
),
refCount_
(
0
)
{}
m_x
(
aX
),
m_y
(
aY
),
m_refCount
(
0
)
{
}
/// Destructor
~
N
ode
()
{}
~
N
ODE
()
{}
/// Returns the x-coordinate
int
GetX
()
const
{
return
x_
;
}
int
GetX
()
const
{
return
m_x
;
}
/// Returns the y-coordinate
int
GetY
()
const
{
return
y_
;
}
int
GetY
()
const
{
return
m_y
;
}
#ifdef TTL_USE_NODE_ID
/// Returns the id (TTL_USE_NODE_ID must be defined)
int
Id
()
const
{
return
id_
;
}
int
Id
()
const
{
return
m_id
;
}
#endif
#ifdef TTL_USE_NODE_FLAG
/// 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)
const
bool
&
GetFlag
()
const
{
return
flag_
;
}
const
bool
&
GetFlag
()
const
{
return
m_flag
;
}
#endif
void
IncRefCount
()
{
refCount_
++
;
}
void
DecRefCount
()
{
refCount_
--
;
}
unsigned
int
GetRefCount
()
const
{
return
refCount_
;
}
};
// End of class Node
void
IncRefCount
()
{
m_refCount
++
;
}
//------------------------------------------------------------------------------------------------
// Edge class in the half-edge data structure
//------------------------------------------------------------------------------------------------
void
DecRefCount
()
{
m_refCount
--
;
}
/** \class Edge
* \brief \b %Edge class in the in the half-edge data structure.
*/
unsigned
int
GetRefCount
()
const
{
return
m_refCount
;
}
};
class
Edge
{
public
:
/**
* \class EDGE
* \brief \b %Edge class in the in the half-edge data structure.
*/
class
EDGE
{
public
:
/// Constructor
Edge
()
:
weight_
(
0
),
isLeadingEdge_
(
false
)
{}
EDGE
()
:
m_weight
(
0
),
m_isLeadingEdge
(
false
)
{
}
/// Destructor
virtual
~
Edge
()
{}
virtual
~
EDGE
()
{
}
/// 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
void
setNextEdgeInFace
(
const
EdgePtr
&
edge
)
{
nextEdgeInFace_
=
edge
;
}
void
SetNextEdgeInFace
(
const
EDGE_PTR
&
aEdge
)
{
m_nextEdgeInFace
=
aEdge
;
}
/// 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
void
setAsLeadingEdge
(
bool
val
=
true
)
{
isLeadingEdge_
=
val
;
}
void
SetAsLeadingEdge
(
bool
aLeading
=
true
)
{
m_isLeadingEdge
=
aLeading
;
}
/// Checks if an edge is a leading edge
bool
isLeadingEdge
()
const
{
return
isLeadingEdge_
;
}
bool
IsLeadingEdge
()
const
{
return
m_isLeadingEdge
;
}
/// 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
const
EdgePtr
&
getNextEdgeInFace
()
const
{
return
nextEdgeInFace_
;
}
const
EDGE_PTR
&
GetNextEdgeInFace
()
const
{
return
m_nextEdgeInFace
;
}
/// Retuns the source node
const
NodePtr
&
getSourceNode
()
const
{
return
sourceNode_
;
}
const
NODE_PTR
&
GetSourceNode
()
const
{
return
m_sourceNode
;
}
/// 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
();
nextEdgeInFace_
.
reset
();
m_sourceNode
.
reset
();
m_nextEdgeInFace
.
reset
();
if
(
!
twinEdge_
.
expired
()
)
if
(
!
m_twinEdge
.
expired
()
)
{
twinEdge_
.
lock
()
->
c
learTwinEdge
();
twinEdge_
.
reset
();
m_twinEdge
.
lock
()
->
C
learTwinEdge
();
m_twinEdge
.
reset
();
}
}
protected
:
N
odePtr
sourceNode_
;
E
dgeWeakPtr
twinEdge_
;
E
dgePtr
nextEdgeInFace_
;
unsigned
int
weight_
;
bool
isLeadingEdge_
;
};
// End of class Edge
protected
:
N
ODE_PTR
m_sourceNode
;
E
DGE_WEAK_PTR
m_twinEdge
;
E
DGE_PTR
m_nextEdgeInFace
;
unsigned
int
m_weight
;
bool
m_isLeadingEdge
;
};
/** \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
{
private
:
N
odePtr
target_
;
class
EDGE_MST
:
public
EDGE
{
private
:
N
ODE_PTR
m_target
;
public
:
EdgeMST
(
const
NodePtr
&
source
,
const
NodePtr
&
target
,
unsigned
int
weight
=
0
)
:
target_
(
target
)
{
sourceNode_
=
source
;
weight_
=
weight
;
}
public
:
EDGE_MST
(
const
NODE_PTR
&
aSource
,
const
NODE_PTR
&
aTarget
,
unsigned
int
aWeight
=
0
)
:
m_target
(
aTarget
)
{
m_sourceNode
=
aSource
;
m_weight
=
aWeight
;
}
E
dgeMST
(
const
Edge
&
edge
)
E
DGE_MST
(
const
EDGE
&
edge
)
{
sourceNode_
=
edge
.
g
etSourceNode
();
target_
=
edge
.
g
etTargetNode
();
weight_
=
edge
.
g
etWeight
();
m_sourceNode
=
edge
.
G
etSourceNode
();
m_target
=
edge
.
G
etTargetNode
();
m_weight
=
edge
.
G
etWeight
();
}
~
EdgeMST
()
{};
~
EDGE_MST
()
{
}
/// @copydoc Edge::setSourceNode()
virtual
const
NodePtr
&
getTargetNode
()
const
{
return
target_
;
}
};
//------------------------------------------------------------------------------------------------
class
Dart
;
// Forward declaration (class in this namespace)
//------------------------------------------------------------------------------------------------
// Triangulation class in the half-edge data structure
//------------------------------------------------------------------------------------------------
/** \class Triangulation
* \brief \b %Triangulation class for the half-edge data structure with adaption to TTL.
*/
virtual
const
NODE_PTR
&
GetTargetNode
()
const
{
return
m_target
;
}
};
class
Triangulation
{
class
DART
;
// Forward declaration (class in this namespace)
protected
:
std
::
list
<
EdgePtr
>
leadingEdges_
;
// one half-edge for each arc
/**
* \class TRIANGULATION
* \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
;
ttl
::
T
riangulationHelper
*
helper
;
ttl
::
T
RIANGULATION_HELPER
*
m_
helper
;
void
addLeadingEdge
(
EdgePtr
&
edge
)
{
edge
->
setAsLeadingEdge
();
leadingEdges_
.
push_front
(
edge
);
void
addLeadingEdge
(
EDGE_PTR
&
aEdge
)
{
aEdge
->
SetAsLeadingEdge
();
m_leadingEdges
.
push_front
(
aEdge
);
}
bool
removeLeadingEdgeFromList
(
EdgePtr
&
leadingEdge
);
bool
removeLeadingEdgeFromList
(
EDGE_PTR
&
aLeadingEdge
);
void
cleanAll
();
/** Swaps the edge associated with \e dart in the actual data structure.
*
* <center>
* \image html swapEdge.gif
* </center>
*
* \param dart
* Some of the functions require a dart as output.
* 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)
* the edge CCW; see the figure.
*
* \note
* - If the edge is \e constrained, or if it should not be swapped for
* some other reason, this function need not do the actual swap of the edge.
* - Some functions in TTL require that \c swapEdge is implemented such that
* darts outside the quadrilateral are not affected by the swap.
*/
void
swapEdge
(
Dart
&
dart
);
/** Splits the triangle associated with \e dart in the actual data structure into
* three new triangles joining at \e point.
*
* <center>
* \image html splitTriangle.gif
* </center>
*
* \param dart
* Output: A CCW dart incident with the new node; see the figure.
*/
void
splitTriangle
(
Dart
&
dart
,
const
NodePtr
&
point
);
/** The reverse operation of TTLtraits::splitTriangle.
* This function is only required for functions that involve
* removal of interior nodes; see for example TrinagulationHelper::removeInteriorNode.
*
* <center>
* \image html reverse_splitTriangle.gif
* </center>
*/
void
reverse_splitTriangle
(
Dart
&
dart
);
/** Removes a triangle with an edge at the boundary of the triangulation
* in the actual data structure
*/
void
removeBoundaryTriangle
(
Dart
&
d
);
public
:
*
* <center>
* \image html swapEdge.gif
* </center>
*
* \param aDart
* Some of the functions require a dart as output.
* 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)
* the edge CCW; see the figure.
*
* \note
* - If the edge is \e constrained, or if it should not be swapped for
* some other reason, this function need not do the actual swap of the edge.
* - Some functions in TTL require that \c swapEdge is implemented such that
* darts outside the quadrilateral are not affected by the swap.
*/
void
swapEdge
(
DART
&
aDart
);
/**
* Splits the triangle associated with \e dart in the actual data structure into
* three new triangles joining at \e point.
*
* <center>
* \image html splitTriangle.gif
* </center>
*
* \param aDart
* Output: A CCW dart incident with the new node; see the figure.
*/
void
splitTriangle
(
DART
&
aDart
,
const
NODE_PTR
&
aPoint
);
/**
* The reverse operation of TTLtraits::splitTriangle.
* This function is only required for functions that involve
* removal of interior nodes; see for example TrinagulationHelper::RemoveInteriorNode.
*
* <center>
* \image html reverse_splitTriangle.gif
* </center>
*/
void
reverseSplitTriangle
(
DART
&
aDart
);
/**
* Removes a triangle with an edge at the boundary of the triangulation
* in the actual data structure
*/
void
removeBoundaryTriangle
(
DART
&
aDart
);
public
:
/// Default constructor
T
riangulation
();
T
RIANGULATION
();
/// Copy constructor
T
riangulation
(
const
Triangulation
&
tr
);
T
RIANGULATION
(
const
TRIANGULATION
&
aTriangulation
);
/// Destructor
~
T
riangulation
();
~
T
RIANGULATION
();
/// Creates a Delaunay triangulation from a set of points
void
createDelaunay
(
NodesContainer
::
iterator
first
,
NodesContainer
::
iterator
last
);
void
CreateDelaunay
(
NODES_CONTAINER
::
iterator
aFirst
,
NODES_CONTAINER
::
iterator
aLast
);
/// Creates an initial Delaunay triangulation from two enclosing triangles
// When using rectangular boundary - loop through all points and expand.
// (Called from createDelaunay(...) when starting)
EdgePtr
initTwoEnclosingTriangles
(
NodesContainer
::
iterator
first
,
NodesContainer
::
iterator
last
);
EDGE_PTR
InitTwoEnclosingTriangles
(
NODES_CONTAINER
::
iterator
aFirst
,
NODES_CONTAINER
::
iterator
aLast
);
// These two functions are required by TTL for Delaunay triangulation
/// 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
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
/// 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
void
reverse_splitTriangle
(
EdgePtr
&
edge
);
void
ReverseSplitTriangle
(
EDGE_PTR
&
aEdge
);
/// 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)
const
std
::
list
<
EdgePtr
>&
getLeadingEdges
()
const
{
return
leadingEdges_
;
}
const
std
::
list
<
EDGE_PTR
>&
GetLeadingEdges
()
const
{
return
m_leadingEdges
;
}
/// 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)
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
/// 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.
std
::
list
<
N
odePtr
>*
g
etNodes
()
const
;
std
::
list
<
N
ODE_PTR
>*
G
etNodes
()
const
;
#endif
/// Swaps edges until the triangulation is Delaunay (constrained edges are not swapped)
void
o
ptimizeDelaunay
();
void
O
ptimizeDelaunay
();
/// 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)
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
E
dgePtr
g
etBoundaryEdge
()
const
;
E
DGE_PTR
G
etBoundaryEdge
()
const
;
/// Print edges for plotting with, e.g., gnuplot
void
printEdges
(
std
::
ofstream
&
os
)
const
;
friend
class
ttl
::
TriangulationHelper
;
};
// End of class Triangulation
void
PrintEdges
(
std
::
ofstream
&
aOutput
)
const
;
friend
class
ttl
::
TRIANGULATION_HELPER
;
};
};
// End of hed namespace
#endif
include/ttl/ttl.h
View file @
6fa2f060
This source diff could not be displayed because it is too large. You can
view the blob
instead.
include/ttl/ttl_util.h
View file @
6fa2f060
...
...
@@ -3,11 +3,11 @@
* Applied Mathematics, Norway.
*
* 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,
* 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
* it under the terms of the GNU Affero General Public License as
...
...
@@ -16,7 +16,7 @@
*
* TTL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A
aPARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
...
...
@@ -40,28 +40,22 @@
#ifndef _TTL_UTIL_H_
#define _TTL_UTIL_H_
#include <vector>
#include <algorithm>
#ifdef _MSC_VER
# if _MSC_VER < 1300
# include <minmax.h>
# endif
#endif
//using namespace std;
/** \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
* 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.
* Thus, the user can call these functions from the traits class.
* For efficiency reasons, the user may consider implementing these
...
...
@@ -77,67 +71,59 @@
* ttl and \ref api
*
* \author
* Øyvind Hjelle, oyvindhj@ifi.uio.no
*
�
yvind Hjelle, oyvindhj@ifi.uio.no
*/
namespace
ttl_util
{
/** @name Computational geometry */
//@{
/** Scalar product between two 2D vectors.
*
* \aPAr Returns:
* \code
* aDX1*aDX2 + aDY1*aDY2
* \endcode
*/
template
<
class
REAL_TYPE
>
REAL_TYPE
ScalarProduct2D
(
REAL_TYPE
aDX1
,
REAL_TYPE
aDY1
,
REAL_TYPE
aDX2
,
REAL_TYPE
aDY2
)
{
return
aDX1
*
aDX2
+
aDY1
*
aDY2
;
}
namespace
ttl_util
{
//------------------------------------------------------------------------------------------------
// ------------------------------ Computational Geometry Group ----------------------------------
//------------------------------------------------------------------------------------------------
/** @name Computational geometry */
//@{
//------------------------------------------------------------------------------------------------
/** Scalar product between two 2D vectors.
*
* \par Returns:
* \code
* dx1*dx2 + dy1*dy2
* \endcode
*/
template
<
class
real_type
>
real_type
scalarProduct2d
(
real_type
dx1
,
real_type
dy1
,
real_type
dx2
,
real_type
dy2
)
{
return
dx1
*
dx2
+
dy1
*
dy2
;
}
//------------------------------------------------------------------------------------------------
/** Cross product between two 2D vectors. (The z-component of the actual cross product.)
*
* \par Returns:
* \code
* dx1*dy2 - dy1*dx2
* \endcode
*/
template
<
class
real_type
>
real_type
crossProduct2d
(
real_type
dx1
,
real_type
dy1
,
real_type
dx2
,
real_type
dy2
)
{
return
dx1
*
dy2
-
dy1
*
dx2
;
}
/** Cross product between two 2D vectors. (The z-component of the actual cross product.)
*
* \aPAr Returns:
* \code
* aDX1*aDY2 - aDY1*aDX2
* \endcode
*/
template
<
class
REAL_TYPE
>
REAL_TYPE
CrossProduct2D
(
REAL_TYPE
aDX1
,
REAL_TYPE
aDY1
,
REAL_TYPE
aDX2
,
REAL_TYPE
aDY2
)
{
return
aDX1
*
aDY2
-
aDY1
*
aDX2
;
}
/** Returns a positive value if the 2D nodes/points \e aPA, \e aPB, and
* \e aPC occur in counterclockwise order; a negative value if they occur
* in clockwise order; and zero if they are collinear.
*
* \note
* - This is a finite arithmetic fast version. It can be made more robust using
* exact arithmetic schemes by Jonathan Richard Shewchuk. See
* http://www-2.cs.cmu.edu/~quake/robust.html
*/
template
<
class
REAL_TYPE
>
REAL_TYPE
Orient2DFast
(
REAL_TYPE
aPA
[
2
],
REAL_TYPE
aPB
[
2
],
REAL_TYPE
aPC
[
2
]
)
{
REAL_TYPE
acx
=
aPA
[
0
]
-
aPC
[
0
];
REAL_TYPE
bcx
=
aPB
[
0
]
-
aPC
[
0
];
REAL_TYPE
acy
=
aPA
[
1
]
-
aPC
[
1
];
REAL_TYPE
bcy
=
aPB
[
1
]
-
aPC
[
1
];
//------------------------------------------------------------------------------------------------
/** Returns a positive value if the 2D nodes/points \e pa, \e pb, and
* \e pc occur in counterclockwise order; a negative value if they occur
* in clockwise order; and zero if they are collinear.
*
* \note
* - This is a finite arithmetic fast version. It can be made more robust using
* exact arithmetic schemes by Jonathan Richard Shewchuk. See
* http://www-2.cs.cmu.edu/~quake/robust.html
*/
template
<
class
real_type
>
real_type
orient2dfast
(
real_type
pa
[
2
],
real_type
pb
[
2
],
real_type
pc
[
2
])
{
real_type
acx
=
pa
[
0
]
-
pc
[
0
];
real_type
bcx
=
pb
[
0
]
-
pc
[
0
];
real_type
acy
=
pa
[
1
]
-
pc
[
1
];
real_type
bcy
=
pb
[
1
]
-
pc
[
1
];
return
acx
*
bcy
-
acy
*
bcx
;
}
}
}
;
// End of ttl_util namespace scope
}
// namespace ttl_util
#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,
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 )
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,
{
RN_EDGE_PTR
&
dt
=
*
aEdges
.
begin
();
int
srcTag
=
tags
[
dt
->
g
etSourceNode
()];
int
trgTag
=
tags
[
dt
->
g
etTargetNode
()];
int
srcTag
=
tags
[
dt
->
G
etSourceNode
()];
int
trgTag
=
tags
[
dt
->
G
etTargetNode
()];
// Check if by adding this edge we are going to join two different forests
if
(
srcTag
!=
trgTag
)
...
...
@@ -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
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
--
;
}
...
...
@@ -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,
// RN_EDGE_MST saves both source and target node and does not require any other
// edges to exist for getting source/target nodes
RN_EDGE_MST_PTR
newEdge
=
boost
::
make_shared
<
RN_EDGE_MST
>
(
dt
->
g
etSourceNode
(),
dt
->
g
etTargetNode
(),
dt
->
g
etWeight
()
);
RN_EDGE_MST_PTR
newEdge
=
boost
::
make_shared
<
RN_EDGE_MST
>
(
dt
->
G
etSourceNode
(),
dt
->
G
etTargetNode
(),
dt
->
G
etWeight
()
);
mst
->
push_back
(
newEdge
);
++
mstSize
;
}
...
...
@@ -169,8 +169,8 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
void
RN_NET
::
validateEdge
(
RN_EDGE_PTR
&
aEdge
)
{
RN_NODE_PTR
source
=
aEdge
->
g
etSourceNode
();
RN_NODE_PTR
target
=
aEdge
->
g
etTargetNode
();
RN_NODE_PTR
source
=
aEdge
->
G
etSourceNode
();
RN_NODE_PTR
target
=
aEdge
->
G
etTargetNode
();
bool
valid
=
true
;
// If any of nodes belonging to the edge has the flag set,
...
...
@@ -280,13 +280,13 @@ void RN_NET::compute()
std
::
partial_sort_copy
(
boardNodes
.
begin
(),
boardNodes
.
end
(),
nodes
.
begin
(),
nodes
.
end
()
);
TRIANGULATOR
triangulator
;
triangulator
.
c
reateDelaunay
(
nodes
.
begin
(),
nodes
.
end
()
);
boost
::
scoped_ptr
<
RN_LINKS
::
RN_EDGE_LIST
>
triangEdges
(
triangulator
.
g
etEdges
()
);
triangulator
.
C
reateDelaunay
(
nodes
.
begin
(),
nodes
.
end
()
);
boost
::
scoped_ptr
<
RN_LINKS
::
RN_EDGE_LIST
>
triangEdges
(
triangulator
.
G
etEdges
()
);
// Compute weight/distance for edges resulting from triangulation
RN_LINKS
::
RN_EDGE_LIST
::
iterator
eit
,
eitEnd
;
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
std
::
copy
(
boardEdges
.
begin
(),
boardEdges
.
end
(),
std
::
front_inserter
(
*
triangEdges
)
);
...
...
@@ -508,8 +508,8 @@ void RN_NET::RemoveItem( const TRACK* aTrack )
RN_EDGE_PTR
&
edge
=
m_tracks
.
at
(
aTrack
);
// Save nodes, so they can be cleared later
RN_NODE_PTR
aBegin
=
edge
->
g
etSourceNode
();
RN_NODE_PTR
aEnd
=
edge
->
g
etTargetNode
();
RN_NODE_PTR
aBegin
=
edge
->
G
etSourceNode
();
RN_NODE_PTR
aEnd
=
edge
->
G
etTargetNode
();
m_links
.
RemoveConnection
(
edge
);
// 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
const
TRACK
*
track
=
static_cast
<
const
TRACK
*>
(
aItem
);
RN_EDGE_PTR
edge
=
m_tracks
.
at
(
track
);
nodes
.
push_back
(
edge
->
g
etSourceNode
()
);
nodes
.
push_back
(
edge
->
g
etTargetNode
()
);
nodes
.
push_back
(
edge
->
G
etSourceNode
()
);
nodes
.
push_back
(
edge
->
G
etTargetNode
()
);
}
break
;
...
...
pcbnew/ratsnest_data.h
View file @
6fa2f060
...
...
@@ -50,13 +50,13 @@ class ZONE_CONTAINER;
class
CPolyPt
;
// Preserve KiCad coding style policy
typedef
hed
::
N
ode
RN_NODE
;
typedef
hed
::
N
odePtr
RN_NODE_PTR
;
typedef
hed
::
E
dge
RN_EDGE
;
typedef
hed
::
E
dgePtr
RN_EDGE_PTR
;
typedef
hed
::
E
dgeMST
RN_EDGE_MST
;
typedef
boost
::
shared_ptr
<
hed
::
EdgeMST
>
RN_EDGE_MST_PT
R
;
typedef
hed
::
Triangulation
TRIANGULATO
R
;
typedef
hed
::
N
ODE
RN_NODE
;
typedef
hed
::
N
ODE_PTR
RN_NODE_PTR
;
typedef
hed
::
E
DGE
RN_EDGE
;
typedef
hed
::
E
DGE_PTR
RN_EDGE_PTR
;
typedef
hed
::
E
DGE_MST
RN_EDGE_MST
;
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
);
...
...
pcbnew/ratsnest_viewitem.cpp
View file @
6fa2f060
...
...
@@ -97,8 +97,8 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const
BOOST_FOREACH
(
const
RN_EDGE_PTR
&
edge
,
*
edges
)
{
const
RN_NODE_PTR
&
sourceNode
=
edge
->
g
etSourceNode
();
const
RN_NODE_PTR
&
targetNode
=
edge
->
g
etTargetNode
();
const
RN_NODE_PTR
&
sourceNode
=
edge
->
G
etSourceNode
();
const
RN_NODE_PTR
&
targetNode
=
edge
->
G
etTargetNode
();
VECTOR2D
source
(
sourceNode
->
GetX
(),
sourceNode
->
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