bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolyline* l, TopoDS_Wire& result) {
	IfcSchema::IfcCartesianPoint::list::ptr points = l->Points();

	// Parse and store the points in a sequence
	TColgp_SequenceOfPnt polygon;
	for(IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it) {
		gp_Pnt pnt;
		IfcGeom::Kernel::convert(*it, pnt);
		polygon.Append(pnt);
	}

	// Remove points that are too close to one another
	remove_redundant_points_from_loop(polygon, false);
	
	BRepBuilderAPI_MakePolygon w;
	for (int i = 1; i <= polygon.Length(); ++i) {
		w.Add(polygon.Value(i));
	}

	result = w.Wire();
	return true;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolyLoop* l, TopoDS_Wire& result) {
	IfcSchema::IfcCartesianPoint::list::ptr points = l->Polygon();

	// Parse and store the points in a sequence
	TColgp_SequenceOfPnt polygon;
	for(IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it) {
		gp_Pnt pnt;
		IfcGeom::Kernel::convert(*it, pnt);
		polygon.Append(pnt);
	}

	// A loop should consist of at least three vertices
	int original_count = polygon.Length();
	if (original_count < 3) {
		Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity);
		return false;
	}

	// Remove points that are too close to one another
	remove_redundant_points_from_loop(polygon, true);

	int count = polygon.Length();
	if (original_count - count != 0) {
		std::stringstream ss; ss << (original_count - count) << " edges removed for:"; 
		Logger::Message(Logger::LOG_WARNING, ss.str(), l->entity);
	}

	if (count < 3) {
		Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity);
		return false;
	}

	BRepBuilderAPI_MakePolygon w;
	for (int i = 1; i <= polygon.Length(); ++i) {
		w.Add(polygon.Value(i));
	}
	w.Close();

	result = w.Wire();	
	return true;
}
Пример #3
0
void IfcGeom::remove_redundant_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol) {
	if (tol <= 0.) tol = GetValue(GV_POINT_EQUALITY_TOLERANCE);
	tol *= tol;

	while (true) {
		bool removed = false;
		int n = polygon.Length() - (closed ? 0 : 1);
		for (int i = 1; i <= n; ++i) {
			// wrap around to the first point in case of a closed loop
			int j = (i % polygon.Length()) + 1;
			double dist = polygon.Value(i).SquareDistance(polygon.Value(j));
			if (dist < tol) {
				// do not remove the first or last point to
				// maintain connectivity with other wires
				if ((closed && j == 1) || (!closed && j == n)) polygon.Remove(i);
				else polygon.Remove(j);
				removed = true;
				break;
			}
		}
		if (!removed) break;
	}
}
bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh&         aMesh,
                                               const TopoDS_Shape& aShape)
{
  TopExp_Explorer exp;
  SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();

  myHelper = new SMESH_MesherHelper( aMesh );
  myHelper->IsQuadraticSubMesh( aShape );
  // to delete helper at exit from Compute()
  auto_ptr<SMESH_MesherHelper> helperDeleter( myHelper );

  myLayerPositions.clear();

  TopoDS_Edge CircEdge, LinEdge1, LinEdge2;
  int nbe = analyseFace( aShape, CircEdge, LinEdge1, LinEdge2 );
  if( nbe>3 || nbe < 1 || CircEdge.IsNull() )
    return error(COMPERR_BAD_SHAPE);
  
  gp_Pnt P0,P1;
  // points for rotation
  TColgp_SequenceOfPnt Points;
  // angles for rotation
  TColStd_SequenceOfReal Angles;
  // Nodes1 and Nodes2 - nodes along radiuses
  // CNodes - nodes on circle edge
  vector< const SMDS_MeshNode* > Nodes1, Nodes2, CNodes;
  SMDS_MeshNode * NC;
  // parameters edge nodes on face
  TColgp_SequenceOfPnt2d Pnts2d1;
  gp_Pnt2d PC;

  int faceID = meshDS->ShapeToIndex(aShape);
  TopoDS_Face F = TopoDS::Face(aShape);
  Handle(Geom_Surface) S = BRep_Tool::Surface(F);

  if(nbe==1)
  {
    Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));

    bool ok = _gen->Compute( aMesh, CircEdge );
    if( !ok ) return false;
    map< double, const SMDS_MeshNode* > theNodes;
    ok = GetSortedNodesOnEdge(aMesh.GetMeshDS(),CircEdge,true,theNodes);
    if( !ok ) return false;

    CNodes.clear();
    map< double, const SMDS_MeshNode* >::iterator itn = theNodes.begin();
    const SMDS_MeshNode* NF = (*itn).second;
    CNodes.push_back( (*itn).second );
    double fang = (*itn).first;
    if ( itn != theNodes.end() ) {
      itn++;
      for(; itn != theNodes.end(); itn++ ) {
        CNodes.push_back( (*itn).second );
        double ang = (*itn).first - fang;
        if( ang>M_PI ) ang = ang - 2*M_PI;
        if( ang<-M_PI ) ang = ang + 2*M_PI;
        Angles.Append( ang ); 
      }
    }
    P1 = gp_Pnt( NF->X(), NF->Y(), NF->Z() );
    P0 = aCirc->Location();

    myLayerPositions.clear();
    computeLayerPositions(P0,P1);

    exp.Init( CircEdge, TopAbs_VERTEX );
    TopoDS_Vertex V1 = TopoDS::Vertex( exp.Current() );
    gp_Pnt2d p2dV = BRep_Tool::Parameters( V1, TopoDS::Face(aShape) );

    NC = meshDS->AddNode(P0.X(), P0.Y(), P0.Z());
    GeomAPI_ProjectPointOnSurf PPS(P0,S);
    double U0,V0;
    PPS.Parameters(1,U0,V0);
    meshDS->SetNodeOnFace(NC, faceID, U0, V0);
    PC = gp_Pnt2d(U0,V0);

    gp_Vec aVec(P0,P1);
    gp_Vec2d aVec2d(PC,p2dV);
    Nodes1.resize( myLayerPositions.size()+1 );
    Nodes2.resize( myLayerPositions.size()+1 );
    int i = 0;
    for(; i<myLayerPositions.size(); i++) {
      gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
                P0.Y() + aVec.Y()*myLayerPositions[i],
                P0.Z() + aVec.Z()*myLayerPositions[i] );
      Points.Append(P);
      SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
      Nodes1[i] = node;
      Nodes2[i] = node;
      double U = PC.X() + aVec2d.X()*myLayerPositions[i];
      double V = PC.Y() + aVec2d.Y()*myLayerPositions[i];
      meshDS->SetNodeOnFace( node, faceID, U, V );
      Pnts2d1.Append(gp_Pnt2d(U,V));
    }
    Nodes1[Nodes1.size()-1] = NF;
    Nodes2[Nodes1.size()-1] = NF;
  }
  else if(nbe==2 && LinEdge1.Orientation() != TopAbs_INTERNAL )
  {
    // one curve must be a half of circle and other curve must be
    // a segment of line
    double fp, lp;
    Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge, &fp, &lp ));
    if( fabs(fabs(lp-fp)-M_PI) > Precision::Confusion() ) {
      // not half of circle
      return error(COMPERR_BAD_SHAPE);
    }
    Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast( getCurve( LinEdge1 ));
    if( aLine.IsNull() ) {
      // other curve not line
      return error(COMPERR_BAD_SHAPE);
    }
    bool linEdgeComputed = false;
    if( SMESH_subMesh* sm1 = aMesh.GetSubMesh(LinEdge1) ) {
      if( !sm1->IsEmpty() ) {
        if( isEdgeCompitaballyMeshed( LinEdge1, aMesh.GetSubMesh(F) ))
          linEdgeComputed = true;
        else
          return error("Invalid set of hypotheses");
      }
    }

    bool ok = _gen->Compute( aMesh, CircEdge );
    if( !ok ) return false;
    map< double, const SMDS_MeshNode* > theNodes;
    GetSortedNodesOnEdge(aMesh.GetMeshDS(),CircEdge,true,theNodes);

    CNodes.clear();
    map< double, const SMDS_MeshNode* >::iterator itn = theNodes.begin();
    double fang = (*itn).first;
    itn++;
    for(; itn != theNodes.end(); itn++ ) {
      CNodes.push_back( (*itn).second );
      double ang = (*itn).first - fang;
      if( ang>M_PI ) ang = ang - 2*M_PI;
      if( ang<-M_PI ) ang = ang + 2*M_PI;
      Angles.Append( ang );
    }
    const SMDS_MeshNode* NF = theNodes.begin()->second;
    const SMDS_MeshNode* NL = theNodes.rbegin()->second;
    CNodes.push_back( NF );
    P1 = gp_Pnt( NF->X(), NF->Y(), NF->Z() );
    gp_Pnt P2( NL->X(), NL->Y(), NL->Z() );
    P0 = aCirc->Location();

    myLayerPositions.clear();
    computeLayerPositions(P0,P1);

    if ( linEdgeComputed )
    {
      if (!GetSortedNodesOnEdge(aMesh.GetMeshDS(),LinEdge1,true,theNodes))
        return error("Invalid mesh on a straight edge");

      vector< const SMDS_MeshNode* > *pNodes1 = &Nodes1, *pNodes2 = &Nodes2;
      bool nodesFromP0ToP1 = ( theNodes.rbegin()->second == NF );
      if ( !nodesFromP0ToP1 ) std::swap( pNodes1, pNodes2 );

      map< double, const SMDS_MeshNode* >::reverse_iterator ritn = theNodes.rbegin();
      itn = theNodes.begin();
      for ( int i = Nodes1.size()-1; i > -1; ++itn, ++ritn, --i )
      {
        (*pNodes1)[i] = ritn->second;
        (*pNodes2)[i] =  itn->second;
        Points.Append( gpXYZ( Nodes1[i]));
        Pnts2d1.Append( myHelper->GetNodeUV( F, Nodes1[i]));
      }
      NC = const_cast<SMDS_MeshNode*>( itn->second );
      Points.Remove( Nodes1.size() );
    }
    else
    {
      gp_Vec aVec(P0,P1);
      int edgeID = meshDS->ShapeToIndex(LinEdge1);
      // check orientation
      Handle(Geom_Curve) Crv = BRep_Tool::Curve(LinEdge1,fp,lp);
      gp_Pnt Ptmp;
      Crv->D0(fp,Ptmp);
      bool ori = true;
      if( P1.Distance(Ptmp) > Precision::Confusion() )
        ori = false;
      // get UV points for edge
      gp_Pnt2d PF,PL;
      BRep_Tool::UVPoints( LinEdge1, TopoDS::Face(aShape), PF, PL );
      PC = gp_Pnt2d( (PF.X()+PL.X())/2, (PF.Y()+PL.Y())/2 );
      gp_Vec2d V2d;
      if(ori) V2d = gp_Vec2d(PC,PF);
      else V2d = gp_Vec2d(PC,PL);
      // add nodes on edge
      double cp = (fp+lp)/2;
      double dp2 = (lp-fp)/2;
      NC = meshDS->AddNode(P0.X(), P0.Y(), P0.Z());
      meshDS->SetNodeOnEdge(NC, edgeID, cp);
      Nodes1.resize( myLayerPositions.size()+1 );
      Nodes2.resize( myLayerPositions.size()+1 );
      int i = 0;
      for(; i<myLayerPositions.size(); i++) {
        gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
                  P0.Y() + aVec.Y()*myLayerPositions[i],
                  P0.Z() + aVec.Z()*myLayerPositions[i] );
        Points.Append(P);
        SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
        Nodes1[i] = node;
        double param;
        if(ori)
          param = fp + dp2*(1-myLayerPositions[i]);
        else
          param = cp + dp2*myLayerPositions[i];
        meshDS->SetNodeOnEdge(node, edgeID, param);
        P = gp_Pnt( P0.X() - aVec.X()*myLayerPositions[i],
                    P0.Y() - aVec.Y()*myLayerPositions[i],
                    P0.Z() - aVec.Z()*myLayerPositions[i] );
        node = meshDS->AddNode(P.X(), P.Y(), P.Z());
        Nodes2[i] = node;
        if(!ori)
          param = fp + dp2*(1-myLayerPositions[i]);
        else
          param = cp + dp2*myLayerPositions[i];
        meshDS->SetNodeOnEdge(node, edgeID, param);
        // parameters on face
        gp_Pnt2d P2d( PC.X() + V2d.X()*myLayerPositions[i],
                      PC.Y() + V2d.Y()*myLayerPositions[i] );
        Pnts2d1.Append(P2d);
      }
      Nodes1[ myLayerPositions.size() ] = NF;
      Nodes2[ myLayerPositions.size() ] = NL;
      // create 1D elements on edge
      vector< const SMDS_MeshNode* > tmpNodes;
      tmpNodes.resize(2*Nodes1.size()+1);
      for(i=0; i<Nodes2.size(); i++)
        tmpNodes[Nodes2.size()-i-1] = Nodes2[i];
      tmpNodes[Nodes2.size()] = NC;
      for(i=0; i<Nodes1.size(); i++)
        tmpNodes[Nodes2.size()+1+i] = Nodes1[i];
      for(i=1; i<tmpNodes.size(); i++) {
        SMDS_MeshEdge* ME = myHelper->AddEdge( tmpNodes[i-1], tmpNodes[i] );
        if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
      }
      markLinEdgeAsComputedByMe( LinEdge1, aMesh.GetSubMesh( F ));
    }
  }
  else // nbe==3 or ( nbe==2 && linEdge is INTERNAL )
  {
    if (nbe==2 && LinEdge1.Orientation() == TopAbs_INTERNAL )
      LinEdge2 = LinEdge1;

    // one curve must be a part of circle and other curves must be
    // segments of line
    double fp, lp;
    Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
    Handle(Geom_Line) aLine1 = Handle(Geom_Line)::DownCast( getCurve( LinEdge1 ));
    Handle(Geom_Line) aLine2 = Handle(Geom_Line)::DownCast( getCurve( LinEdge2 ));
    if( aLine1.IsNull() || aLine2.IsNull() ) {
      // other curve not line
      return error(COMPERR_BAD_SHAPE);
    }

    bool linEdge1Computed = false;
    if ( SMESH_subMesh* sm1 = aMesh.GetSubMesh(LinEdge1))
      if( !sm1->IsEmpty() ) {
        if( isEdgeCompitaballyMeshed( LinEdge1, aMesh.GetSubMesh(F) ))
          linEdge1Computed = true;
        else
          return error("Invalid set of hypotheses");
      }
    bool linEdge2Computed = false;
    if ( SMESH_subMesh* sm2 = aMesh.GetSubMesh(LinEdge2))
      if( !sm2->IsEmpty() ) {
        if( isEdgeCompitaballyMeshed( LinEdge2, aMesh.GetSubMesh(F)  ))
          linEdge2Computed = true;
        else
          return error("Invalid set of hypotheses");
      }
    bool ok = _gen->Compute( aMesh, CircEdge );
    if( !ok ) return false;
    map< double, const SMDS_MeshNode* > theNodes;
    GetSortedNodesOnEdge(aMesh.GetMeshDS(),CircEdge,true,theNodes);

    const SMDS_MeshNode* NF = theNodes.begin()->second;
    const SMDS_MeshNode* NL = theNodes.rbegin()->second;
    CNodes.clear();
    CNodes.push_back( NF );
    map< double, const SMDS_MeshNode* >::iterator itn = theNodes.begin();
    double fang = (*itn).first;
    itn++;
    for(; itn != theNodes.end(); itn++ ) {
      CNodes.push_back( (*itn).second );
      double ang = (*itn).first - fang;
      if( ang>M_PI ) ang = ang - 2*M_PI;
      if( ang<-M_PI ) ang = ang + 2*M_PI;
      Angles.Append( ang );
    }
    P1 = gp_Pnt( NF->X(), NF->Y(), NF->Z() );
    gp_Pnt P2( NL->X(), NL->Y(), NL->Z() );
    P0 = aCirc->Location();

    myLayerPositions.clear();
    computeLayerPositions(P0,P1);

    Nodes1.resize( myLayerPositions.size()+1 );
    Nodes2.resize( myLayerPositions.size()+1 );

    exp.Init( LinEdge1, TopAbs_VERTEX );
    TopoDS_Vertex V1 = TopoDS::Vertex( exp.Current() );
    exp.Next();
    TopoDS_Vertex V2 = TopoDS::Vertex( exp.Current() );
    gp_Pnt PE1 = BRep_Tool::Pnt(V1);
    gp_Pnt PE2 = BRep_Tool::Pnt(V2);
    if( ( P1.Distance(PE1) > Precision::Confusion() ) &&
        ( P1.Distance(PE2) > Precision::Confusion() ) )
    {
      std::swap( LinEdge1, LinEdge2 );
      std::swap( linEdge1Computed, linEdge2Computed );
    }
    TopoDS_Vertex VC = V2;
    if( ( P1.Distance(PE1) > Precision::Confusion() ) &&
        ( P2.Distance(PE1) > Precision::Confusion() ) )
      VC = V1;
    int vertID = meshDS->ShapeToIndex(VC);

    // LinEdge1
    if ( linEdge1Computed )
    {
      if (!GetSortedNodesOnEdge(aMesh.GetMeshDS(),LinEdge1,true,theNodes))
        return error("Invalid mesh on a straight edge");

      bool nodesFromP0ToP1 = ( theNodes.rbegin()->second == NF );
      NC = const_cast<SMDS_MeshNode*>
        ( nodesFromP0ToP1 ? theNodes.begin()->second : theNodes.rbegin()->second );
      int i = 0, ir = Nodes1.size()-1;
      int * pi = nodesFromP0ToP1 ? &i : &ir;
      itn = theNodes.begin();
      if ( nodesFromP0ToP1 ) ++itn;
      for ( ; i < Nodes1.size(); ++i, --ir, ++itn )
      {
        Nodes1[*pi] = itn->second;
      }
      for ( i = 0; i < Nodes1.size()-1; ++i )
      {
        Points.Append( gpXYZ( Nodes1[i]));
        Pnts2d1.Append( myHelper->GetNodeUV( F, Nodes1[i]));
      }
    }
    else
    {
      int edgeID = meshDS->ShapeToIndex(LinEdge1);
      gp_Vec aVec(P0,P1);
      // check orientation
      Handle(Geom_Curve) Crv = BRep_Tool::Curve(LinEdge1,fp,lp);
      gp_Pnt Ptmp = Crv->Value(fp);
      bool ori = false;
      if( P1.Distance(Ptmp) > Precision::Confusion() )
        ori = true;
      // get UV points for edge
      gp_Pnt2d PF,PL;
      BRep_Tool::UVPoints( LinEdge1, TopoDS::Face(aShape), PF, PL );
      gp_Vec2d V2d;
      if(ori) {
        V2d = gp_Vec2d(PF,PL);
        PC = PF;
      }
      else {
        V2d = gp_Vec2d(PL,PF);
        PC = PL;
      }
      NC = const_cast<SMDS_MeshNode*>( VertexNode( VC, meshDS ));
      if ( !NC )
      {
        NC = meshDS->AddNode(P0.X(), P0.Y(), P0.Z());
        meshDS->SetNodeOnVertex(NC, vertID);
      }
      double dp = lp-fp;
      int i = 0;
      for(; i<myLayerPositions.size(); i++) {
        gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
                  P0.Y() + aVec.Y()*myLayerPositions[i],
                  P0.Z() + aVec.Z()*myLayerPositions[i] );
        Points.Append(P);
        SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
        Nodes1[i] = node;
        double param;
        if(!ori)
          param = fp + dp*(1-myLayerPositions[i]);
        else
          param = fp + dp*myLayerPositions[i];
        meshDS->SetNodeOnEdge(node, edgeID, param);
        // parameters on face
        gp_Pnt2d P2d( PC.X() + V2d.X()*myLayerPositions[i],
                      PC.Y() + V2d.Y()*myLayerPositions[i] );
        Pnts2d1.Append(P2d);
      }
      Nodes1[ myLayerPositions.size() ] = NF;
      // create 1D elements on edge
      SMDS_MeshEdge* ME = myHelper->AddEdge( NC, Nodes1[0] );
      if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
      for(i=1; i<Nodes1.size(); i++) {
        ME = myHelper->AddEdge( Nodes1[i-1], Nodes1[i] );
        if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
      }
      if (nbe==2 && LinEdge1.Orientation() == TopAbs_INTERNAL )
        Nodes2 = Nodes1;
    }
    markLinEdgeAsComputedByMe( LinEdge1, aMesh.GetSubMesh( F ));

    // LinEdge2
    if ( linEdge2Computed )
    {
      if (!GetSortedNodesOnEdge(aMesh.GetMeshDS(),LinEdge2,true,theNodes))
        return error("Invalid mesh on a straight edge");

      bool nodesFromP0ToP2 = ( theNodes.rbegin()->second == NL );
      int i = 0, ir = Nodes1.size()-1;
      int * pi = nodesFromP0ToP2 ? &i : &ir;
      itn = theNodes.begin();
      if ( nodesFromP0ToP2 ) ++itn;
      for ( ; i < Nodes2.size(); ++i, --ir, ++itn )
        Nodes2[*pi] = itn->second;
    }
    else
    {
      int edgeID = meshDS->ShapeToIndex(LinEdge2);
      gp_Vec aVec = gp_Vec(P0,P2);
      // check orientation
      Handle(Geom_Curve) Crv = BRep_Tool::Curve(LinEdge2,fp,lp);
      gp_Pnt Ptmp = Crv->Value(fp);
      bool ori = false;
      if( P2.Distance(Ptmp) > Precision::Confusion() )
        ori = true;
      // get UV points for edge
      gp_Pnt2d PF,PL;
      BRep_Tool::UVPoints( LinEdge2, TopoDS::Face(aShape), PF, PL );
      gp_Vec2d V2d;
      if(ori) {
        V2d = gp_Vec2d(PF,PL);
        PC = PF;
      }
      else {
        V2d = gp_Vec2d(PL,PF);
        PC = PL;
      }
      double dp = lp-fp;
      for(int i=0; i<myLayerPositions.size(); i++) {
        gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
                  P0.Y() + aVec.Y()*myLayerPositions[i],
                  P0.Z() + aVec.Z()*myLayerPositions[i] );
        SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
        Nodes2[i] = node;
        double param;
        if(!ori)
          param = fp + dp*(1-myLayerPositions[i]);
        else
          param = fp + dp*myLayerPositions[i];
        meshDS->SetNodeOnEdge(node, edgeID, param);
        // parameters on face
        gp_Pnt2d P2d( PC.X() + V2d.X()*myLayerPositions[i],
                      PC.Y() + V2d.Y()*myLayerPositions[i] );
      }
      Nodes2[ myLayerPositions.size() ] = NL;
      // create 1D elements on edge
      SMDS_MeshEdge* ME = myHelper->AddEdge( NC, Nodes2[0] );
      if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
      for(int i=1; i<Nodes2.size(); i++) {
        ME = myHelper->AddEdge( Nodes2[i-1], Nodes2[i] );
        if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
      }
    }
    markLinEdgeAsComputedByMe( LinEdge2, aMesh.GetSubMesh( F ));
  }

  // orientation
  bool IsForward = ( CircEdge.Orientation()==TopAbs_FORWARD );

  // create nodes and mesh elements on face
  // find axis of rotation
  gp_Pnt P2 = gp_Pnt( CNodes[1]->X(), CNodes[1]->Y(), CNodes[1]->Z() );
  gp_Vec Vec1(P0,P1);
  gp_Vec Vec2(P0,P2);
  gp_Vec Axis = Vec1.Crossed(Vec2);
  // create elements
  int i = 1;
  //cout<<"Angles.Length() = "<<Angles.Length()<<"   Points.Length() = "<<Points.Length()<<endl;
  //cout<<"Nodes1.size() = "<<Nodes1.size()<<"   Pnts2d1.Length() = "<<Pnts2d1.Length()<<endl;
  for(; i<Angles.Length(); i++) {
    vector< const SMDS_MeshNode* > tmpNodes;
    tmpNodes.reserve(Nodes1.size());
    gp_Trsf aTrsf;
    gp_Ax1 theAxis(P0,gp_Dir(Axis));
    aTrsf.SetRotation( theAxis, Angles.Value(i) );
    gp_Trsf2d aTrsf2d;
    aTrsf2d.SetRotation( PC, Angles.Value(i) );
    // create nodes
    int j = 1;
    for(; j<=Points.Length(); j++) {
      double cx,cy,cz;
      Points.Value(j).Coord( cx, cy, cz );
      aTrsf.Transforms( cx, cy, cz );
      SMDS_MeshNode* node = myHelper->AddNode( cx, cy, cz );
      // find parameters on face
      Pnts2d1.Value(j).Coord( cx, cy );
      aTrsf2d.Transforms( cx, cy );
      // set node on face
      meshDS->SetNodeOnFace( node, faceID, cx, cy );
      tmpNodes[j-1] = node;
    }
    // create faces
    tmpNodes[Points.Length()] = CNodes[i];
    // quad
    for(j=0; j<Nodes1.size()-1; j++) {
      SMDS_MeshFace* MF;
      if(IsForward)
        MF = myHelper->AddFace( tmpNodes[j], Nodes1[j],
                                Nodes1[j+1], tmpNodes[j+1] );
      else
        MF = myHelper->AddFace( tmpNodes[j], tmpNodes[j+1],
                                Nodes1[j+1], Nodes1[j] );
      if(MF) meshDS->SetMeshElementOnShape(MF, faceID);
    }
    // tria
    SMDS_MeshFace* MF;
    if(IsForward)
      MF = myHelper->AddFace( NC, Nodes1[0], tmpNodes[0] );
    else
      MF = myHelper->AddFace( NC, tmpNodes[0], Nodes1[0] );
    if(MF) meshDS->SetMeshElementOnShape(MF, faceID);
    for(j=0; j<Nodes1.size(); j++) {
      Nodes1[j] = tmpNodes[j];
    }
  }
  // create last faces
  // quad
  for(i=0; i<Nodes1.size()-1; i++) {
    SMDS_MeshFace* MF;
    if(IsForward)
      MF = myHelper->AddFace( Nodes2[i], Nodes1[i],
                              Nodes1[i+1], Nodes2[i+1] );
    else
      MF = myHelper->AddFace( Nodes2[i],  Nodes2[i+1],
                              Nodes1[i+1], Nodes1[i] );
    if(MF) meshDS->SetMeshElementOnShape(MF, faceID);
  }
  // tria
  SMDS_MeshFace* MF;
  if(IsForward)
    MF = myHelper->AddFace( NC, Nodes1[0], Nodes2[0] );
  else
    MF = myHelper->AddFace( NC, Nodes2[0], Nodes1[0] );
  if(MF) meshDS->SetMeshElementOnShape(MF, faceID);

  return true;
}