Exemple #1
0
/*******************************************************************************
 *
 *                      Initialize Function
 *
 *******************************************************************************/
void initialize() {
    /**************************************************
     *  Setting up for Clock (PLL, M, N1, N2)
     *  for 32 MHz and Fcy = 16 MHz
     *************************************************/
    // Fosc = Fin(M/(N1*N2)) = 8 MHz (32/(2*4)) = 32 MHz
    PLLFBD = 30; // M = 32
    // N1 default is 2
    // N2 default is 4
    // Fcy = Fosc/2 by default

     // Setting up RD6 and RD7
    _TRISD6 = 1;
    _TRISD7 = 1;                                    // Set RD6 & 7 to inputs

    // Initialize LCD
    Init_LCD();

    lcd_cmd(0xD);

    // Making sure that we are starting at line 1, column 0
    home_it();
    // Print the LcdData1
    puts_lcd(LcdData1, sizeof(LcdData1)-1);
    // Move to next line
    line_2();
    // Print the LCDData2
    puts_lcd(LcdData2, sizeof(LcdData2)-1);
}
void LinkStatusWidget::initLines(){

    lines.clear();

    int lineLeft=this->left_left+this->left_width+this->left_space;
    int lineRight=this->width()-this->right_right;

    int centerHeight=this->right_top+this->right_height+this->right_space/2;

    QPoint p_left_left(lineLeft,centerHeight);
    QPoint p_left_right(lineRight,centerHeight);

    QLine line_1(p_left_left,p_left_right);

    int lineRightRight=this->width()-this->right_right+this->right_space;
    int lineRightTop=centerHeight- this->right_space/2-this->right_height/2;
    int lineRightBottom= centerHeight+this->right_space/2+this->right_height/2;

    QPoint p_right_top_left(lineRightRight,lineRightTop);
    QPoint p_right_top_right(lineRightRight,lineRightBottom);

    QLine line_2(p_right_top_left,p_right_top_right);

    lines.append(line_1);
    lines.append(line_2);


}
bool ParametricCurveTests::testProjectionBasedInterpolation()
{
  bool success = true;
  // to start with, project a line onto a linear basis
  shards::CellTopology line_2(shards::getCellTopologyData<shards::Line<2> >() );

  /////////////////// TEST LINEAR CURVES RECOVERED //////////////////////

  BasisPtr linearBasis = BasisFactory::basisFactory()->getBasis(1, line_2.getKey(), Camellia::FUNCTION_SPACE_HGRAD);

  double x0=3, y0=-3, x1=5, y1=4;
//  double dist = sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
  double dist = 1; // the length of the parametric space
  BasisCachePtr basisCache = BasisCache::basisCache1D(0, dist, linearBasis->getDegree()*2);
  ParametricCurvePtr myLine = ParametricCurve::line(x0, y0, x1, y1);

  bool useH1 = true;
  double lengthScale = 1.0;
  FieldContainer<double> basisCoefficients_x, basisCoefficients_y;
  myLine->projectionBasedInterpolant(basisCoefficients_x, linearBasis, 0, lengthScale, useH1);
  myLine->projectionBasedInterpolant(basisCoefficients_y, linearBasis, 1, lengthScale, useH1);

  if ( ! basisSumInterpolatesCurveEndPoints(basisCoefficients_x,basisCoefficients_y, linearBasis, myLine))
  {
    cout << "testProjectionBasedInterpolation() failed: projection-based interpolant doesn't interpolate line endpoints.\n";
    cout << "basisCoefficients_x:\n" << basisCoefficients_x;
    cout << "basisCoefficients_y:\n" << basisCoefficients_y;
    success = false;
  }

  // in fact, we should recover the line in x and y:
  if ( !basisSumEqualsFunction(basisCoefficients_x, linearBasis, myLine->x()) )
  {
    cout << "testProjectionBasedInterpolation() failed: projection-based interpolant doesn't recover the line in the x component.\n";
    success = false;
  }
  if ( !basisSumEqualsFunction(basisCoefficients_y, linearBasis, myLine->y()) )
  {
    cout << "testProjectionBasedInterpolation() failed: projection-based interpolant doesn't recover the line in the y component.\n";
    success = false;
  }

  /////////////////// TEST CUBIC CURVES RECOVERED //////////////////////
  FunctionPtr t = Function::xn(1);
  // define x and y as functions of t:
  FunctionPtr x_t = t*t*t-2*t;
  FunctionPtr y_t = t*t*t+8*t*t;

  ParametricCurvePtr myCurve = ParametricCurve::curve(x_t,y_t);

  BasisPtr cubicBasis = BasisFactory::basisFactory()->getBasis(3, line_2.getKey(), Camellia::FUNCTION_SPACE_HGRAD);

  myCurve->projectionBasedInterpolant(basisCoefficients_x, cubicBasis, 0, lengthScale, useH1);
  myCurve->projectionBasedInterpolant(basisCoefficients_y, cubicBasis, 1, lengthScale, useH1);

  // we should again recover the curve exactly:
  if ( !basisSumEqualsFunction(basisCoefficients_x, cubicBasis, myCurve->x()) )
  {
    cout << "testProjectionBasedInterpolation() failed: projection-based interpolant doesn't recover the cubic curve in the x component.\n";
    success = false;
  }
  if ( !basisSumEqualsFunction(basisCoefficients_y, cubicBasis, myCurve->y()) )
  {
    cout << "testProjectionBasedInterpolation() failed: projection-based interpolant doesn't recover the cubic curve in the y component.\n";
    success = false;
  }

  /////////////////// TEST UNRECOVERABLE CURVE INTERPOLATED //////////////////////

  // finally, project the cubic curve onto a quadratic basis, and check that it interpolates the endpoints
  BasisPtr quadraticBasis = BasisFactory::basisFactory()->getBasis(2, line_2.getKey(), Camellia::FUNCTION_SPACE_HGRAD);

  myCurve->projectionBasedInterpolant(basisCoefficients_x, quadraticBasis, 0, lengthScale, useH1);
  myCurve->projectionBasedInterpolant(basisCoefficients_y, quadraticBasis, 1, lengthScale, useH1);

  if ( ! basisSumInterpolatesCurveEndPoints(basisCoefficients_x,basisCoefficients_y, quadraticBasis, myCurve))
  {
    cout << "testProjectionBasedInterpolation() failed: quadratic projection-based interpolant doesn't interpolate cubic curve endpoints.\n";
    cout << "basisCoefficients_x:\n" << basisCoefficients_x;
    cout << "basisCoefficients_y:\n" << basisCoefficients_y;
    success = false;
  }

  return success;
}
bool ParametricCurveTests::testCircularArc()
{
  bool success = true;

  // the arc details are copied from CurvilinearMeshTests -- motivation is to diagnose test failure there with a more granular test here
  double radius = 1.0;
  double meshWidth = sqrt(2);

  ParametricCurvePtr circle = ParametricCurve::circle(radius, meshWidth / 2.0, meshWidth / 2.0);
  ParametricCurvePtr circularArc = ParametricCurve::subCurve(circle,  5.0/8.0, 7.0/8.0);

  BasisCachePtr basisCache = BasisCache::parametric1DCache(15); // overintegrate to be safe

  FunctionPtr cos_part = Teuchos::rcp( new Cos_ax(PI/2, 1.25*PI));
  FunctionPtr sin_part = Teuchos::rcp( new Sin_ax(PI/2, 1.25*PI));
  FunctionPtr x_t = meshWidth / 2 + cos_part;
  FunctionPtr y_t = meshWidth / 2 + sin_part;

  FunctionPtr dx_dt = (- PI / 2) * sin_part;
  FunctionPtr dy_dt = (PI / 2) * cos_part;

  double arcIntegral_x = circularArc->x()->integrate(basisCache);
  double x_t_integral = x_t->integrate(basisCache);

  // check that we have the right idea for all those functions:
  if (! x_t->equals(circularArc->x(),basisCache))
  {
    double x1_expected = Function::evaluate(x_t,1);
    double x1_actual;
    circularArc->xPart()->value(1,x1_actual);
    cout << "expected x(0) = " << x1_expected;
    cout << "; actual = " << x1_actual << endl;
    cout << "x part of circularArc doesn't match expected.\n";
    success = false;
  }
  if (! y_t->equals(circularArc->y(),basisCache))
  {
    double y1_actual;
    circularArc->yPart()->value(1,y1_actual);
    cout << "expected y(1) = " << Function::evaluate(y_t,1);
    cout << "; actual = " << y1_actual << endl;
    cout << "y part of circularArc doesn't match expected.\n";
    success = false;
  }

  if (! dx_dt->equals(circularArc->dt_parametric()->x(),basisCache))
  {
    cout << "dx/dt of circularArc doesn't match expected.\n";
    success = false;
  }
  if (! dy_dt->equals(circularArc->dt_parametric()->y(),basisCache))
  {
    cout << "dy/dt of circularArc doesn't match expected.\n";
    success = false;
  }

  // test exact curve at t=0.5

  double tol=1e-14;
  double t = 0.5;
  double x_expected = meshWidth / 2;
  double y_expected = meshWidth / 2 - radius;

  double x,y,xErr,yErr;
  // check value
  circularArc->value(t, x, y);
  xErr = abs(x-x_expected);
  yErr = abs(y-y_expected);
  if (xErr > tol)
  {
    cout << "exact arc x at t=0.5 is incorrect.\n";
    success = false;
  }
  if (yErr > tol)
  {
    cout << "exact arc y at t=0.5 is incorrect.\n";
    success = false;
  }

  // check derivatives
  // figuring out what the x derivative should be is a bit of work, I think,
  // but the y value is at a minimum, so its derivative should be zero
  y_expected = 0;
  circularArc->dt_parametric()->value(t, x, y);
  yErr = abs(y-y_expected);
  if (yErr > tol)
  {
    cout << "exact arc dy/dt at t=0.5 is nonzero.\n";
    success = false;
  }

  shards::CellTopology line_2(shards::getCellTopologyData<shards::Line<2> >() );
  BasisPtr quadraticBasis = BasisFactory::basisFactory()->getBasis(2, line_2.getKey(), Camellia::FUNCTION_SPACE_HGRAD);

  // figure out what the weights for the quadratic "middle node" basis function should be:
  double expected_H1_weight_x, expected_H1_weight_y;
  double expected_L2_weight_x, expected_L2_weight_y;

  FunctionPtr middleBasis;
  {
    FunctionPtr t = Function::xn(1);
    middleBasis = 4 * t * (1-t);
  }

  double middleBasisL2_squared = (middleBasis*middleBasis)->integrate(basisCache);
  double middleBasisH1_squared = ( middleBasis->dx() * middleBasis->dx() )->integrate(basisCache) + middleBasisL2_squared;

  ParametricCurvePtr circularArcBubble = ParametricCurve::bubble(circularArc);

  FunctionPtr bubble_x = circularArcBubble->x();
  FunctionPtr bubble_y = circularArcBubble->y();

  double x_against_middle_L2 = (bubble_x * middleBasis)->integrate(basisCache);
  double x_against_middle_H1 = (bubble_x->dx() * middleBasis->dx())->integrate(basisCache) + x_against_middle_L2;

  double y_against_middle_L2 = (bubble_y * middleBasis)->integrate(basisCache);
  double y_against_middle_H1 = (bubble_y->dx() * middleBasis->dx())->integrate(basisCache) + y_against_middle_L2;

  expected_L2_weight_x = x_against_middle_L2 / middleBasisL2_squared;
  expected_H1_weight_x = x_against_middle_H1 / middleBasisH1_squared;

  expected_L2_weight_y = y_against_middle_L2 / middleBasisL2_squared;
  expected_H1_weight_y = y_against_middle_H1 / middleBasisH1_squared;

  int middleBasisOrdinal = quadraticBasis->getDofOrdinal(1,0,0);

  FieldContainer<double> basisCoefficients_x, basisCoefficients_y;
  bool useH1 = false; // just trying to diagnose whether the issue is in derivatives or values (most likely derivatives)
  double lengthScale = 1.0;
  circularArcBubble->projectionBasedInterpolant(basisCoefficients_x, quadraticBasis, 0, lengthScale, useH1);
  circularArcBubble->projectionBasedInterpolant(basisCoefficients_y, quadraticBasis, 1, lengthScale, useH1);

  double weightError_x = abs(expected_L2_weight_x-basisCoefficients_x[middleBasisOrdinal]);
  double weightError_y = abs(expected_L2_weight_y-basisCoefficients_y[middleBasisOrdinal]);

  if (weightError_x > tol)
  {
    success = false;
    cout << "testCircularArc(): L2 projection doesn't match expected basis weight in x.\n";
    cout << "expected " << expected_L2_weight_x << ", was " << basisCoefficients_x[middleBasisOrdinal] << endl;
  }
  if (weightError_y > tol)
  {
    success = false;
    cout << "testCircularArc(): L2 projection doesn't match expected basis weight in y.\n";
    cout << "expected " << expected_L2_weight_y << ", was " << basisCoefficients_y[middleBasisOrdinal] << endl;
  }

  useH1 = true;
  circularArcBubble->projectionBasedInterpolant(basisCoefficients_x, quadraticBasis, 0, lengthScale, useH1);
  circularArcBubble->projectionBasedInterpolant(basisCoefficients_y, quadraticBasis, 1, lengthScale, useH1);

  weightError_x = abs(expected_H1_weight_x-basisCoefficients_x[middleBasisOrdinal]);
  weightError_y = abs(expected_H1_weight_y-basisCoefficients_y[middleBasisOrdinal]);

  if (weightError_x > tol)
  {
    success = false;
    cout << "testCircularArc(): H1 projection doesn't match expected basis weight in x.\n";
    cout << "expected " << expected_H1_weight_x << ", was " << basisCoefficients_x[middleBasisOrdinal] << endl;
  }
  if (weightError_y > tol)
  {
    success = false;
    cout << "testCircularArc(): H1 projection doesn't match expected basis weight in y.\n";
    cout << "expected " << expected_H1_weight_y << ", was " << basisCoefficients_y[middleBasisOrdinal] << endl;
  }
  /*
  FunctionPtr projection_x = BasisSumFunction::basisSumFunction(quadraticBasis, basisCoefficients_x);
  FunctionPtr projection_y = BasisSumFunction::basisSumFunction(quadraticBasis, basisCoefficients_y);

  FieldContainer<double> parametricPoint(1,1);
  parametricPoint[0] = t;
  FieldContainer<double> refPoint = basisCache->getRefCellPointsForPhysicalPoints(parametricPoint);
  basisCache->setRefCellPoints(refPoint);
  FieldContainer<double> value(1,1);
  projection_x->values(value, basisCache);
  x = value[0];
  projection_y->values(value, basisCache);
  y = value[0];

  // same expectations at the beginning, except of course now we don't expect to nail it.
  // but we do expect to be closer than the linear interpolation of the vertices
  x_expected = meshWidth / 2;
  y_expected = meshWidth / 2 - radius;

  double linearErr_x = 0; // linear interpolant nails the x value
  double linearErr_y = abs(y_expected);

  xErr = abs(x-x_expected);
  yErr = abs(y-y_expected);

  if (xErr > linearErr_x + tol) {
    cout << "quadratic projection-based interpolant has greater error in x than linear interpolant.\n";
    success = false;
  }
  if (yErr > linearErr_y + tol) {
    cout << "quadratic projection-based interpolant has greater error in y than linear interpolant.\n";
    success = false;
  }*/

  return success;
}
Exemple #5
0
/*******************************************************************************
 *
 *                      Main Function
 *
 *******************************************************************************/
