T DDT2D::globalCostFunction ( Container <HalfEdge <T> *> &half_edges ) { // Compute cost of the triangulation using selected criterion const unsigned int n = half_edges.size(); T cost = 0; //Loop all edges for ( unsigned int i = 0; i < n; i++ ) { //Take half edge HalfEdge <T> *e = half_edges [i]; //Use simplex indentificator to eliminate T processing of the edge if ( !e->isSimplexEdge() ) { //Get the first triangle const HalfEdge <T> *e12 = e->getNextEdge(); const HalfEdge <T> *e13 = e12->getNextEdge(); //Does a twin edge exist? if ( e->getTwinEdge() ) { //Get coordinates of the first triangle const Point3DCartesian <T> *p11 = e->getPoint(); const Point3DCartesian <T> *p12 = e12->getPoint() ; const Point3DCartesian <T> *p13 = e13->getPoint() ; //Get second triangle HalfEdge <T> *e21 = e->getTwinEdge(); const HalfEdge <T> *e22 = e21->getNextEdge(); const HalfEdge <T> *e23 = e22->getNextEdge(); //Get coordinates const Point3DCartesian <T> *p21 = p12; const Point3DCartesian <T> *p22 = p11; const Point3DCartesian <T> *p23 = e23->getPoint(); //Compute local criterion T fi = ( *pcriterion ) ( p11, p12, p13, p21, p22, p23 ); //Global cost cost += fi; //Set both edges to be processed e->setEdgeAsSimplex ( true ); e21->setEdgeAsSimplex ( true ); } } } //Reset attribute for ( unsigned int i = 0; i < n; i++ ) { ( *half_edges ) [i]->setEdgeAsSimplex ( false ); } //Return global cost of the triangulation return cost; }
void DDT2D::DDTLOP ( Container <Node3DCartesian <T> *> &nl, Container <HalfEdge <T> *> &half_edges, unsigned short swap_criterion_selected, const bool print_message, const bool print_exception, std::ostream * output ) { // Data Depending triangulation using selected local criterion bool swap_exist = true; //Set iterations unsigned iterations = 0; //Create Delaunay triangulation DT2D::DT ( nl, half_edges, print_message ); //Get number of HalfEdges const unsigned int n = half_edges->size(); //Set local swap criterion setSwapCriterion ( swap_criterion_selected ); //Global cost before swapping const T global_cost_old = globalCostFunction ( half_edges ); T global_cost = global_cost_old; //Print info if ( print_message ) { *output << "> Starting DDTLOP... " ; } //Initialize counters unsigned int counter = MAX_INT, counter_old = MAX_INT; try { //Run until swap exists or decrease number of swaps between two loops do { //We suppose ordered set of triangles, no swap will be required swap_exist = false; //Remember old counter counter_old = counter; //Assign new counter value counter = 0; //Loop all edges for ( unsigned int i = 0; i < n; i++ ) { //Take half edge HalfEdge <T> *e = ( *half_edges ) [i]; //Use simplex flag to eliminate T processing of the edge if ( !e->isSimplexEdge() ) { //Does twin edge exist? if ( e->getTwinEdge() ) { // Test of convexity for quadrilateral HalfEdge <T> *e12 = e->getNextEdge(); HalfEdge <T> *e13 = e12->getNextEdge(); HalfEdge <T> *e21 = e->getTwinEdge(); HalfEdge <T> *e22 = e21->getNextEdge(); HalfEdge <T> *e23 = e22->getNextEdge(); // Get nodes, counterclockwise set of nodes const Node3DCartesian <T> *p1 = e->getPoint(); const Node3DCartesian <T> *p2 = e23->getPoint(); const Node3DCartesian <T> *p3 = e12->getPoint(); const Node3DCartesian <T> *p4 = e13->getPoint(); //Is convex (non convex can not be swapped) if ( ConvexQuadrilateral::isStrictlyConvex ( p1, p2, p3, p4 ) == 1 ) { //Set twin edge to be processed e->getTwinEdge()->setEdgeAsSimplex ( true ); //Get first triangle e12 = e->getNextEdge(); e13 = e12->getNextEdge(); //Get coordinates (cast to parent using static_cast) const Point3DCartesian <T> *p11 = e->getPoint(); const Point3DCartesian <T> *p12 = e12->getPoint(); const Point3DCartesian <T> *p13 = e13->getPoint(); //Get second triangle e21 = e->getTwinEdge(); e22 = e21->getNextEdge(); e23 = e22->getNextEdge(); //Get coordinates const Point3DCartesian <T> *p21 = p12; const Point3DCartesian <T> *p22 = p11; const Point3DCartesian <T> *p23 = e23->getPoint(); //Compute local criterion const T c1 = ( *pcriterion ) ( p11, p12, p13, p21, p22, p23 ); //Calculation local criterion from swapped diagonal const T c2 = ( *pcriterion ) ( p13, p11, p23, p12, p13, p23 ); //Swap diagonal if ( c2 < c1 ) { //Swap exists swap_exist = true; //Swap diagonal DT2D::swapDiagonal ( e, e12, e13, e21, e22, e23 ); counter++; } //Set both edges to be processed e->setEdgeAsSimplex ( true ); e21->setEdgeAsSimplex ( true ); } } } } //Set all edges as unused for ( unsigned int i = 0; i < n; i++ ) { //Take half edge HalfEdge <T> *e = ( *half_edges ) [i]; //Set edge not to be a simplex e->setEdgeAsSimplex ( false ); } //Number of iterations iterations ++; } while ( swap_exist ); //Global cost after swapping global_cost = globalCostFunction ( half_edges ); //Compute change ratio T ddt_ratio = 0; if ( global_cost != global_cost_old ) { ddt_ratio = 100 * ( global_cost - global_cost_old ) / global_cost_old; } //Print info if ( print_message ) { *output << "Completed..." << std::endl; *output << "> DT global cost old: " << global_cost_old << " DT global cost new: " << global_cost << ", ratio: " << ddt_ratio << "%" << std::endl; } } //Throw exception catch ( Error & error ) { if ( print_exception ) { error.printException ( output ); } //Delete lists half_edges->clear(); *output << "DDT construction cancelled..." << std::endl; throw; } }
float DDT2D::getInitialTemperature ( Container <HalfEdge <T> *> &half_edges ) { // Compute cost of the triangulation using selected criterion const unsigned int n = half_edges.size(); T max_difference = 0; ; //Loop all edges for ( unsigned int i = 0; i < n; i++ ) { //Take half edge HalfEdge <T> *e = half_edges [i]; if ( !e->isSimplexEdge() ) { //Get next edges const HalfEdge <T> *e12 = e->getNextEdge(); const HalfEdge <T> *e13 = e12->getNextEdge(); //Does a twin edge exist? if ( e->getTwinEdge() ) { //Get coordinates of the first triangle (cast to parent using static_cast) const Point3DCartesian <T> *p11 = e->getPoint(); const Point3DCartesian <T> *p12 = e12->getPoint(); const Point3DCartesian <T> *p13 = e13->getPoint(); //Get second triangle HalfEdge <T> *e21 = e->getTwinEdge(); HalfEdge <T> *e22 = e21->getNextEdge(); HalfEdge <T> *e23 = e22->getNextEdge(); //Get coordinates const Point3DCartesian <T> *p21 = p12; const Point3DCartesian <T> *p22 = p11; const Point3DCartesian <T> *p23 = e23->getPoint(); //Only strictly convex quadrilaterals if ( ConvexQuadrilateral::isStrictlyConvex ( p11, p23, p12, p13 ) == 1 ) { //Compute local criterion for adjacent triangles const T fi1 = ( *pcriterion ) ( p11, p12, p13, p21, p22, p23 ); //Compute local criterion for swapped triangles const T fi2 = ( *pcriterion ) ( p13, p23, p12, p23, p13, p11 ); //Find max difference if ( fabs ( fi2 - fi1 ) > max_difference ) { max_difference = fabs ( fi2 - fi1 ); } } //Set both edges to be processed e->setEdgeAsSimplex ( true ); e21->setEdgeAsSimplex ( true ); } } } //Reset attribute for ( unsigned int i = 0; i < n; i++ ) { ( *half_edges ) [i]->setEdgeAsSimplex ( false ); } //Return result return ( float ) ( 2 * max_difference ); }