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
e76c330a
Commit
e76c330a
authored
Mar 13, 2014
by
Maciej Suminski
Committed by
Marco Serantoni
Mar 13, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixes build error with the choosy CLANG (Thanks to Maciej Suminski)
parent
d00fae58
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
1 addition
and
645 deletions
+1
-645
ttl.h
include/ttl/ttl.h
+1
-10
ttl_constr.h
include/ttl/ttl_constr.h
+0
-635
No files found.
include/ttl/ttl.h
View file @
e76c330a
...
@@ -357,7 +357,7 @@ private:
...
@@ -357,7 +357,7 @@ private:
ForwardIterator
it
;
ForwardIterator
it
;
for
(
it
=
first
;
it
!=
last
;
++
it
)
{
for
(
it
=
first
;
it
!=
last
;
++
it
)
{
bool
status
=
insertNode
<
TraitsType
>
(
dart
,
**
it
);
insertNode
<
TraitsType
>
(
dart
,
**
it
);
}
}
}
}
...
@@ -1914,13 +1914,4 @@ passes:
...
@@ -1914,13 +1914,4 @@ passes:
};
// 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)
//------------------------------------------------------------------------------------------------
// ----------------------------- Constrained Triangulation Group --------------------------------
//------------------------------------------------------------------------------------------------
// Still namespace ttl
#include <ttl/ttl_constr.h>
#endif // _TTL_H_
#endif // _TTL_H_
include/ttl/ttl_constr.h
deleted
100644 → 0
View file @
d00fae58
/*
* Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
* Applied Mathematics, Norway.
*
* Contact information: E-mail: tor.dokken@sintef.no
* SINTEF ICT, Department of Applied Mathematics,
* P.O. Box 124 Blindern,
* 0314 Oslo, Norway.
*
* This file is part 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
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* 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
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with TTL. If not, see
* <http://www.gnu.org/licenses/>.
*
* In accordance with Section 7(b) of the GNU Affero General Public
* License, a covered work must retain the producer line in every data
* file that is created or manipulated using TTL.
*
* Other Usage
* You can be released from the requirements of the license by purchasing
* a commercial license. Buying such a license is mandatory as soon as you
* develop commercial activities involving the TTL library without
* disclosing the source code of your own applications.
*
* This file may be used in accordance with the terms contained in a
* written agreement between you and SINTEF ICT.
*/
#ifndef _TTL_CONSTR_H_
#define _TTL_CONSTR_H_
#include <list>
#include <cmath>
// Debugging
#ifdef DEBUG_TTL_CONSTR_PLOT
#include <fstream>
static
ofstream
ofile_constr
(
"qweCons.dat"
);
#endif
/** \brief Constrained Delaunay triangulation
*
* Basic generic algorithms in TTL for inserting a constrained edge between two existing nodes.\n
*
* See documentation for the namespace ttl for general requirements and assumptions.
*
* \author
* �yvind Hjelle, oyvindhj@ifi.uio.no
*/
namespace
ttl_constr
{
// ??? A constant used to evluate a numerical expression against a user spesified
// roundoff-zero number
#ifdef DEBUG_TTL_CONSTR
static
const
double
ROUNDOFFZERO
=
0
.
0
;
// 0.1e-15;
#endif
class
ConstrainedTriangulation
{
public
:
//------------------------------------------------------------------------------------------------
/* Checks if \e dart has start and end points in \e dstart and \e dend.
*
* \param dart
* The dart that should be controlled to see if it's the constraint
*
* \param dstart
* A CCW dart with the startnode of the constraint as the startnode
*
* \param dend
* A CCW dart with the endnode of the constraint as the startnode
*
* \retval bool
* A bool confirming that it's the constraint or not
*
* \using
* same_0_orbit
*/
template
<
class
DartType
>
static
bool
isTheConstraint
(
const
DartType
&
dart
,
const
DartType
&
dstart
,
const
DartType
&
dend
)
{
DartType
d0
=
dart
;
d0
.
alpha0
();
// CW
if
((
ttl
::
TriangulationHelper
::
same_0_orbit
(
dstart
,
dart
)
&&
ttl
::
TriangulationHelper
::
same_0_orbit
(
dend
,
d0
))
||
(
ttl
::
TriangulationHelper
::
same_0_orbit
(
dstart
,
d0
)
&&
ttl
::
TriangulationHelper
::
same_0_orbit
(
dend
,
dart
)))
{
return
true
;
}
return
false
;
}
//------------------------------------------------------------------------------------------------
/* Checks if \e d1 and \e d2 are on the same side of the line between \e dstart and \e dend.
* (The start nodes of \e d1 and \e d2 represent an edge).
*
* \param dstart
* A CCW dart with the start node of the constraint as the source node of the dart.
*
* \param dend
* A CCW dart with the end node of the constraint as the source node of the dart.
*
* \param d1
* A CCW dart with the first node as the start node of the dart.
*
* \param d2
* A CCW dart with the other node as the start node of the dart.
*
* \using
* TraitsType::orient2d
*/
template
<
class
TraitsType
,
class
DartType
>
static
bool
crossesConstraint
(
DartType
&
dstart
,
DartType
&
dend
,
DartType
&
d1
,
DartType
&
d2
)
{
typename
TraitsType
::
real_type
orient_1
=
TraitsType
::
orient2d
(
dstart
,
d1
,
dend
);
typename
TraitsType
::
real_type
orient_2
=
TraitsType
::
orient2d
(
dstart
,
d2
,
dend
);
// ??? Should we refine this? e.g. find if (dstart,dend) (d1,d2) represent the same edge
if
((
orient_1
<=
0
&&
orient_2
<=
0
)
||
(
orient_1
>=
0
&&
orient_2
>=
0
))
return
false
;
return
true
;
}
//------------------------------------------------------------------------------------------------
/* Return the dart \e d making the smallest non-negative angle,
* as calculated with: orient2d(dstart, d.alpha0(), dend),
* at the 0-orbit of dstart.
* If (dstart,dend) is a CCW boundary edge \e d will be CW, otherwise CCW (since CCW in)
* at the 0-orbit of dstart.
*
* \par Assumes:
* - CCW dstart and dend, but returned dart can be CW at the boundary.
* - Boundary is convex?
*
* \param dstart
* A CCW dart dstart
*
* \param dend
* A CCW dart dend
*
* \retval DartType
* The dart \e d making the smallest positive (or == 0) angle
*
* \using
* isBoundaryNode
* positionAtNextBoundaryEdge
* TraitsType::orient2d
*/
template
<
class
TraitsType
,
class
DartType
>
static
DartType
getAtSmallestAngle
(
const
DartType
&
dstart
,
const
DartType
&
dend
)
{
// - Must boundary be convex???
// - Handle the case where the constraint is already present???
// - Handle dstart and/or dend at the boundary
// (dstart and dend may define a boundary edge)
DartType
d_iter
=
dstart
;
if
(
ttl
::
TriangulationHelper
::
isBoundaryNode
(
d_iter
))
{
d_iter
.
alpha1
();
// CW
ttl
::
TriangulationHelper
::
positionAtNextBoundaryEdge
(
d_iter
);
// CCW (was rotated CW to the boundary)
}
// assume convex boundary; see comments
DartType
d0
=
d_iter
;
d0
.
alpha0
();
bool
ccw
=
true
;
// the rotation later
typename
TraitsType
::
real_type
o_iter
=
TraitsType
::
orient2d
(
d_iter
,
d0
,
dend
);
if
(
o_iter
==
0
)
{
// collinear BUT can be on "back side"
d0
.
alpha1
().
alpha0
();
// CW
if
(
TraitsType
::
orient2d
(
dstart
,
dend
,
d0
)
>
0
)
return
d_iter
;
//(=dstart) collinear
else
{
// collinear on "back side"
d_iter
.
alpha1
().
alpha2
();
// assume convex boundary
ccw
=
true
;
}
}
else
if
(
o_iter
<
0
)
{
// Prepare for rotating CW and with d_iter CW
d_iter
.
alpha1
();
ccw
=
false
;
}
// Set first angle
d0
=
d_iter
;
d0
.
alpha0
();
o_iter
=
TraitsType
::
orient2d
(
dstart
,
d0
,
dend
);
typename
TraitsType
::
real_type
o_next
;
// Rotate towards the constraint CCW or CW.
// Here we assume that the boundary is convex.
DartType
d_next
=
d_iter
;
for
(;;)
{
d_next
.
alpha1
();
// CW !!! (if ccw == true)
d0
=
d_next
;
d0
.
alpha0
();
o_next
=
TraitsType
::
orient2d
(
dstart
,
d0
,
dend
);
if
(
ccw
&&
o_next
<
0
)
// and o_iter > 0
return
d_iter
;
else
if
(
!
ccw
&&
o_next
>
0
)
return
d_next
;
// CCW
else
if
(
o_next
==
0
)
{
if
(
ccw
)
return
d_next
.
alpha2
();
// also ok if boundary
else
return
d_next
;
}
// prepare next
d_next
.
alpha2
();
// CCW if ccw
d_iter
=
d_next
;
// also ok if boundary CCW if ccw == true
}
}
//------------------------------------------------------------------------------------------------
/* This function finds all the edges in the triangulation crossing
* the spesified constraint and puts them in a list.
* In the case of collinearity, an attempt is made to detect this.
* The first collinear node between dstart and dend is then returned.
*
* Strategy:
* - Iterate such that \e d_iter is always strictly "below" the constraint
* as seen with \e dstart to the left and \e dend to the right.
* - Add CCW darts, whose edges intersect the constrait, to a list.
* These edges are found by the orient2d predicate:
* If two nodes of an edge are on opposite sides of the constraint,
* the edge between them intersect.
* - Must handle collinnear cases, i.e., if a node falls on the constraint,
* and possibly restarting collection of edges. Detecting collinearity
* heavily relies on the orient2d predicate which is provided by the
* traits class.
*
* Action:
* 1) Find cone/opening angle containing \e dstart and \e dend
* 2) Find first edge from the first 0-orbit that intersects
* 3) Check which of the two opposite that intersects
*
* 1)
* Rotate CCW and find the (only) case where \e d_iter and \e d_next satisfy:
* - orient2d(d_iter, d_iter.alpha0(), dend) > 0
* - orient2d(d_next, d_next.alpha0(), dend) < 0
*
* - check if we are done, i.e., if (d_next.alpha0() == my_dend)
* - Note also the situation if, e.g., the constraint is a boundary edge in which case
* \e my_dend wil be CW
*
* \param dstart
* A CCW dart with the startnode of the constraint as the startnode
*
* \param dend
* A CCW dart with the endnode of the constraint as the startnode
*
* \param elist
* A list where all the edges crossing the spesified constraint will be put
*
* \retval dartType
* Returns the next "collinear" starting node such that dend is returned when done.
*/
template
<
class
TraitsType
,
class
DartType
,
class
ListType
>
static
DartType
findCrossingEdges
(
const
DartType
&
dstart
,
const
DartType
&
dend
,
ListType
&
elist
)
{
const
DartType
my_start
=
getAtSmallestAngle
<
TraitsType
>
(
dstart
,
dend
);
DartType
my_end
=
getAtSmallestAngle
<
TraitsType
>
(
dend
,
dstart
);
DartType
d_iter
=
my_start
;
if
(
d_iter
.
alpha0
().
alpha2
()
==
my_end
)
return
d_iter
;
// The constraint is an existing edge and we are done
// Facts/status so far:
// - my_start and my_end are now both CCW and the constraint is not a boundary edge.
// - Further, the constraint is not one single existing edge, but it might be a collection
// of collinear edges in which case we return the current collinear edge
// and calling this function until all are collected.
my_end
.
alpha1
();
// CW! // ??? this is probably ok for testing now?
d_iter
=
my_start
;
d_iter
.
alpha0
().
alpha1
();
// alpha0 is downwards or along the constraint
// Facts:
// - d_iter is guaranteed to intersect, but can be in start point.
// - d_iter.alpha0() is not at dend yet
typename
TraitsType
::
real_type
orient
=
TraitsType
::
orient2d
(
dstart
,
d_iter
,
dend
);
// Use round-off error/tolerance or rely on the orient2d predicate ???
// Make a warning message if orient != exact 0
if
(
orient
==
0
)
return
d_iter
;
#ifdef DEBUG_TTL_CONSTR
else
if
(
fabs
(
orient
)
<=
ROUNDOFFZERO
)
{
cout
<<
"The darts are not exactly colinear, but |d1 x d2| <= "
<<
ROUNDOFFZERO
<<
endl
;
return
d_iter
;
// collinear, not done (and not collect in the list)
}
#endif
// Collect intersecting edges
// --------------------------
elist
.
push_back
(
d_iter
);
// The first with interior intersection point
// Facts, status so far:
// - The first intersecting edge is now collected
// (- d_iter.alpha0() is still not at dend)
// d_iter should always be the edge that intersects and be below or on the constraint
// One of the two edges opposite to d_iter must intersect, or we have collinearity
// Note: Almost collinear cases can be handled on the
// application side with orient2d. We should probably
// return an int and the application will set it to zero
for
(;;)
{
// assume orient have been calc. and collinearity has been tested,
// above the first time and below later
d_iter
.
alpha2
().
alpha1
();
// 2a same node
DartType
d0
=
d_iter
;
d0
.
alpha0
();
// CW
if
(
d0
==
my_end
)
return
dend
;
// WE ARE DONE (but can we enter an endless loop???)
// d_iter or d_iter.alpha0().alpha1() must intersect
orient
=
TraitsType
::
orient2d
(
dstart
,
d0
,
dend
);
if
(
orient
==
0
)
return
d0
.
alpha1
();
#ifdef DEBUG_TTL_CONSTR
else
if
(
fabs
(
orient
)
<=
ROUNDOFFZERO
)
{
return
d0
.
alpha1
();
// CCW, collinear
}
#endif
else
if
(
orient
>
0
)
{
// orient > 0 and still below
// This one must intersect!
d_iter
=
d0
.
alpha1
();
}
elist
.
push_back
(
d_iter
);
}
}
//------------------------------------------------------------------------------------------------
/* This function recives a constrained edge and a list of all the edges crossing a constraint.
* It then swaps the crossing edges away from the constraint. This is done according to a
* scheme suggested by Dyn, Goren & Rippa (slightly modified).
* The resulting triangulation is a constrained one, but not necessarily constrained Delaunay.
* In other to run optimization later to obtain a constrained Delaunay triangulation,
* the swapped edges are maintained in a list.
*
* Strategy :
* - Situation A: Run through the list and swap crossing edges away from the constraint.
* All the swapped edges are moved to the end of the list, and are "invisible" to this procedure.
* - Situation B: We may come in a situation where none of the crossing edges can be swapped away
* from the constraint.
* Then we follow the strategy of Dyn, Goren & Rippa and allow edges to be swapped,
* even if they are not swapped away from the constraint.
* These edges are NOT moved to the end of the list. They are later swapped to none-crossing
* edges when the locked situation is solved.
* - We keep on swapping edges in Situation B until we have iterated trough the list.
* We then resume Situation A.
* - This is done until the list is virtualy empty. The resulting \c elist has the constraint
* as the last element.
*
* \param dstart
* A CCW dart dstart
*
* \param dend
* A CCW dart dend
*
* \param elist
* A list containing all the edges crossing the spesified constraint
*
* \using
* swappableEdge
* swapEdgeInList
* crossesConstraint
* isTheConstraint
*/
template
<
class
TraitsType
,
class
DartType
>
void
transformToConstraint
(
ttl
::
TriangulationHelper
helper
,
DartType
&
dstart
,
DartType
&
dend
,
std
::
list
<
DartType
>&
elist
)
const
{
typename
std
::
list
<
DartType
>::
iterator
it
,
used
;
// We may enter in a situation where dstart and dend are altered because of a swap.
// (The general rule is that darts inside the actual quadrilateral can be changed,
// but not those outside.)
// So, we need some look-ahead strategies for dstart and dend and change these
// after a swap if necessary.
int
dartsInList
=
(
int
)
elist
.
size
();
if
(
dartsInList
==
0
)
return
;
bool
erase
;
// indicates if an edge is swapped away from the constraint such that it can be
// moved to the back of the list
bool
locked
=
false
;
do
{
int
noswap
=
0
;
it
=
elist
.
begin
();
// counts how many edges that have been swapped per list-cycle
int
counter
=
1
;
while
(
it
!=
elist
.
end
())
{
// ??? change this test with counter > dartsInList
erase
=
false
;
// Check if our virtual end of the list has been crossed. It breaks the
// while and starts all over again in the do-while loop
if
(
counter
>
dartsInList
)
break
;
if
(
ttl
::
TriangulationHelper
::
swappableEdge
<
TraitsType
,
DartType
>
(
*
it
,
true
))
{
// Dyn & Goren & Rippa 's notation:
// The node assosiated with dart *it is denoted u_m. u_m has edges crossing the constraint
// named w_1, ... , w_r . The other node to the edge assosiated with dart *it is w_s.
// We want to swap from edge u_m<->w_s to edge w_{s-1}<->w_{s+1}.
DartType
op1
=
*
it
;
DartType
op2
=
op1
;
op1
.
alpha1
().
alpha0
();
//finds dart with node w_{s-1}
op2
.
alpha2
().
alpha1
().
alpha0
();
// (CW) finds dart with node w_{s+1}
DartType
tmp
=
*
it
;
tmp
.
alpha0
();
// Dart with assosiated node opposite to node of *it allong edge
// If there is a locked situation we swap, even if the result is crossing the constraint
// If there is a looked situation, but we do an ordinary swap, it should be treated as
// if we were not in a locked situation!!
// The flag swap_away indicates if the edge is swapped away from the constraint such that
// it does not cross the constraint.
bool
swap_away
=
(
crossesConstraint
<
TraitsType
>
(
dstart
,
dend
,
*
it
,
tmp
)
&&
!
crossesConstraint
<
TraitsType
>
(
dstart
,
dend
,
op1
,
op2
));
if
(
swap_away
||
locked
)
{
// Do a look-ahead to see if dstart and/or dend are in the quadrilateral
// If so, we mark it with a flag to make sure we update them after the swap
// (they may have been changed during the swap according to the general rule!)
bool
start
=
false
;
bool
end
=
false
;
DartType
d
=
*
it
;
if
(
d
.
alpha1
().
alpha0
()
==
dstart
)
start
=
true
;
d
=
*
it
;
if
(
d
.
alpha2
().
alpha1
().
alpha0
().
alpha1
()
==
dend
)
end
=
true
;
// This is the only place swapping is called when inserting a constraint
helper
.
swapEdgeInList
<
TraitsType
,
DartType
>
(
it
,
elist
);
// If we, during look-ahead, found that dstart and/or dend were in the quadrilateral,
// we update them.
if
(
end
)
dend
=
*
it
;
if
(
start
)
{
dstart
=
*
it
;
dstart
.
alpha0
().
alpha2
();
}
if
(
swap_away
)
{
// !locked || //it should be sufficient with swap_away ???
noswap
++
;
erase
=
true
;
}
if
(
isTheConstraint
(
*
it
,
dstart
,
dend
))
{
// Move the constraint to the end of the list
DartType
the_constraint
=
*
it
;
elist
.
erase
(
it
);
elist
.
push_back
(
the_constraint
);
return
;
}
//endif
}
//endif
}
//endif "swappable edge"
// Move the edge to the end of the list if it was swapped away from the constraint
if
(
erase
)
{
used
=
it
;
elist
.
push_back
(
*
it
);
++
it
;
elist
.
erase
(
used
);
--
dartsInList
;
}
else
{
++
it
;
++
counter
;
}
}
//end while
if
(
noswap
==
0
)
locked
=
true
;
}
while
(
dartsInList
!=
0
);
#ifdef DEBUG_TTL_CONSTR
// We will never enter here. (If elist is empty, we return above).
cout
<<
"??????? ERROR 2, should never enter here ????????????????????????? SKIP ???? "
<<
endl
;
exit
(
-
1
);
#endif
}
};
// End of ConstrainedTriangulation class
};
// End of ttl_constr namespace scope
namespace
ttl
{
// (extension)
/** @name Constrained (Delaunay) Triangulation */
//@{
//------------------------------------------------------------------------------------------------
/** Inserts a constrained edge between two existing nodes in a triangulation.
* If the constraint falls on one or more existing nodes and this is detected by the
* predicate \c TraitsType::orient2d, which should return zero in this case, the
* constraint is split. Otherwise a degenerate triangle will be made along
* the constraint.
*
* \param dstart
* A CCW dart with the start node of the constraint as the source node
*
* \param dend
* A CCW dart with the end node of the constraint as the source node
*
* \param optimize_delaunay
* If set to \c true, the resulting triangulation will be
* a \e constrained \e Delaunay \e triangulation. If set to \c false, the resulting
* triangulation will not necessarily be of constrained Delaunay type.
*
* \retval DartType
* A dart representing the constrained edge.
*
* \require
* - \ref hed::TTLtraits::orient2d "TraitsType::orient2d" (DartType&, DartType&, PointType&)
* - \ref hed::TTLtraits::swapEdge "TraitsType::swapEdge" (DartType&)
*
* \using
* - optimizeDelaunay if \e optimize_delaunay is set to \c true
*
* \par Assumes:
* - The constrained edge must be inside the existing triangulation (and it cannot
* cross the boundary of the triangulation).
*/
template
<
class
TraitsType
,
class
DartType
>
DartType
TriangulationHelper
::
insertConstraint
(
DartType
&
dstart
,
DartType
&
dend
,
bool
optimize_delaunay
)
{
// Assumes:
// - It is the users responsibility to avoid crossing constraints
// - The constraint cannot cross the boundary, i.e., the boundary must be
// convex in the area of crossing edges.
// - dtart and dend are preserved (same node associated.)
// Find edges crossing the constraint and put them in elist.
// If findCrossingEdges reaches a Node lying on the constraint, this function
// calls itself recursively.
// RECURSION
std
::
list
<
DartType
>
elist
;
DartType
next_start
=
ttl_constr
::
ConstrainedTriangulation
::
findCrossingEdges
<
TraitsType
>
(
dstart
,
dend
,
elist
);
// If there are no crossing edges (elist is empty), we assume that the constraint
// is an existing edge.
// In this case, findCrossingEdges returns the constraint.
// Put the constraint in the list to fit with the procedures below
// (elist can also be empty in the case of invalid input data (the constraint is in
// a non-convex area) but this is the users responsibility.)
//by Thomas Sevaldrud if (elist.size() == 0)
//by Thomas Sevaldrud elist.push_back(next_start);
// findCrossingEdges stops if it finds a node lying on the constraint.
// A dart with this node as start node is returned
// We call insertConstraint recursivly until the received dart is dend
if
(
!
same_0_orbit
(
next_start
,
dend
))
{
#ifdef DEBUG_TTL_CONSTR_PLOT
cout
<<
"RECURSION due to collinearity along constraint"
<<
endl
;
#endif
insertConstraint
<
TraitsType
,
DartType
>
(
next_start
,
dend
,
optimize_delaunay
);
}
// Swap edges such that the constraint edge is present in the transformed triangulation.
if
(
elist
.
size
()
>
0
)
// by Thomas Sevaldrud
ttl_constr
::
ConstrainedTriangulation
::
transformToConstraint
<
TraitsType
>
(
dstart
,
next_start
,
elist
);
#ifdef DEBUG_TTL_CONSTR_PLOT
cout
<<
"size of elist = "
<<
elist
.
size
()
<<
endl
;
if
(
elist
.
size
()
>
0
)
{
DartType
the_constraint
=
elist
.
back
();
ofile_constr
<<
the_constraint
.
x
()
<<
" "
<<
the_constraint
.
y
()
<<
" "
<<
0
<<
endl
;
the_constraint
.
alpha0
();
ofile_constr
<<
the_constraint
.
x
()
<<
" "
<<
the_constraint
.
y
()
<<
" "
<<
0
<<
endl
<<
endl
;
}
#endif
// Optimize to constrained Delaunay triangulation if required.
typename
std
::
list
<
DartType
>::
iterator
end_opt
=
elist
.
end
();
if
(
optimize_delaunay
)
{
// Indicate that the constrained edge, which is the last element in the list,
// should not be swapped
--
end_opt
;
optimizeDelaunay
<
TraitsType
,
DartType
>
(
elist
,
end_opt
);
}
if
(
elist
.
size
()
==
0
)
// by Thomas Sevaldrud
return
next_start
;
// by Thomas Sevaldrud
// Return the constraint, which is still the last element in the list
end_opt
=
elist
.
end
();
--
end_opt
;
return
*
end_opt
;
}
//@} // End of Constrained Triangulation Group
};
// End of ttl namespace scope (extension)
#endif // _TTL_CONSTR_H_
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