int main() {
    // setting up everything
    initialize();
    int LcdCounter = 0;
    int LcdFlag = 0, LcdLine = 1;
    /*************** Main Loop ***********************************/
    while (1) {

        // Next press of RD6 = the printing of one char
        if ((_RD6 == 0) && (LcdFlag == 1))
        {
            if (LcdCounter < (sizeof(LcdData1)-1))
            {
                puts_lcd(&LcdData1[LcdCounter], 1);
                LcdCounter++;
            }
            if (LcdCounter >= (sizeof(LcdData1)- 1))
            {
                if ((LcdCounter == (sizeof(LcdData1) - 1 )) && (LcdLine = 1))
                {
                    line_2();
                    LcdLine = 2;
                }

                else if (LcdCounter <= ((sizeof(LcdData1) + sizeof(LcdData2)) -2))
                {
                    puts_lcd(&LcdData2[(LcdCounter - sizeof(LcdData1))], 1);
                    LcdCounter++;
                }
            }
            Delay_Us(1000);                                  // Debouncing
        }
        // First press of RD6 = clear the screen
        if ((_RD6 == 0) && (LcdFlag == 0))
        {
            home_clr();
            home_it();
            LcdFlag = 1;
            Delay_Us(1000);                                 // Debouncing
        }

        // If RD7 was pressed
        if ((_RD7 == 0))
        {
            if ((LcdCounter == sizeof(LcdData1)) && (LcdLine == 2))
            {
                lcd_cmd(0x8F);
                puts_lcd(&LcdSpace, 1);
                lcd_cmd(0x8F);
                LcdCounter--;
//                LcdLine = 1;
            }
            else
            {
                cursor_left();
                puts_lcd(&LcdSpace, 1);
                cursor_left();
                LcdCounter--;
            }


            Delay_Us(1000);                                 // Debouncing
        }

    } // End of the infinite While loop

    return 1;
}
//
// removes the given vertex and retriangulates the hole which would be made
//
// The method returns true if the vertex has been removed and false if the vertex has been retained.
//
bool MeshEx::removeVertexAndReTriangulateNeighbourhood( Vertex *v )
{
	std::vector<MeshEx::Edge *>                                          boundaryEdges; // boundary edges which form the polygon which has to be triangulated
	std::vector<MeshEx::Edge *>                                          criticalEdges; // edges which are not only connected to other vertices of the vertexring through boundary edges
	std::map<MeshEx::Vertex *, EdgeInfoHelper>                            boundaryRing; // maps incomming and outgoing edge to each vertex of the boundary vertex-ring



	// gather and prepare information ------------------------------------------------
	for( std::vector<Triangle *>::iterator it = v->triangleRing.begin(); it != v->triangleRing.end(); ++it )
	{
		Triangle *t = (*it);

		Edge *boundaryEdge = t->getOtherEdge( v );

		boundaryRing[boundaryEdge->v1].registerEdge( boundaryEdge );
		boundaryRing[boundaryEdge->v2].registerEdge( boundaryEdge );

		boundaryEdges.push_back( boundaryEdge );
	}


	// align the edges so that for each vertex e1 is the incomming and e2 is the outgoing edge
	Vertex *first = boundaryRing.begin()->first;
	Vertex *current = first;
	Vertex *next = 0;
	Vertex *prev = 0;
	
	do
	{
		// we have to be sure that each boundaryRing Vertex has an incomming and outgoing edge
		if( !boundaryRing[current].e1 || !boundaryRing[current].e2 )
		{
			printf( "error : edge ring around vertex not closed boundary vertex has less than 2 edges (polygon hole?)\n" );
			//++g_iterations;
			return false;
		}

		boundaryRing[current].setVertex( current );

		next = boundaryRing[current].next;

		if( boundaryRing[next].e1 != boundaryRing[current].e2 )
			boundaryRing[next].swap();

		current = next;
	}while( current != first );

	// we have to collect all edges going out from the vertex-ring vertices which are connected to
	// other vertices of the vertex ring - these will later be used for consistency check #2 (see chapter 4.4 of the paper)
	// for each vertex of the vertex Ring V
	for( std::map<Vertex *, EdgeInfoHelper>::iterator it = boundaryRing.begin(); it != boundaryRing.end(); ++it )
	{
		Vertex *rv       = it->first; // current vertex of the vertex ring

		// for each triangle referencing rv...
		for( std::vector<Triangle *>::iterator tit = rv->triangleRing.begin(); tit != rv->triangleRing.end(); ++tit )
		{
			Triangle *rv_tri = *tit;

			// ... which doesnt belong to the triangleRing of v
			if( std::find( v->triangleRing.begin(), v->triangleRing.end(), rv_tri ) == v->triangleRing.end() )
			{
				// collect the edges containing rv...
				for( size_t i=0; i<3; ++i )
					if( rv_tri->e[i]->contains(rv) )
						// ...and dont belong to the edgeRing list
						if( std::find( boundaryEdges.begin(), boundaryEdges.end(), rv_tri->e[i] ) == boundaryEdges.end() )
							// store the edge if the node on the other side references another vertex of the vertex-ring
							if( boundaryRing.find( rv_tri->e[i]->getOtherVertex(rv) ) != boundaryRing.end() )
								criticalEdges.push_back( rv_tri->e[i] );

			}
		}
	}

	// remove duplicate entries
	std::sort( criticalEdges.begin(), criticalEdges.end() );
	criticalEdges.erase( std::unique(criticalEdges.begin(), criticalEdges.end()), criticalEdges.end() );

	// Now we will project the neighbourhood of v onto a plane so that we can employ the greedy
	// triangulation. For this we will have to find a projection of the neighbourhood of v so that
	// no edges intersect on that plane. If they would, then the greedy triangulation would introduce
	// folds which means that the topology would be destroyed.
	// Looking for a working projection may lead to a number of projection-trials. For the first try
	// we will take the plane to be the plane defined by the normal of v and (its distance to the origin).
	// This will do the job most of the time.
	math::Vec3f                           normal; // direction of the projection plane
	math::Vec3f                            base1; // base vector which builds the 2d-coordinate system
	math::Vec3f                            base2; // base vector which builds the 2d-coordinate system
	float                               distance; // distance of the plane to the origin
	CGAL::Orientation boundaryPolygonOrientation; // orientation (clockwise/counterclockwise of the boundary polyon)

	distance = -math::dotProduct( v->position, normal );

	size_t   trialCount = 13; // only one trial for now
	size_t currentTrial = 0;
	bool    success = true;
	do
	{
		// we assume that we will be successfull
		success = true;

		switch(currentTrial)
		{
		case 0:
			// first trial: we take the plane defined by the normal of v
			normal = v->normal;
			break;
		// for all other trials we will try one of 12 different directions
		case  1:normal = math::normalize( math::Vec3f( .8507f, .4472f, .2764f ));break;
		case  2:normal = math::normalize( math::Vec3f( -.8507f, .4472f, .2764f ));break;
		case  3:normal = math::normalize( math::Vec3f( .8507f, -.4472f, -.2764f ));break;
		case  4:normal = math::normalize( math::Vec3f( -.8507f, -.4472f, -.2764f ));break;
		case  5:normal = math::normalize( math::Vec3f( .5257f, -.4472f, .7236f ));break;
		case  6:normal = math::normalize( math::Vec3f( .5257f, .4472f, -.7236f ));break;
		case  7:normal = math::normalize( math::Vec3f( -.5257f, -.4472f, .7236f ));break;
		case  8:normal = math::normalize( math::Vec3f( -.5257f, .4472f, -.7236f ));break;
		case  9:normal = math::normalize( math::Vec3f( .0f, .4472f, .8944f ));break;
		case 10:normal = math::normalize( math::Vec3f( .0f, -1.0f, .0f ));break;
		case 11:normal = math::normalize( math::Vec3f( .0f, 1.0f, .0f ));break;
		case 12:normal = math::normalize( math::Vec3f( .0f, -.4472f, -.8944f ));break;
		};

		// compute the basis of the 2d-coordinate system of the plane defined by current normal
		base1 = math::normalize( math::projectPointOnPlane( normal, distance, boundaryRing.begin()->first->position ) - v->position );
		base2 = math::normalize( math::crossProduct( normal, base1 ) );


		// project neighbours into the given plane
		for( std::map<Vertex *, EdgeInfoHelper>::iterator it = boundaryRing.begin(); it != boundaryRing.end(); ++it )
			it->second.projected = _get2d( base1, base2, math::projectPointOnPlane( normal, distance, it->first->position ) );

		// topologic constistency check #1 (see chapter 4.4 of the paper)
		// now do the consistency check: test if all edges dont intersect and dont lie over each other
		// if any edge between the projected vertices intersect -> success = false
		// test each projected edge of the edge ring against each other edge
		for( std::vector<Edge *>::iterator it1 = boundaryEdges.begin(); it1 != boundaryEdges.end() - 1; ++it1 )
		{
			for( std::vector<Edge *>::iterator it2 = it1+1; it2 != boundaryEdges.end(); ++it2 )
			{
				Edge *e1 = *it1;
				Edge *e2 = *it2;
				math::Vec3f intersectionPoint;

				// skip if the 2 lines share a common vertex
				if( e2->contains(e1->v1) || e2->contains(e1->v2) )
					continue;

				math::Vec2f e1_v1_projected = boundaryRing[e1->v1].projected;
				math::Vec2f e1_v2_projected = boundaryRing[e1->v2].projected;
				math::Vec2f e2_v1_projected = boundaryRing[e2->v1].projected;
				math::Vec2f e2_v2_projected = boundaryRing[e2->v2].projected;

				CGAL::Segment_2<K> line_1( Point( e1_v1_projected.x, e1_v1_projected.y ), Point(e1_v2_projected.x, e1_v2_projected.y) );
				CGAL::Segment_2<K> line_2( Point( e2_v1_projected.x, e2_v1_projected.y ), Point(e2_v2_projected.x, e2_v2_projected.y) );

				if( CGAL::do_intersect( line_1, line_2 ) )
				{
					success = false;
					break;
				}
			}

			if( !success )
				break;
		}


		if( success )
		{
			//
			// now we do the topology consistency check #2 (see chapter 4.4 of the paper)
			// this is done by checking all critical edges whether they cross the interior of the
			// polygon boundary which is formed by the projected vertex ring vertices
			// to do this we create the 2 polygongs which can be made by using the edge as a divider
			// the line crosses the interior if both polgons have a counterclockwise orientation
			//
			for( std::vector<Edge *>::iterator it = criticalEdges.begin(); it != criticalEdges.end(); ++it )
			{
				Edge *criticalEdge = *it;


				// setup left polygon
				// start from v1 and go to v2
				Polygon leftPoly;

				prev = 0;
				current = criticalEdge->v1;
				do
				{
					leftPoly.push_back( current, boundaryRing[current].projected );
					prev = current;
					current = boundaryRing[current].next;

				}while( current != criticalEdge->v2 );
				leftPoly.push_back( current, boundaryRing[current].projected );


				// setup right polygon
				// start from v2 and go to v1
				Polygon rightPoly;

				prev = 0;
				current = criticalEdge->v2;
				do
				{
					rightPoly.push_back( current, boundaryRing[current].projected );
					prev = current;
					current = boundaryRing[current].next;

				}while( current != criticalEdge->v1 );
				rightPoly.push_back( current, boundaryRing[current].projected );


				// if orientations of both polygons are the same then the critical edge crosses the bounding polygon interior
				if( leftPoly.orientation() == rightPoly.orientation() )
				{
					printf( "info : unable to triangulate since critical edge(es) would cross the polygon interior - vertex is not removed\n" );

					success = false;
					break;
				}
			}
		}
	}while( (++currentTrial < trialCount)&&(!success) );

	
	if( !success )
	{
		// we dont remove the vertex since we didnt managed to find a planar
		// projection of the neighbourhood which would not destroy the topology
		printf( "info : unable to find planar projection for vertex remove and retriangulation - vertex is not removed\n" );
		//++g_iterations;
		return false;
	}

	boundaryPolygonOrientation = CGAL::orientation( Point_3( v->position ), Point_3( v->position + base1 ), Point_3( v->position + base2 ), Point_3( v->position + normal ) );



	// execute the result ------------------------------------------------------------

	// remove vertex v and the triangle ring around v
	removeVertex( v );


	// compute squared distances
	
	// compute the squared distances of all point pairs
	std::vector<DistanceHelper> sqDistances;  // sorted distances of each pair of points
	for( std::map<Vertex *, EdgeInfoHelper>::iterator it1 = boundaryRing.begin(); it1 != boundaryRing.end(); ++it1 )
		for( std::map<Vertex *, EdgeInfoHelper>::iterator it2 = it1; it2 != boundaryRing.end(); ++it2 )
		{
			Vertex *v1 = it1->first;
			Vertex *v2 = it2->first;

			if( v1 == v2 )
				continue;

			// we dont want to add pairs, which would build a boundary edge, since those
			// already exist -> simply check for next or prev vertex in boundaryRing
			if( (boundaryRing[v1].next == v2)||(boundaryRing[v1].prev == v2) )
				continue;


			sqDistances.push_back( DistanceHelper( it1->first, it2->first ) );
		}

	// sort
	std::sort( sqDistances.begin(), sqDistances.end() );


	//
	std::list<Polygon *>                                                polygons; // polygons which have to be triangulated
	std::vector<Edge *>        edges( boundaryEdges.begin(), boundaryEdges.end() ); // created edges

	// create polygon which is made by the boundary edges and put it on polygon list
	Polygon *boundaryPolygon = new Polygon();


	first = boundaryRing.begin()->first;
	current = first;
	prev = 0;

	do
	{
		boundaryPolygon->push_back( current, boundaryRing[current].projected );
		prev = current;
		current = boundaryRing[current].next;
	}while( current != first );

	if( boundaryPolygon->orientation() != boundaryPolygonOrientation )
		boundaryPolygon->flip();


	polygons.push_back( boundaryPolygon );

	// for each entry in the sqDistance list
	//     find the polygon on the polygon list which contains h->v1 and h->v2
	//     check if edge is outside the polygon by checking the orientations of the left and right sides (build left and right polygons)
	//     check if edge intersects with any other existing edge which dont have a point in h->v1 or h->v2
	//     if checks pass:
	//         create edge -> assign it to the left and right polygons | add it to the list of edges
	//         split the polygon by removing the polygon from polygon list and putting the left and right polygons on the list if it is not a triangle
	//     
	// if the any polygon remains on the polygon list, throw an error that the triangulation has created a hole in the mesh
	//std::vector<Edge *> edges( edgeRing.begin(), edgeRing.end() );

	// when the mother polygon is already a triangle, then we have sqDistances.size() == 0
	// and we have to handle the polygon
	if( boundaryPolygon->isTriangle() )
	{
		createTriangle( boundaryPolygon->vertices[0], boundaryPolygon->vertices[1], boundaryPolygon->vertices[2], edges );
		polygons.clear();
		delete boundaryPolygon;

		//++g_iterations;
		return true;

	}


	for( std::vector<DistanceHelper>::iterator it=sqDistances.begin(); it != sqDistances.end(); ++it )
	{
		DistanceHelper *h = &(*it);

		Polygon *poly = 0; // polygon which contains both vertices of h

		std::list<Polygon *>::iterator pit;

		// find the polygon which contains both vertices of h
		for( pit = polygons.begin(); pit != polygons.end(); ++pit )
		{
			Polygon *p = *pit;
			if( p->contains( h->v1 ) && p->contains( h->v2 ) )
			{
				poly = p;
				break;
			}
		}

		// if no polygon could be found which contains both vertices of h, then
		// we can skip this one
		if( !poly )
			continue;

		// test for intersection with all existing edges
		bool intersection = false;
		for( std::vector<Edge *>::iterator eit = edges.begin(); eit != edges.end(); ++eit)
		{
			Edge *e = (*eit);

			math::Vec3f intersectionPoint;

			// ---- test for intersection of the edges projected into 2d plane using cgal ----
			// skip if the 2 lines share a common vertex
			if( e->contains(h->v1) || e->contains(h->v2) )
				continue;

			CGAL::Segment_2<K> line_1( Point( boundaryRing[e->v1].projected.x, boundaryRing[e->v1].projected.y ), Point(boundaryRing[e->v2].projected.x, boundaryRing[e->v2].projected.y) );
			CGAL::Segment_2<K> line_2( Point( boundaryRing[h->v1].projected.x, boundaryRing[h->v1].projected.y ), Point(boundaryRing[h->v2].projected.x, boundaryRing[h->v2].projected.y) );

			if( CGAL::do_intersect( line_1, line_2 ) )
			{
				intersection = true;
				break;
			}
		}

		// if there was an intersection, then we can skip this one
		// since a non-compatible edge would be introduced
		if( intersection )
			continue;

		// no intersection, get the 2 polygons which would be created from dividing the mother polyon along the edge
		Polygon *left, *right;

		left = right = 0;

		poly->split( left, right, h->v1, h->v2 );

		// if the 2 polygons have the same orientation, then we can be sure that
		// the edge goes through the interior of the polygon

		if( left->orientation() == right->orientation() )
		{

			// remove the current polygon from the list of polygons
			polygons.erase( pit );
			delete poly;

			// create the edge h->v1 -> h->v2
			Edge *edge = createEdge( h->v1, h->v2 );

			edges.push_back( edge );

			// and add the left and righ polygon to the list if they are not triangles
			if( left->isTriangle() )
			{
				// add triangle to the mesh
				createTriangle( left->vertices[0], left->vertices[1], left->vertices[2], edges );

				// remove polygon helper structure
				delete left;
			}else
				polygons.push_back( left );

			if( right->isTriangle() )
			{
				// add triangle to the mesh
				createTriangle( right->vertices[0], right->vertices[1], right->vertices[2], edges );

				// remove polygon helper structure
				delete right;
			}else
				polygons.push_back( right );
		}else
		{
			delete left;
			delete right;
		}
	}

	if( !polygons.empty() )
		printf( "error : hole created during retriangulation\n" );

	for( std::list<Polygon *>::iterator pit = polygons.begin(); pit != polygons.end(); ++pit )
		delete *pit;
	polygons.clear();


	//++g_iterations;
	return true;
}