From 657ac76bbf29693e8ff3ecd21bc1fd02611be4b6 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 13 Mar 2014 18:50:52 +0100 Subject: [PATCH] Fixes build error with the choosy CLANG (Thanks to Maciej Suminski) --- include/ttl/ttl.h | 11 +- include/ttl/ttl_constr.h | 635 --------------------------------------- 2 files changed, 1 insertion(+), 645 deletions(-) delete mode 100644 include/ttl/ttl_constr.h diff --git a/include/ttl/ttl.h b/include/ttl/ttl.h index 7d7c655843..7de2e7b08d 100644 --- a/include/ttl/ttl.h +++ b/include/ttl/ttl.h @@ -357,7 +357,7 @@ private: ForwardIterator it; for (it = first; it != last; ++it) { - bool status = insertNode(dart, **it); + insertNode(dart, **it); } } @@ -1914,13 +1914,4 @@ passes: }; // End of ttl namespace scope (but other files may also contain functions for ttl) - - //------------------------------------------------------------------------------------------------ - // ----------------------------- Constrained Triangulation Group -------------------------------- - //------------------------------------------------------------------------------------------------ - - // Still namespace ttl - -#include - #endif // _TTL_H_ diff --git a/include/ttl/ttl_constr.h b/include/ttl/ttl_constr.h deleted file mode 100644 index 125bddeb23..0000000000 --- a/include/ttl/ttl_constr.h +++ /dev/null @@ -1,635 +0,0 @@ -/* - * 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 - * . - * - * 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 -#include - - -// Debugging -#ifdef DEBUG_TTL_CONSTR_PLOT - #include - 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 - 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 - 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 - 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 - static DartType findCrossingEdges(const DartType& dstart, const DartType& dend, ListType& elist) { - - const DartType my_start = getAtSmallestAngle(dstart, dend); - DartType my_end = getAtSmallestAngle(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 - void transformToConstraint(ttl::TriangulationHelper helper, DartType& dstart, DartType& dend, - std::list& elist) const { - - typename std::list::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(*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(dstart, dend, *it, tmp) && - !crossesConstraint(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(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 - 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 elist; - DartType next_start = ttl_constr::ConstrainedTriangulation::findCrossingEdges(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(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(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::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(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_