Ejemplo n.º 1
0
bool Polygon::convertToInequalityConstraints(Eigen::MatrixXd& A, Eigen::VectorXd& b) const
{
  Eigen::MatrixXd V(nVertices(), 2);
  for (unsigned int i = 0; i < nVertices(); ++i)
    V.row(i) = vertices_[i];

  // Create k, a list of indices from V forming the convex hull.
  // TODO: Assuming counter-clockwise ordered convex polygon.
  // MATLAB: k = convhulln(V);
  Eigen::MatrixXi k;
  k.resizeLike(V);
  for (unsigned int i = 0; i < V.rows(); ++i)
    k.row(i) << i, (i+1) % V.rows();
  Eigen::RowVectorXd c = V.colwise().mean();
  V.rowwise() -= c;
  A = Eigen::MatrixXd::Constant(k.rows(), V.cols(), NAN);

  unsigned int rc = 0;
  for (unsigned int ix = 0; ix < k.rows(); ++ix) {
    Eigen::MatrixXd F(2, V.cols());
    F.row(0) << V.row(k(ix, 0));
    F.row(1) << V.row(k(ix, 1));
    Eigen::FullPivLU<Eigen::MatrixXd> luDecomp(F);
    if (luDecomp.rank() == F.rows()) {
      A.row(rc) = F.colPivHouseholderQr().solve(Eigen::VectorXd::Ones(F.rows()));
      ++rc;
    }
  }

  A = A.topRows(rc);
  b = Eigen::VectorXd::Ones(A.rows());
  b = b + A * c.transpose();

  return true;
}
Ejemplo n.º 2
0
 std::vector<carve::geom::vector<2> > Face<ndim>::projectedVertices() const {
   p2_adapt_project<ndim> proj = projector();
   std::vector<carve::geom::vector<2> > result;
   result.reserve(nVertices());
   for (size_t i = 0; i < nVertices(); ++i) {
     result.push_back(proj(vertex(i)->v));
   }
   return result;
 }
Ejemplo n.º 3
0
    Face<ndim> *Face<ndim>::init(const Face<ndim> *base, iter_t vbegin, iter_t vend, bool flipped) {
      CARVE_ASSERT(vbegin < vend);

      vertices.reserve((size_t)std::distance(vbegin, vend));

      if (flipped) {
        std::reverse_copy(vbegin, vend, std::back_inserter(vertices));
        plane_eqn = -base->plane_eqn;
      } else {
        std::copy(vbegin, vend, std::back_inserter(vertices));
        plane_eqn = base->plane_eqn;
      }

      edges.clear();
      edges.resize(nVertices(), NULL);

      aabb.fit(vertices.begin(), vertices.end(), vec_adapt_vertex_ptr());
      untag();

      int da = carve::geom::largestAxis(plane_eqn.N);

      project = getProjector(plane_eqn.N.v[da] > 0, da);
      unproject = getUnprojector(plane_eqn.N.v[da] > 0, da);

      return this;
    }
Ejemplo n.º 4
0
void tDxfSpline::refresh()
{
    hs->removeAllVertices();
    /*
    for (int i=0; i<nVertices(); i++){
        hs->addVertex(vertex(i));
    }*/

    if (nVertices()>2){
        UpdateControlPoints();
        updateXX();
    }
    /*
    if (data.degree<1 || data.degree>3) {
        RS_DEBUG->print("RS_Spline::update: invalid degree: %d", data.degree);
        return;
    }

    if (data.controlPoints.size() < data.degree+1) {
        RS_DEBUG->print("RS_Spline::update: not enough control points");
        return;
    }
*/
    // controlpoints berechnen.
}
Ejemplo n.º 5
0
void Mesh::addRow()
{
    // Create new vertices 2d (temporary).
    IndexVector2d newVertices2d;
    resizeVertices2d(newVertices2d, nColumns(), nRows()+1);

    // Top displacement of points already there.
    qreal topMoveProp = 1.0f/(nRows()-1) - 1.0f/nRows();

    // Add a point at each row.
    int k = nVertices();
    for (int x=0; x<nColumns(); x++)
    {
        // Get left and right vertices.
        QPointF top    = getVertex2d(x, 0);
        QPointF bottom = getVertex2d(x, nRows()-1);
        QPointF diff   = bottom - top;

        // First pass: move middle points.
        for (int y=1; y<nRows()-1; y++)
        {
            QPointF p = getVertex2d(x, y);
            p -= diff * y * topMoveProp;
            _rawSetVertex( _vertices2d[x][y], p );
        }

        // Create and add new point.
        QPointF newPoint = bottom - diff * 1.0f/nRows();
        _addVertex(newPoint);

        // Assign new vertices 2d.
        for (int y=0; y<nRows()-1; y++)
            newVertices2d[x][y] = _vertices2d[x][y];

        // The new point.
        newVertices2d[x][nRows()-1] = k;

        // The rightmost point.
        newVertices2d[x][nRows()]   = _vertices2d[x][nRows()-1];

        k++;
    }

    // Copy new mapping.
    _vertices2d = newVertices2d;

    // Increment number of columns.
    _nRows++;

    // Reorder.
    _reorderVertices();
}
Ejemplo n.º 6
0
// vertices 0..3 = 4 corners
//
void Mesh::addColumn()
{
    // Create new vertices 2d (temporary).
    IndexVector2d newVertices2d;
    resizeVertices2d(newVertices2d, nColumns()+1, nRows());

    // Left displacement of points already there.
    qreal leftMoveProp = 1.0f/(nColumns()-1) - 1.0f/nColumns();

    // Add a point at each row.
    int k = nVertices();
    for (int y=0; y<nRows(); y++)
    {
        // Get left and right vertices.
        QPointF left  = getVertex2d( 0,            y );
        QPointF right = getVertex2d( nColumns()-1, y );
        QPointF diff  = right - left;

        // First pass: move middle points.
        for (int x=1; x<nColumns()-1; x++)
        {
            QPointF p = getVertex2d(x, y);
            p -= diff * x * leftMoveProp;
            _rawSetVertex( _vertices2d[x][y], p );
        }

        // Create and add new point.
        QPointF newPoint = right - diff * 1.0f/nColumns();
        _addVertex(newPoint);

        // Assign new vertices 2d.
        for (int x=0; x<nColumns()-1; x++)
            newVertices2d[x][y] = _vertices2d[x][y];

        // The new point.
        newVertices2d[nColumns()-1][y] = k;

        // The rightmost point.
        newVertices2d[nColumns()][y]   = _vertices2d[nColumns()-1][y];

        k++;
    }

    // Copy new mapping.
    _vertices2d = newVertices2d;

    // Increment number of columns.
    _nColumns++;

    // Reorder.
    _reorderVertices();
}
Ejemplo n.º 7
0
void MShape::write(QDomElement& obj)
{
  // Write basic data.
  Serializable::write(obj);

  // Write vertices.
  QDomElement verticesObj = obj.ownerDocument().createElement("vertices");
  for (int i=0; i<nVertices(); i++)
  {
    QDomElement vertexObj = obj.ownerDocument().createElement("vertex");
    vertexObj.setAttribute("x", QString::number(getVertex(i).x()));
    vertexObj.setAttribute("y", QString::number(getVertex(i).y()));
    verticesObj.appendChild(vertexObj);
  }

  obj.appendChild(verticesObj);
}
Ejemplo n.º 8
0
bool Polygon::offsetInward(const double margin)
{
  // Create a list of indices of the neighbours of each vertex.
  // TODO: Assuming counter-clockwise ordered convex polygon.
  std::vector<Eigen::Array2i> neighbourIndices;
  const unsigned int n = nVertices();
  neighbourIndices.resize(n);
  for (unsigned int i = 0; i < n; ++i) {
    neighbourIndices[i] << (i > 0 ? (i-1)%n : n-1), (i + 1) % n;
  }

  std::vector<Position> copy(vertices_);
  for (unsigned int i = 0; i < neighbourIndices.size(); ++i) {
    Eigen::Vector2d v1 = vertices_[neighbourIndices[i](0)] - vertices_[i];
    Eigen::Vector2d v2 = vertices_[neighbourIndices[i](1)] - vertices_[i];
    v1.normalize();
    v2.normalize();
    const double angle = acos(v1.dot(v2));
    copy[i] += margin / sin(angle) * (v1 + v2);
  }
  vertices_ = copy;
  return true;
}
Ejemplo n.º 9
0
void MayaNurbsCurveWriter::write()
{
    Alembic::AbcGeom::OCurvesSchema::Sample samp;
    samp.setBasis(Alembic::AbcGeom::kBsplineBasis);

    MStatus stat;
    mCVCount = 0;

    // if inheritTransform is on and the curve group is animated,
    // bake the cv positions in the world space
    MMatrix exclusiveMatrixInv = mRootDagPath.exclusiveMatrixInverse(&stat);

    std::size_t numCurves = 1;

    if (mIsCurveGrp)
        numCurves = mNurbsCurves.length();

    std::vector<Alembic::Util::int32_t> nVertices(numCurves);
    std::vector<float> points;
    std::vector<float> width;
    std::vector<float> knots;
    std::vector<Alembic::Util::uint8_t> orders(numCurves);

    MMatrix transformMatrix;
    bool useConstWidth = false;

    MFnDependencyNode dep(mRootDagPath.transform());
    MPlug constWidthPlug = dep.findPlug("width");

    if (!constWidthPlug.isNull())
    {
        useConstWidth = true;
        width.push_back(constWidthPlug.asFloat());
    }

    for (unsigned int i = 0; i < numCurves; i++)
    {
        MFnNurbsCurve curve;
        if (mIsCurveGrp)
        {
            curve.setObject(mNurbsCurves[i]);
            MMatrix inclusiveMatrix = mNurbsCurves[i].inclusiveMatrix(&stat);
            transformMatrix = inclusiveMatrix*exclusiveMatrixInv;
        }
        else
        {
            curve.setObject(mRootDagPath.node());
        }

        if (i == 0)
        {
            if (curve.form() == MFnNurbsCurve::kOpen)
            {
                samp.setWrap(Alembic::AbcGeom::kNonPeriodic);
            }
            else
            {
                samp.setWrap(Alembic::AbcGeom::kPeriodic);
            }

            if (curve.degree() == 3)
            {
                samp.setType(Alembic::AbcGeom::kCubic);
            }
            else if (curve.degree() == 1)
            {
                samp.setType(Alembic::AbcGeom::kLinear);
            }
            else
            {
                samp.setType(Alembic::AbcGeom::kVariableOrder);
            }
        }
        else
        {
            if (curve.form() == MFnNurbsCurve::kOpen)
            {
                samp.setWrap(Alembic::AbcGeom::kNonPeriodic);
            }

            if ((samp.getType() == Alembic::AbcGeom::kCubic &&
                curve.degree() != 3) ||
                (samp.getType() == Alembic::AbcGeom::kLinear &&
                curve.degree() != 1))
            {
                samp.setType(Alembic::AbcGeom::kVariableOrder);
            }
        }

        orders[i] = static_cast<Alembic::Util::uint8_t>(curve.degree() + 1);

        Alembic::Util::int32_t numCVs = curve.numCVs(&stat);

        MPointArray cvArray;
        stat = curve.getCVs(cvArray, MSpace::kObject);

        mCVCount += numCVs;
        nVertices[i] = numCVs;

        for (Alembic::Util::int32_t j = 0; j < numCVs; j++)
        {
            MPoint transformdPt;
            if (mIsCurveGrp)
            {
                transformdPt = cvArray[j]*transformMatrix;
            }
            else
            {
                transformdPt = cvArray[j];
            }

            points.push_back(static_cast<float>(transformdPt.x));
            points.push_back(static_cast<float>(transformdPt.y));
            points.push_back(static_cast<float>(transformdPt.z));
        }

        MDoubleArray knotsArray;
        curve.getKnots(knotsArray);
        knots.reserve(knotsArray.length() + 2);

        // need to add a knot to the start and end (M + 2N + 1)
        if (knotsArray.length() > 1)
        {
            unsigned int knotsLength = knotsArray.length();
            if (knotsArray[0] == knotsArray[knotsLength - 1] ||
                knotsArray[0] == knotsArray[1])
            {
                knots.push_back(knotsArray[0]);
            }
            else
            {
                knots.push_back(2 * knotsArray[0] - knotsArray[1]);
            }

            for (unsigned int j = 0; j < knotsLength; ++j)
            {
                knots.push_back(knotsArray[j]);
            }

            if (knotsArray[0] == knotsArray[knotsLength - 1] ||
                knotsArray[knotsLength - 1] == knotsArray[knotsLength - 2])
            {
                knots.push_back(knotsArray[knotsLength - 1]);
            }
            else
            {
                knots.push_back(2 * knotsArray[knotsLength - 1] -
                                knotsArray[knotsLength - 2]);
            }
        }

        // width
        MPlug widthPlug = curve.findPlug("width");

        if (!useConstWidth && !widthPlug.isNull())
        {
            MObject widthObj;
            MStatus status = widthPlug.getValue(widthObj);
            MFnDoubleArrayData fnDoubleArrayData(widthObj, &status);
            MDoubleArray doubleArrayData = fnDoubleArrayData.array();
            Alembic::Util::int32_t arraySum = doubleArrayData.length();
            if (arraySum == numCVs)
            {
                for (Alembic::Util::int32_t i = 0; i < arraySum; i++)
                {
                    width.push_back(static_cast<float>(doubleArrayData[i]));
                }
            }
            else if (status == MS::kSuccess)
            {
                MString msg = "Curve ";
                msg += curve.partialPathName();
                msg += " has incorrect size for the width vector.";
                msg += "\nUsing default constant width of 0.1.";
                MGlobal::displayWarning(msg);

                width.clear();
                width.push_back(0.1f);
                useConstWidth = true;
            }
            else
            {
                width.push_back(widthPlug.asFloat());
                useConstWidth = true;
            }
        }
        else if (!useConstWidth)
        {
            // pick a default value
            width.clear();
            width.push_back(0.1f);
            useConstWidth = true;
        }
    }

    Alembic::AbcGeom::GeometryScope scope = Alembic::AbcGeom::kVertexScope;
    if (useConstWidth)
        scope = Alembic::AbcGeom::kConstantScope;

    samp.setCurvesNumVertices(Alembic::Abc::Int32ArraySample(nVertices));
    samp.setPositions(Alembic::Abc::V3fArraySample(
        (const Imath::V3f *)&points.front(), points.size() / 3 ));
    samp.setWidths(Alembic::AbcGeom::OFloatGeomParam::Sample(
        Alembic::Abc::FloatArraySample(width), scope) );

    if (samp.getType() == Alembic::AbcGeom::kVariableOrder)
    {
        samp.setOrders(Alembic::Abc::UcharArraySample(orders));
    }

    if (!knots.empty())
    {
        samp.setKnots(Alembic::Abc::FloatArraySample(knots));
    }

    mSchema.set(samp);
}
Ejemplo n.º 10
0
   VertexIter HalfedgeMesh::collapseEdge( EdgeIter e )
   {
      // TODO This method should collapse the given edge and return an iterator to the new vertex created by the collapse.
		 
		 //1. collect elements
		 EdgeIter e4 = e;

		 //Halfedges
		 HalfedgeIter h1 = e4->halfedge();
		 HalfedgeIter h5 = h1->twin();
		 
		 //Faces
		 FaceIter f0 = h1->face();
		 FaceIter f1 = h5->face();
		 
		 //Early Exit #1: Ignore requests to collapse boundary edges
		 if(f0->isBoundary() || f1->isBoundary())
			 return verticesEnd();
		 
		 //Halfedges, cont'
		 HalfedgeIter h2 = h1->next();
		 HalfedgeIter h0 = h2->next();
		 HalfedgeIter h3 = h5->next();
		 HalfedgeIter h4 = h3->next();
		 
		 HalfedgeIter h7 = h0->twin();
		 HalfedgeIter h12 = h3->twin();
		 
		 HalfedgeIter h20 = h2->twin();
		 HalfedgeIter h15 = h4->twin();
		 
		 //Edges
		 EdgeIter e0 = h0->edge();
		 EdgeIter e1 = h3->edge();
		 EdgeIter e2 = h4->edge();
		 EdgeIter e3 = h2->edge();
			//EdgeIter e4
		 
		 //Faces
		 
		 //Vertices
		 VertexIter v0 = h0->vertex();
		 VertexIter v1 = h3->vertex();
		 VertexIter v2 = h4->vertex();
		 VertexIter v3 = h2->vertex();
		 
		 //Early Exit #2: The number of the joint neighbor vertices of the two merging vertices
		 //must be EXACTLY TWO
		 std::vector<VertexIter> v1_neighbors;
		 std::vector<VertexIter> v3_neighbors;
		 HalfedgeIter h = h3;
		 do
		 {
			 h = h->twin();
			 if(h->vertex() != v1)
				 v1_neighbors.push_back(h->vertex());
			 h = h->next();
		 }
		 while(h != h3);
		 h = h2;
		 do
		 {
			 h = h->twin();
			 if(h->vertex() != v3)
				 v3_neighbors.push_back(h->vertex());
			 h = h->next();
		 }
		 while(h != h2);
		 std::sort(v1_neighbors.begin(), v1_neighbors.end());
		 std::sort(v3_neighbors.begin(), v3_neighbors.end());
		 std::vector<VertexIter> joint_neighbors;
		 std::set_intersection(v1_neighbors.begin(), v1_neighbors.end(),
													 v3_neighbors.begin(), v3_neighbors.end(),
													 std::back_inserter(joint_neighbors));
		 if(joint_neighbors.size() != 2)
			 return verticesEnd();
		 
		 //Early Exit #3: mesh must have more than 4 vertices if neither v1 nor v3 is boundary vertex,
		 //and more than 3 vertices if either v1 or v3 is boundary vertex
		 if(!v1->isBoundary() && !v3->isBoundary() && nVertices() <= 4)
			 return verticesEnd();
		 if((v1->isBoundary() || v3->isBoundary()) && nVertices() <= 3)
			 return verticesEnd();
		 
		 //Early Exit #4: v1, v3 cannot be both boundary vertex
		 if(v1->isBoundary() && v3->isBoundary())
			 return verticesEnd();
		 
		 //Early Exit #5: boundary vertex needs at least one triangle
		 //By convention, Vertex::degree() returns the face degree
		 if(v0->isBoundary() && v0->degree() <= 1)
			 return verticesEnd();
		 if(v1->isBoundary() && v1->degree() <= 1)
			 return verticesEnd();
		 if(v2->isBoundary() && v2->degree() <= 1)
			 return verticesEnd();
		 if(v3->isBoundary() && v3->degree() <= 1)
			 return verticesEnd();
		
		 //Early Exit #6: degenerated case: v0/v1/v2/v3 are duplicated
		 if(v0 == v1 || v0 == v2 || v0 == v3 || v1 == v2 || v1 == v3 || v2 == v3)
			 return verticesEnd();
		 

		 
		 VertexIter output = verticesEnd();
		 if(v3->isBoundary())
		 {
			 std::vector<HalfedgeIter> v1_out;
			 HalfedgeIter h = v1->halfedge();
			 do
			 {
				 v1_out.push_back(h);
				 h = h->next()->next()->twin();
			 }
			 while(h != v1->halfedge());
			 
			 //2. reassign elements
			 
			 //Halfedges
			 h7->twin() = h20; h7->edge() = e3;
			 h20->twin() = h7;
			 h12->twin() = h15; h12->edge() = e2;
			 h15->twin() = h12;
			 
			 for(auto h = v1_out.begin(); h!= v1_out.end(); ++h)
				 (*h)->vertex() = v3;
			 
			 //Vertices
			 v0->halfedge() = h20;
			 v3->halfedge() = h15;
			 v3->position = 0.5f * (v1->position + v3->position);
			 v2->halfedge() = h12;
			 
			 //Edges
			 e3->halfedge() = h20;
			 e2->halfedge() = h15;
			 
			 //Faces
			 
			 //3. delete elements
			 //Halfedges
			 deleteHalfedge(h0);
			 deleteHalfedge(h1);
			 deleteHalfedge(h2);
			 deleteHalfedge(h3);
			 deleteHalfedge(h4);
			 deleteHalfedge(h5);
			 
			 //Vertices
			 deleteVertex(v1);
			 
			 //Edges
			 deleteEdge(e0);
			 deleteEdge(e1);
			 deleteEdge(e4);
			 
			 //Faces
			 deleteFace(f0);
			 deleteFace(f1);
			 
			 output = v3;
		 }
		 else
		 {
			 std::vector<HalfedgeIter> v3_out;
			 HalfedgeIter h = v3->halfedge();
			 do
			 {
				 v3_out.push_back(h);
				 h = h->next()->next()->twin();
			 }
			 while(h != v3->halfedge());
			 
			 //2. reassign elements
			 
			 //Halfedges
			 h7->twin() = h20;
			 h20->twin() = h7; h20->edge() = e0;
			 h12->twin() = h15;
			 h15->twin() = h12; h15->edge() = e1;
			 
			 for(auto h = v3_out.begin(); h!= v3_out.end(); ++h)
				 (*h)->vertex() = v1;
			 
			 //Vertices
			 v0->halfedge() = h20;
			 v1->halfedge() = h15;
			 v1->position = 0.5f * (v1->position + v3->position);
			 v2->halfedge() = h12;
			 
			 //Edges
			 e0->halfedge() = h20;
			 e1->halfedge() = h15;
			 
			 //Faces
			 
			 //3. delete elements
			 //Halfedges
			 deleteHalfedge(h0);
			 deleteHalfedge(h1);
			 deleteHalfedge(h2);
			 deleteHalfedge(h3);
			 deleteHalfedge(h4);
			 deleteHalfedge(h5);
			 
			 //Vertices
			 deleteVertex(v3);
			 
			 //Edges
			 deleteEdge(e2);
			 deleteEdge(e3);
			 deleteEdge(e4);
			 
			 //Faces
			 deleteFace(f0);
			 deleteFace(f1);
			 
			 output = v1;
		 }
		 
		 return output;
   }
Ejemplo n.º 11
0
 void Face<ndim>::getVertexLoop(std::vector<const vertex_t *> &loop) const {
   loop.resize(nVertices(), NULL);
   std::copy(vbegin(), vend(), loop.begin());
 }
Ejemplo n.º 12
0
void tDxfSpline::UpdateControlPoints()
{
    controlPoints.clear();
    //tList<tVector> controlPoints;
    int n = nVertices();

    if(isClosed && n < 3)
    {
        if(n > 0) controlPoints.append(vertex(0)->vector());
        if(n > 1) controlPoints.append(vertex(1)->vector());
        return;
    }

    if(isClosed && n < 4)
    {
        if(n > 0) controlPoints.append(vertex(0)->vector());
        if(n > 2)
        {
            tVector x1 = vertex(0)->vector(),
                    x2 = vertex(1)->vector(),
                    x3 = vertex(2)->vector();

            double dl1 = (x2 - x1).length();
            double dl2 = (x3 - x2).length();
            double dt = dl1/(dl1 + dl2);

            if(dt < RS_TOLERANCE || dt > 1.0 - RS_TOLERANCE)
                //return RS_Vector(false);
                controlPoints.append((x2 - x1*(1.0 - dt)*(1.0 - dt) - x3*dt*dt)*(1./dt/(1 - dt)/2.0));
        }
        if(n > 1) {
            controlPoints.append(vertex(n - 1)->vector());
        }
        return;
    }

    int iDim = 0;
    if(isClosed) {
        iDim = n;
    } else {
        iDim = n - 2;
    }

    double *dt = new double[iDim];
    double dl1, dl2;

    if(isClosed)  {
        dl1 = (vertex(n - 1)->vector() - vertex(0)->vector()).length();
        dl2 = (vertex(1)->vector()     - vertex(0)->vector()).length();
        dt[0] = dl1/(dl1 + dl2);
        for(int i = 1; i < iDim - 1; i++)
        {
            dl1 = dl2;
            dl2 = (vertex(i + 1)->vector() - vertex(i)->vector()).length();
            dt[i] = dl1/(dl1 + dl2);
        }
        dl1 = (vertex(n - 1)->vector() - vertex(n - 2)->vector()).length();
        dl2 = (vertex(0)->vector() - vertex(n - 1)->vector()).length();
        dt[iDim - 1] = dl1/(dl1 + dl2);
    } else {
        dl1 = (vertex(1)->vector() - vertex(0)->vector()).length();
        dl2 = (vertex(2)->vector() - vertex(1)->vector()).length();
        dt[0] = dl1/(dl1 + dl2/2.0);
        for(int i = 1; i < iDim - 1; i++)
        {
            dl1 = dl2;
            dl2 = (vertex(i + 2)->vector() - vertex(i + 1)->vector()).length();
            dt[i] = dl1/(dl1 + dl2);
        }
        dl1 = dl2;
        dl2 = (vertex(iDim)->vector() - vertex(iDim + 1)->vector()).length();
        dt[iDim - 1] = dl1/(dl1 + 2.0*dl2);
    }

    double *pdMatrix = GetMatrix(n, dt);

    if(!pdMatrix) return;
    tVector *dx = new tVector[iDim],
            *dx2 = new tVector[iDim];
    /*double *dx = new double[iDim];
    double *dy = new double[iDim];
    double *dx2 = new double[iDim];
    double *dy2 = new double[iDim];*/

    if(isClosed)
    {
        double *pdDiag = pdMatrix;
        double *pdDiag1 = &pdMatrix[n];
        double *pdDiag2 = &pdMatrix[2*n - 1];
        double *pdLastCol1 = &pdMatrix[3*n - 2];
        double *pdLastCol2 = &pdMatrix[4*n - 4];

        dx[0] = vertex(0)->vector() * (1./pdDiag[0]);
        //dx[0] = vertex(0).x/pdDiag[0];
        //dy[0] = vertex(0).y/pdDiag[0];
        for(int i = 1; i < iDim - 1; i++)
        {
            dx[i] = (vertex(i)->vector() - dx[i-1]*pdDiag2[i-1])*(1./pdDiag[i]);
            //dx[i] = (vertex(i).x - pdDiag2[i - 1]*dx[i - 1])/pdDiag[i];
            //dy[i] = (vertex(i).y - pdDiag2[i - 1]*dy[i - 1])/pdDiag[i];
        }

        dx[iDim-1] = vertex(iDim - 1)->vector() - dx[iDim - 2]*pdDiag2[iDim - 2];
        //dx[iDim - 1] = vertex(iDim - 1).x - pdDiag2[iDim - 2]*dx[iDim - 2];
        //dy[iDim - 1] = vertex(iDim - 1).y - pdDiag2[iDim - 2]*dy[iDim - 2];
        for(int i = 0; i < iDim - 2; i++)
        {
            dx[iDim-1] = dx[iDim-1] - (dx[i] * pdLastCol2[i]);
            //dx[iDim - 1] -= (dx[i]*pdLastCol2[i]);
            //dy[iDim - 1] -= (dy[i]*pdLastCol2[i]);
        }
        dx[iDim-1] = dx[iDim-1] * (1./pdDiag[iDim - 1]);
        //dx[iDim - 1] /= pdDiag[iDim - 1];
        //dy[iDim - 1] /= pdDiag[iDim - 1];

        dx2[iDim-1] = dx[iDim-1]*(1./pdDiag[iDim-1]);
        //dx2[iDim - 1] = dx[iDim - 1]/pdDiag[iDim - 1];
        //dy2[iDim - 1] = dy[iDim - 1]/pdDiag[iDim - 1];

        dx2[iDim-2] = (dx[iDim-2]-dx2[iDim-1]*pdDiag1[iDim-2])*(1./pdDiag[iDim - 2]);
        //dx2[iDim - 2] = (dx[iDim - 2] - pdDiag1[iDim - 2]*dx2[iDim - 1])/pdDiag[iDim - 2];
        //dy2[iDim - 2] = (dy[iDim - 2] - pdDiag1[iDim - 2]*dy2[iDim - 1])/pdDiag[iDim - 2];

        for(int i = iDim - 3; i >= 0; i--)
        {
            dx2[i] = (dx[i] - dx2[i + 1]*pdDiag1[i] - dx2[iDim - 1]*pdLastCol1[i])*(1./pdDiag[i]);
            //dx2[i] = (dx[i] - pdDiag1[i]*dx2[i + 1] - pdLastCol1[i]*dx2[iDim - 1])/pdDiag[i];
            //dy2[i] = (dy[i] - pdDiag1[i]*dy2[i + 1] - pdLastCol1[i]*dy2[iDim - 1])/pdDiag[i];
        }

        for(int i = 0; i < iDim; i++)
        {
            controlPoints.append(dx2[i]);
        }
    }
    else
    {
        double *pdDiag = pdMatrix;
        double *pdDiag1 = &pdMatrix[n - 2];
        double *pdDiag2 = &pdMatrix[2*n - 5];

        dx[0] = (vertex(1)->vector() - vertex(0)->vector()*(1.0-dt[0]) * (1.0 - dt[0]))*(1./pdDiag[0]);
        //dx[0] = (vertex(1).x - vertex(0).x*(1.0 - dt[0])*(1.0 - dt[0]))/pdDiag[0];
        //dy[0] = (vertex(1).y - vertex(0).y*(1.0 - dt[0])*(1.0 - dt[0]))/pdDiag[0];
        for(int i = 1; i < iDim - 1; i++)
        {
            dx[i] = (vertex(i + 1)->vector() - dx[i-1]*pdDiag2[i-1])*(1./pdDiag[i]);
            //dx[i] = (vertex(i + 1).x - pdDiag2[i - 1]*dx[i - 1])/pdDiag[i];
            //dy[i] = (vertex(i + 1).y - pdDiag2[i - 1]*dy[i - 1])/pdDiag[i];
        }

        dx[iDim-1] = ((vertex(iDim)->vector() - vertex(iDim + 1)->vector()*dt[n-3]*dt[n-3]) - dx[iDim-2]*pdDiag2[iDim-2])*(1./pdDiag[iDim-1]);
        //dx[iDim - 1] = ((vertex(iDim).x - vertex(iDim + 1).x*dt[n - 3]*dt[n - 3]) -
        //    pdDiag2[iDim - 2]*dx[iDim - 2])/pdDiag[iDim - 1];
        //dy[iDim - 1] = ((vertex(iDim).y - vertex(iDim + 1).y*dt[n - 3]*dt[n - 3]) -
        //    pdDiag2[iDim - 2]*dy[iDim - 2])/pdDiag[iDim - 1];

        dx2[iDim-1] = dx[iDim-1]*(1./pdDiag[iDim - 1]);
        //dx2[iDim - 1] = dx[iDim - 1]/pdDiag[iDim - 1];
        //dy2[iDim - 1] = dy[iDim - 1]/pdDiag[iDim - 1];

        for(int i = iDim - 2; i >= 0; i--)
        {
            dx2[i] = (dx[i]-dx2[i+1]*pdDiag1[i])*(1./pdDiag[i]);
            //dx2[i] = (dx[i] - pdDiag1[i]*dx2[i + 1])/pdDiag[i];
            //dy2[i] = (dy[i] - pdDiag1[i]*dy2[i + 1])/pdDiag[i];
        }

        controlPoints.append(vertex(0)->vector());
        for(int i = 0; i < iDim; i++)
        {
            controlPoints.append(dx2[i]);
        }
        controlPoints.append(vertex(n - 1)->vector());
    }

    delete[] pdMatrix;

    delete[] dt;

    //delete[] dy2;
    delete[] dx2;
    //delete[] dy;
    delete[] dx;
}