Esempio n. 1
0
bool SMESH_MesherHelper::GetNodeUVneedInFaceNode(const TopoDS_Face& F) const
{
  if ( F.IsNull() ) return !mySeamShapeIds.empty();

  if ( !F.IsNull() && !myShape.IsNull() && myShape.IsSame( F ))
    return !mySeamShapeIds.empty();

  Handle(Geom_Surface) aSurface = BRep_Tool::Surface( F );
  if ( !aSurface.IsNull() )
    return ( aSurface->IsUPeriodic() || aSurface->IsVPeriodic() );

  return false;
}
// TODO: This code is taken from and duplicates code in Part2DObject::positionBySupport()
// Note: We cannot return a reference, because it will become Null.
// Not clear where, because we check for IsNull() here, but as soon as it is passed out of
// this method, it becomes null!
const TopoDS_Face SketchBased::getSupportFace() const {
    const App::PropertyLinkSub& Support = static_cast<Part::Part2DObject*>(Sketch.getValue())->Support;
    Part::Feature *part = static_cast<Part::Feature*>(Support.getValue());
    if (!part || !part->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))
        throw Base::Exception("Sketch has no support shape");

    const std::vector<std::string> &sub = Support.getSubValues();
    assert(sub.size()==1);
    // get the selected sub shape (a Face)
    const Part::TopoShape &shape = part->Shape.getShape();
    if (shape._Shape.IsNull())
        throw Base::Exception("Sketch support shape is empty!");

    TopoDS_Shape sh = shape.getSubShape(sub[0].c_str());
    if (sh.IsNull())
        throw Base::Exception("Null shape in SketchBased::getSupportFace()!");

    const TopoDS_Face face = TopoDS::Face(sh);
    if (face.IsNull())
        throw Base::Exception("Null face in SketchBased::getSupportFace()!");

    BRepAdaptor_Surface adapt(face);
    if (adapt.GetType() != GeomAbs_Plane)
        throw Base::Exception("No planar face in SketchBased::getSupportFace()!");

    return face;
}
Esempio n. 3
0
gp_Dir GetFaceNormalAtUV(const TopoDS_Face &face, double u, double v, gp_Pnt *pos){
	if(face.IsNull()) return gp_Dir(0, 0, 1);

	try
	{
		Handle(Geom_Surface) surf=BRep_Tool::Surface(face);          // get surface properties
		GeomLProp_SLProps props(surf, u, v, 1, 0.01);          // get surface normal
		if(!props.IsNormalDefined())return gp_Dir(0, 0, 1);
		gp_Dir norm=props.Normal();                         // check orientation
		if(pos)*pos = props.Value();
		if(face.Orientation()==TopAbs_REVERSED) norm.Reverse();
		return norm;
	}
	catch (Standard_Failure) {
		Handle_Standard_Failure e = Standard_Failure::Caught();
		wxMessageBox(wxString(_("Error in GetFaceNormalAtUV")) + _T(": ") + Ctt(e->GetMessageString()));
		return gp_Dir(0, 0, 1);
	}
	catch (const char* str)
	{
		wxMessageBox(wxString(_("Error in GetFaceNormalAtUV")) + _T(": ") + Ctt(str));
		return gp_Dir(0, 0, 1);
	}
	catch (...)
	{
		wxMessageBox(_("Error in GetFaceNormalAtUV"));
		return gp_Dir(0, 0, 1);
	}
}
void PointOnFacesProjector::prepare(const TopoDS_Shape& faces)
{
  d->clear();
  // Build the UB tree for binary search of points
  internal::UBTreeOfNodeIndicesFiller_t ubTreeFiller(d->m_ubTree, Standard_False);
  for (TopExp_Explorer exp(faces, TopAbs_FACE); exp.More(); exp.Next()) {
    const TopoDS_Face face = TopoDS::Face(exp.Current());
    if (!face.IsNull()) {
      TopLoc_Location loc;
      const Handle_Poly_Triangulation& triangulation = BRep_Tool::Triangulation(face, loc);
      if (!triangulation.IsNull()) {
        d->insertMapping(triangulation, face);
        const gp_Trsf& trsf = loc.Transformation();
        const TColgp_Array1OfPnt& nodes = triangulation->Nodes();
        for (int i = nodes.Lower(); i <= nodes.Upper(); ++i) {
          const gp_Pnt iNode(nodes(i).Transformed(trsf));
          Bnd_Box ibb;
          ibb.Set(iNode);
          ubTreeFiller.Add(std::make_pair(i, triangulation), ibb);
        }
      }
    }
  }
  ubTreeFiller.Fill();
}
Esempio n. 5
0
void ProfileBased::getUpToFaceFromLinkSub(TopoDS_Face& upToFace,
                                         const App::PropertyLinkSub& refFace)
{
    App::DocumentObject* ref = refFace.getValue();
    std::vector<std::string> subStrings = refFace.getSubValues();

    if (ref == NULL)
        throw Base::ValueError("SketchBased: Up to face: No face selected");

    if (ref->getTypeId().isDerivedFrom(App::Plane::getClassTypeId())) {
        upToFace = TopoDS::Face(makeShapeFromPlane(ref));
        return;
    } else if (ref->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId())) {
        Part::Datum* datum = static_cast<Part::Datum*>(ref);
        upToFace = TopoDS::Face(datum->getShape());
        return;
    }

    if (!ref->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))
        throw Base::TypeError("SketchBased: Up to face: Must be face of a feature");
    Part::TopoShape baseShape = static_cast<Part::Feature*>(ref)->Shape.getShape();

    if (subStrings.empty() || subStrings[0].empty())
        throw Base::ValueError("SketchBased: Up to face: No face selected");
    // TODO: Check for multiple UpToFaces?

    upToFace = TopoDS::Face(baseShape.getSubShape(subStrings[0].c_str()));
    if (upToFace.IsNull())
        throw Base::ValueError("SketchBased: Up to face: Failed to extract face");
}
Esempio n. 6
0
// Note: We cannot return a reference, because it will become Null.
// Not clear where, because we check for IsNull() here, but as soon as it is passed out of
// this method, it becomes null!
const TopoDS_Face ProfileBased::getSupportFace() const {
    const Part::Part2DObject* sketch = getVerifiedSketch();
    if (sketch->MapMode.getValue() == Attacher::mmFlatFace  &&  sketch->Support.getValue()) {
        const auto &Support = sketch->Support;
        App::DocumentObject* ref = Support.getValue();

        Part::Feature *part = static_cast<Part::Feature*>(ref);
        if (part && part->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
            const std::vector<std::string> &sub = Support.getSubValues();
            assert(sub.size()==1);

            if (sub.at(0) == "") {
                // This seems to happen when sketch is on a datum plane
                return TopoDS::Face(Feature::makeShapeFromPlane(sketch));
            }

            // get the selected sub shape (a Face)
            const Part::TopoShape &shape = part->Shape.getShape();
            if (shape.getShape().IsNull())
                throw Base::ValueError("Sketch support shape is empty!");

            TopoDS_Shape sh = shape.getSubShape(sub[0].c_str());
            if (sh.IsNull())
                throw Base::ValueError("Null shape in SketchBased::getSupportFace()!");

            const TopoDS_Face face = TopoDS::Face(sh);
            if (face.IsNull())
                throw Base::ValueError("Null face in SketchBased::getSupportFace()!");

            BRepAdaptor_Surface adapt(face);
            if (adapt.GetType() != GeomAbs_Plane)
                throw Base::TypeError("No planar face in SketchBased::getSupportFace()!");

            return face;
        }
    }
    return TopoDS::Face(Feature::makeShapeFromPlane(sketch));

}
Esempio n. 7
0
TopoDS_Face FaceTypedCylinder::buildFace(const FaceVectorType &faces) const
{
    std::vector<EdgeVectorType> boundaries;
    boundarySplit(faces, boundaries);
    static TopoDS_Face dummy;
    if (boundaries.size() < 1)
        return dummy;

    //take one face and remove all the wires.
    TopoDS_Face workFace = faces.at(0);
    ShapeBuild_ReShape reshaper;
    TopExp_Explorer it;
    for (it.Init(workFace, TopAbs_WIRE); it.More(); it.Next())
        reshaper.Remove(it.Current());
    workFace = TopoDS::Face(reshaper.Apply(workFace));
    if (workFace.IsNull())
        return TopoDS_Face();

    ShapeFix_Face faceFixer(workFace);

    //makes wires
    std::vector<EdgeVectorType>::iterator boundaryIt;
    for (boundaryIt = boundaries.begin(); boundaryIt != boundaries.end(); ++boundaryIt)
    {
        BRepLib_MakeWire wireMaker;
        EdgeVectorType::iterator it;
        for (it = (*boundaryIt).begin(); it != (*boundaryIt).end(); ++it)
            wireMaker.Add(*it);
        if (wireMaker.Error() != BRepLib_WireDone)
            continue;
        faceFixer.Add(wireMaker.Wire());
    }
    if (faceFixer.Perform() > ShapeExtend_DONE5)
        return TopoDS_Face();
    faceFixer.FixOrientation();
    if (faceFixer.Perform() > ShapeExtend_DONE5)
        return TopoDS_Face();
    return faceFixer.Face();
}
const std::list<gp_Trsf> LinearPattern::getTransformations(const std::vector<App::DocumentObject*>)
{
    std::string stdDirection = StdDirection.getValue();
    float distance = Length.getValue();
    if (distance < Precision::Confusion())
        throw Base::Exception("Pattern length too small");
    int occurrences = Occurrences.getValue();
    if (occurrences < 2)
        throw Base::Exception("At least two occurrences required");
    bool reversed = Reversed.getValue();

    gp_Dir dir;
    double offset = distance / (occurrences - 1);

    if (!stdDirection.empty()) {
        // Note: The placement code commented out below had the defect of working always on the
        // absolute X,Y,Z direction, not on the relative coordinate system of the Body feature.
        // It requires positionBySupport() to be called in Transformed::Execute() AFTER
        // the call to getTransformations()
        // New code thanks to logari81
        if (stdDirection == "X") {
            //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(1,0,0));
            dir = gp_Dir(1,0,0);
        } else if (stdDirection == "Y") {
            //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(0,1,0));
            dir = gp_Dir(0,1,0);
        } else if(stdDirection == "Z") {
            //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(0,0,1));
            dir = gp_Dir(0,0,1);
        } else {
            throw Base::Exception("Invalid direction (must be X, Y or Z)");
        }
    } else {
        App::DocumentObject* refObject = Direction.getValue();
        if (refObject == NULL)
            throw Base::Exception("No direction specified");
        if (!refObject->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))
            throw Base::Exception("Direction reference must be edge or face of a feature");
        std::vector<std::string> subStrings = Direction.getSubValues();
        if (subStrings.empty() || subStrings[0].empty())
            throw Base::Exception("No direction reference specified");

        Part::Feature* refFeature = static_cast<Part::Feature*>(refObject);
        Part::TopoShape refShape = refFeature->Shape.getShape();
        TopoDS_Shape ref = refShape.getSubShape(subStrings[0].c_str());

        if (ref.ShapeType() == TopAbs_FACE) {
            TopoDS_Face refFace = TopoDS::Face(ref);
            if (refFace.IsNull())
                throw Base::Exception("Failed to extract direction plane");
            BRepAdaptor_Surface adapt(refFace);
            if (adapt.GetType() != GeomAbs_Plane)
                throw Base::Exception("Direction face must be planar");

            dir = adapt.Plane().Axis().Direction();
            //gp_Dir d = adapt.Plane().Axis().Direction();
            //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(d.X(), d.Y(), d.Z()));
        } else if (ref.ShapeType() == TopAbs_EDGE) {
            TopoDS_Edge refEdge = TopoDS::Edge(ref);
            if (refEdge.IsNull())
                throw Base::Exception("Failed to extract direction edge");
            BRepAdaptor_Curve adapt(refEdge);
            if (adapt.GetType() != GeomAbs_Line)
                throw Base::Exception("Direction edge must be a straight line");

            //gp_Dir d = adapt.Line().Direction();
            //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(d.X(), d.Y(), d.Z()));
            dir = adapt.Line().Direction();
        } else {
            throw Base::Exception("Direction reference must be edge or face");
        }
        TopLoc_Location invObjLoc = this->getLocation().Inverted();
        dir.Transform(invObjLoc.Transformation());
    }

    // get the support placement
    // TODO: Check for NULL pointer
    /*Part::Feature* supportFeature = static_cast<Part::Feature*>(originals.front());
    if (supportFeature == NULL)
        throw Base::Exception("Cannot work on invalid support shape");
    Base::Placement supportPlacement = supportFeature->Placement.getValue();
    dir *= supportPlacement;
    gp_Vec direction(dir.getDirection().x, dir.getDirection().y, dir.getDirection().z);*/
    gp_Vec direction(dir.X(), dir.Y(), dir.Z());

    if (reversed)
        direction.Reverse();

    // Note: The original feature is NOT included in the list of transformations! Therefore
    // we start with occurrence number 1, not number 0
    std::list<gp_Trsf> transformations;
    gp_Trsf trans;
    transformations.push_back(trans); // identity transformation

    for (int i = 1; i < occurrences; i++) {
        trans.SetTranslation(direction * i * offset);
        transformations.push_back(trans);
    }

    return transformations;
}
//=============================================================================
bool NETGENPlugin_Mesher::Compute()
{
#ifdef WNT
  netgen::MeshingParameters& mparams = netgen::GlobalMeshingParameters();
#else
  netgen::MeshingParameters& mparams = netgen::mparam;
#endif  
  MESSAGE("Compute with:\n"
          " max size = " << mparams.maxh << "\n"
          " segments per edge = " << mparams.segmentsperedge);
  MESSAGE("\n"
          " growth rate = " << mparams.grading << "\n"
          " elements per radius = " << mparams.curvaturesafety << "\n"
          " second order = " << mparams.secondorder << "\n"
          " quad allowed = " << mparams.quad);

  SMESH_ComputeErrorPtr error = SMESH_ComputeError::New();
  nglib::Ng_Init();

  // -------------------------
  // Prepare OCC geometry
  // -------------------------

  netgen::OCCGeometry occgeo;
  list< SMESH_subMesh* > meshedSM;
  PrepareOCCgeometry( occgeo, _shape, *_mesh, &meshedSM );

  // -------------------------
  // Generate the mesh
  // -------------------------

  netgen::Mesh *ngMesh = NULL;

  SMESH_Comment comment;
  int err = 0;
  int nbInitNod = 0;
  int nbInitSeg = 0;
  int nbInitFac = 0;
  // vector of nodes in which node index == netgen ID
  vector< SMDS_MeshNode* > nodeVec;
  try
  {
    // ----------------
    // compute 1D mesh
    // ----------------
    // pass 1D simple parameters to NETGEN
    if ( _simpleHyp ) {
      if ( int nbSeg = _simpleHyp->GetNumberOfSegments() ) {
        // nb of segments
        mparams.segmentsperedge = nbSeg + 0.1;
        mparams.maxh = occgeo.boundingbox.Diam();
        mparams.grading = 0.01;
      }
      else {
        // segment length
        mparams.segmentsperedge = 1;
        mparams.maxh = _simpleHyp->GetLocalLength();
      }
    }
    // let netgen create ngMesh and calculate element size on not meshed shapes
    char *optstr = 0;
    int startWith = netgen::MESHCONST_ANALYSE;
    int endWith   = netgen::MESHCONST_ANALYSE;
    err = netgen::OCCGenerateMesh(occgeo, ngMesh, startWith, endWith, optstr);
    if (err) comment << "Error in netgen::OCCGenerateMesh() at MESHCONST_ANALYSE step";

    // fill ngMesh with nodes and elements of computed submeshes
    err = ! fillNgMesh(occgeo, *ngMesh, nodeVec, meshedSM);
    nbInitNod = ngMesh->GetNP();
    nbInitSeg = ngMesh->GetNSeg();
    nbInitFac = ngMesh->GetNSE();

    // compute mesh
    if (!err)
    {
      startWith = endWith = netgen::MESHCONST_MESHEDGES;
      err = netgen::OCCGenerateMesh(occgeo, ngMesh, startWith, endWith, optstr);
      if (err) comment << "Error in netgen::OCCGenerateMesh() at 1D mesh generation";
    }
    // ---------------------
    // compute surface mesh
    // ---------------------
    if (!err)
    {
      // pass 2D simple parameters to NETGEN
      if ( _simpleHyp ) {
        if ( double area = _simpleHyp->GetMaxElementArea() ) {
          // face area
          mparams.maxh = sqrt(2. * area/sqrt(3.0));
          mparams.grading = 0.4; // moderate size growth
        }
        else {
          // length from edges
          double length = 0;
          TopTools_MapOfShape tmpMap;
          for ( TopExp_Explorer exp( _shape, TopAbs_EDGE ); exp.More(); exp.Next() )
            if( tmpMap.Add(exp.Current()) )
              length += SMESH_Algo::EdgeLength( TopoDS::Edge( exp.Current() ));

          if ( ngMesh->GetNSeg() ) {
            // we have to multiply length by 2 since for each TopoDS_Edge there
            // are double set of NETGEN edges or, in other words, we have to
            // divide ngMesh->GetNSeg() on 2.
            mparams.maxh = 2*length / ngMesh->GetNSeg();
          }
          else
            mparams.maxh = 1000;
          mparams.grading = 0.2; // slow size growth
        }
        mparams.maxh = min( mparams.maxh, occgeo.boundingbox.Diam()/2 );
        ngMesh->SetGlobalH (mparams.maxh);
        netgen::Box<3> bb = occgeo.GetBoundingBox();
        bb.Increase (bb.Diam()/20);
        ngMesh->SetLocalH (bb.PMin(), bb.PMax(), mparams.grading);
      }
      // let netgen compute 2D mesh
      startWith = netgen::MESHCONST_MESHSURFACE;
      endWith = _optimize ? netgen::MESHCONST_OPTSURFACE : netgen::MESHCONST_MESHSURFACE;
      err = netgen::OCCGenerateMesh(occgeo, ngMesh, startWith, endWith, optstr);
      if (err) comment << "Error in netgen::OCCGenerateMesh() at surface mesh generation";
    }
    // ---------------------
    // generate volume mesh
    // ---------------------
    if (!err && _isVolume)
    {
      // add ng face descriptors of meshed faces
      std::map< int, std::pair<int,int> >::iterator fId_soIds = _faceDescriptors.begin();
      for ( ; fId_soIds != _faceDescriptors.end(); ++fId_soIds ) {
        int faceID   = fId_soIds->first;
        int solidID1 = fId_soIds->second.first;
        int solidID2 = fId_soIds->second.second;
        ngMesh->AddFaceDescriptor (netgen::FaceDescriptor(faceID, solidID1, solidID2, 0));
      }
      // pass 3D simple parameters to NETGEN
      const NETGENPlugin_SimpleHypothesis_3D* simple3d =
        dynamic_cast< const NETGENPlugin_SimpleHypothesis_3D* > ( _simpleHyp );
      if ( simple3d ) {
        if ( double vol = simple3d->GetMaxElementVolume() ) {
          // max volume
          mparams.maxh = pow( 72, 1/6. ) * pow( vol, 1/3. );
          mparams.maxh = min( mparams.maxh, occgeo.boundingbox.Diam()/2 );
        }
        else {
          // length from faces
          mparams.maxh = ngMesh->AverageH();
        }
//      netgen::ARRAY<double> maxhdom;
//      maxhdom.SetSize (occgeo.NrSolids());
//      maxhdom = mparams.maxh;
//      ngMesh->SetMaxHDomain (maxhdom);
        ngMesh->SetGlobalH (mparams.maxh);
        mparams.grading = 0.4;
        ngMesh->CalcLocalH();
      }
      // let netgen compute 3D mesh
      startWith = netgen::MESHCONST_MESHVOLUME;
      endWith = _optimize ? netgen::MESHCONST_OPTVOLUME : netgen::MESHCONST_MESHVOLUME;
      err = netgen::OCCGenerateMesh(occgeo, ngMesh, startWith, endWith, optstr);
      if (err) comment << "Error in netgen::OCCGenerateMesh()";
    }
    if (!err && mparams.secondorder > 0)
    {
      netgen::OCCRefinementSurfaces ref (occgeo);
      ref.MakeSecondOrder (*ngMesh);
    }
  }
  catch (netgen::NgException exc)
  {
    error->myName = err = COMPERR_ALGO_FAILED;
    comment << exc.What();
  }

  int nbNod = ngMesh->GetNP();
  int nbSeg = ngMesh->GetNSeg();
  int nbFac = ngMesh->GetNSE();
  int nbVol = ngMesh->GetNE();

  MESSAGE((err ? "Mesh Generation failure" : "End of Mesh Generation") <<
          ", nb nodes: " << nbNod <<
          ", nb segments: " << nbSeg <<
          ", nb faces: " << nbFac <<
          ", nb volumes: " << nbVol);

  // -----------------------------------------------------------
  // Feed back the SMESHDS with the generated Nodes and Elements
  // -----------------------------------------------------------

  SMESHDS_Mesh* meshDS = _mesh->GetMeshDS();
  bool isOK = ( !err && (_isVolume ? (nbVol > 0) : (nbFac > 0)) );
  if ( true /*isOK*/ ) // get whatever built
  {
    // map of nodes assigned to submeshes
    NCollection_Map<int> pindMap;
    // create and insert nodes into nodeVec
    nodeVec.resize( nbNod + 1 );
    int i;
    for (i = nbInitNod+1; i <= nbNod /*&& isOK*/; ++i )
    {
      const netgen::MeshPoint& ngPoint = ngMesh->Point(i);
      SMDS_MeshNode* node = NULL;
      bool newNodeOnVertex = false;
      TopoDS_Vertex aVert;
      if (i-nbInitNod <= occgeo.vmap.Extent())
      {
        // point on vertex
        aVert = TopoDS::Vertex(occgeo.vmap(i-nbInitNod));
        SMESHDS_SubMesh * submesh = meshDS->MeshElements(aVert);
        if (submesh)
        {
          SMDS_NodeIteratorPtr it = submesh->GetNodes();
          if (it->more())
          {
            node = const_cast<SMDS_MeshNode*> (it->next());
            pindMap.Add(i);
          }
        }
        if (!node)
          newNodeOnVertex = true;
      }
      if (!node)
        node = meshDS->AddNode(ngPoint.X(), ngPoint.Y(), ngPoint.Z());
      if (!node)
      {
        MESSAGE("Cannot create a mesh node");
        if ( !comment.size() ) comment << "Cannot create a mesh node";
        nbSeg = nbFac = nbVol = isOK = 0;
        break;
      }
      nodeVec.at(i) = node;
      if (newNodeOnVertex)
      {
        // point on vertex
        meshDS->SetNodeOnVertex(node, aVert);
        pindMap.Add(i);
      }
    }

    // create mesh segments along geometric edges
    NCollection_Map<Link> linkMap;
    for (i = nbInitSeg+1; i <= nbSeg/* && isOK*/; ++i )
    {
      const netgen::Segment& seg = ngMesh->LineSegment(i);
      Link link(seg.p1, seg.p2);
      if (linkMap.Contains(link))
        continue;
      linkMap.Add(link);
      TopoDS_Edge aEdge;
      int pinds[3] = { seg.p1, seg.p2, seg.pmid };
      int nbp = 0;
      double param2 = 0;
      for (int j=0; j < 3; ++j)
      {
        int pind = pinds[j];
        if (pind <= 0) continue;
        ++nbp;
        double param;
        if (j < 2)
        {
          if (aEdge.IsNull())
          {
            int aGeomEdgeInd = seg.epgeominfo[j].edgenr;
            if (aGeomEdgeInd > 0 && aGeomEdgeInd <= occgeo.emap.Extent())
              aEdge = TopoDS::Edge(occgeo.emap(aGeomEdgeInd));
          }
          param = seg.epgeominfo[j].dist;
          param2 += param;
        }
        else
          param = param2 * 0.5;
        if (pind <= nbInitNod || pindMap.Contains(pind))
          continue;
        if (!aEdge.IsNull())
        {
          meshDS->SetNodeOnEdge(nodeVec.at(pind), aEdge, param);
          pindMap.Add(pind);
        }
      }
      SMDS_MeshEdge* edge;
      if (nbp < 3) // second order ?
        edge = meshDS->AddEdge(nodeVec.at(pinds[0]), nodeVec.at(pinds[1]));
      else
        edge = meshDS->AddEdge(nodeVec.at(pinds[0]), nodeVec.at(pinds[1]),
                                nodeVec.at(pinds[2]));
      if (!edge)
      {
        if ( !comment.size() ) comment << "Cannot create a mesh edge";
        MESSAGE("Cannot create a mesh edge");
        nbSeg = nbFac = nbVol = isOK = 0;
        break;
      }
      if (!aEdge.IsNull())
        meshDS->SetMeshElementOnShape(edge, aEdge);
    }

    // create mesh faces along geometric faces
    for (i = nbInitFac+1; i <= nbFac/* && isOK*/; ++i )
    {
      const netgen::Element2d& elem = ngMesh->SurfaceElement(i);
      int aGeomFaceInd = elem.GetIndex();
      TopoDS_Face aFace;
      if (aGeomFaceInd > 0 && aGeomFaceInd <= occgeo.fmap.Extent())
        aFace = TopoDS::Face(occgeo.fmap(aGeomFaceInd));
      vector<SMDS_MeshNode*> nodes;
      for (int j=1; j <= elem.GetNP(); ++j)
      {
        int pind = elem.PNum(j);
        SMDS_MeshNode* node = nodeVec.at(pind);
        nodes.push_back(node);
        if (pind <= nbInitNod || pindMap.Contains(pind))
          continue;
        if (!aFace.IsNull())
        {
          const netgen::PointGeomInfo& pgi = elem.GeomInfoPi(j);
          meshDS->SetNodeOnFace(node, aFace, pgi.u, pgi.v);
          pindMap.Add(pind);
        }
      }
      SMDS_MeshFace* face = NULL;
      switch (elem.GetType())
      {
      case netgen::TRIG:
        face = meshDS->AddFace(nodes[0],nodes[1],nodes[2]);
        break;
      case netgen::QUAD:
        face = meshDS->AddFace(nodes[0],nodes[1],nodes[2],nodes[3]);
        break;
      case netgen::TRIG6:
        face = meshDS->AddFace(nodes[0],nodes[1],nodes[2],nodes[5],nodes[3],nodes[4]);
        break;
      case netgen::QUAD8:
        face = meshDS->AddFace(nodes[0],nodes[1],nodes[2],nodes[3],
                               nodes[4],nodes[7],nodes[5],nodes[6]);
        break;
      default:
        MESSAGE("NETGEN created a face of unexpected type, ignoring");
        continue;
      }
      if (!face)
      {
        if ( !comment.size() ) comment << "Cannot create a mesh face";
        MESSAGE("Cannot create a mesh face");
        nbSeg = nbFac = nbVol = isOK = 0;
        break;
      }
      if (!aFace.IsNull())
        meshDS->SetMeshElementOnShape(face, aFace);
    }

    // create tetrahedra
    for (i = 1; i <= nbVol/* && isOK*/; ++i)
    {
      const netgen::Element& elem = ngMesh->VolumeElement(i);      
      int aSolidInd = elem.GetIndex();
      TopoDS_Solid aSolid;
      if (aSolidInd > 0 && aSolidInd <= occgeo.somap.Extent())
        aSolid = TopoDS::Solid(occgeo.somap(aSolidInd));
      vector<SMDS_MeshNode*> nodes;
      for (int j=1; j <= elem.GetNP(); ++j)
      {
        int pind = elem.PNum(j);
        SMDS_MeshNode* node = nodeVec.at(pind);
        nodes.push_back(node);
        if (pind <= nbInitNod || pindMap.Contains(pind))
          continue;
        if (!aSolid.IsNull())
        {
          // point in solid
          meshDS->SetNodeInVolume(node, aSolid);
          pindMap.Add(pind);
        }
      }
      SMDS_MeshVolume* vol = NULL;
      switch (elem.GetType())
      {
      case netgen::TET:
        vol = meshDS->AddVolume(nodes[0],nodes[1],nodes[2],nodes[3]);
        break;
      case netgen::TET10:
        vol = meshDS->AddVolume(nodes[0],nodes[1],nodes[2],nodes[3],
                                nodes[4],nodes[7],nodes[5],nodes[6],nodes[8],nodes[9]);
        break;
      default:
        MESSAGE("NETGEN created a volume of unexpected type, ignoring");
        continue;
      }
      if (!vol)
      {
        if ( !comment.size() ) comment << "Cannot create a mesh volume";
        MESSAGE("Cannot create a mesh volume");
        nbSeg = nbFac = nbVol = isOK = 0;
        break;
      }
      if (!aSolid.IsNull())
        meshDS->SetMeshElementOnShape(vol, aSolid);
    }
  }

  if ( error->IsOK() && ( !isOK || comment.size() > 0 ))
    error->myName = COMPERR_ALGO_FAILED;
  if ( !comment.empty() )
    error->myComment = comment;

  // set bad compute error to subshapes of all failed subshapes shapes
  if ( !error->IsOK() && err )
  {
    for (int i = 1; i <= occgeo.fmap.Extent(); i++) {
      int status = occgeo.facemeshstatus[i-1];
      if (status == 1 ) continue;
      if ( SMESH_subMesh* sm = _mesh->GetSubMeshContaining( occgeo.fmap( i ))) {
        SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
        if ( !smError || smError->IsOK() ) {
          if ( status == -1 )
            smError.reset( new SMESH_ComputeError( error->myName, error->myComment ));
          else
            smError.reset( new SMESH_ComputeError( COMPERR_ALGO_FAILED, "Ignored" ));
        }
      }
    }
  }

  nglib::Ng_DeleteMesh((nglib::Ng_Mesh*)ngMesh);
  nglib::Ng_Exit();

  RemoveTmpFiles();

  return error->IsOK();
}
Esempio n. 10
0
void ShapeGeometryBuilder::edgeConstruct(const TopoDS_Edge &edgeIn)
{
  TopoDS_Face face = TopoDS::Face(edgeToFace.FindFromKey(edgeIn).First());
  if (face.IsNull())
    throw std::runtime_error("face is null in edge construction");

  TopLoc_Location location;
  Handle(Poly_Triangulation) triangulation;
  triangulation = BRep_Tool::Triangulation(face, location);

  const Handle(Poly_PolygonOnTriangulation) &segments =
      BRep_Tool::PolygonOnTriangulation(edgeIn, triangulation, location);
  if (segments.IsNull())
    throw std::runtime_error("edge triangulation is null in edge construction");

  gp_Trsf transformation;
  bool identity = true;
  if(!location.IsIdentity())
  {
    identity = false;
    transformation = location.Transformation();
  }

  const TColStd_Array1OfInteger& indexes = segments->Nodes();
  const TColgp_Array1OfPnt& nodes = triangulation->Nodes();
  osg::Vec3Array *vertices = dynamic_cast<osg::Vec3Array *>(edgeGeometry->getVertexArray());
  osg::Vec4Array *colors = dynamic_cast<osg::Vec4Array *>(edgeGeometry->getColorArray());
  osg::ref_ptr<osg::DrawElementsUInt> indices = new osg::DrawElementsUInt
	  (GL_LINE_STRIP, indexes.Length());
  osg::BoundingSphere bSphere;
  
  for (int index(indexes.Lower()); index < indexes.Upper() + 1; ++index)
  {
    gp_Pnt point = nodes(indexes(index));
    if(!identity)
	point.Transform(transformation);
    vertices->push_back(osg::Vec3(point.X(), point.Y(), point.Z()));
    colors->push_back(edgeGeometry->getColor());
    (*indices)[index - 1] = vertices->size() - 1;
    
    if (!bSphere.valid()) //for first one.
    {
      bSphere.center() = vertices->back();
      bSphere.radius() = 0.0;
    }
    else
      bSphere.expandBy(vertices->back());
  }
  edgeGeometry->addPrimitiveSet(indices.get());
  boost::uuids::uuid id = seerShape->findShapeIdRecord(edgeIn).id;
  std::size_t lastPrimitiveIndex = edgeGeometry->getNumPrimitiveSets() - 1;
  if (!idPSetWrapperEdge->hasId(id))
  {
    IdPSetRecord record;
    record.id = id;
    record.primitiveSetIndex = lastPrimitiveIndex;
    record.bSphere = bSphere;
    idPSetWrapperEdge->idPSetContainer.insert(record);
  }
  else
    //ensure that edges have the same primitive index between lod calls.
    //asserts here prior to having lod implemented is probably duplicate ids
    //for different geometry.
    assert(lastPrimitiveIndex == idPSetWrapperEdge->findPSetFromId(id));
}
App::DocumentObjectExecReturn *DrawViewSection::execute(void)
{
    App::DocumentObject* link = Source.getValue();
    App::DocumentObject* base = BaseView.getValue();
    if (!link || !base)  {
        Base::Console().Log("INFO - DVS::execute - No Source or Link - creation?\n");
        return DrawView::execute();
    }

    if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))
        return new App::DocumentObjectExecReturn("Source object is not a Part object");
    if (!base->getTypeId().isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId()))
        return new App::DocumentObjectExecReturn("BaseView object is not a DrawViewPart object");

    //Base::Console().Message("TRACE - DVS::execute() - %s/%s\n",getNameInDocument(),Label.getValue());

    const Part::TopoShape &partTopo = static_cast<Part::Feature*>(link)->Shape.getShape();

    if (partTopo.getShape().IsNull())
        return new App::DocumentObjectExecReturn("Linked shape object is empty");

    (void) DrawView::execute();          //make sure Scale is up to date

    gp_Pln pln = getSectionPlane();
    gp_Dir gpNormal = pln.Axis().Direction();
    Base::Vector3d orgPnt = SectionOrigin.getValue();

    Base::BoundBox3d bb = partTopo.getBoundBox();
    if(!isReallyInBox(orgPnt, bb)) {
        Base::Console().Warning("DVS: Section Plane doesn't intersect part in %s\n",getNameInDocument());
        Base::Console().Warning("DVS: Using center of bounding box.\n");
        orgPnt = bb.GetCenter();
        SectionOrigin.setValue(orgPnt);
    }

    // Make the extrusion face
    double dMax = bb.CalcDiagonalLength();
    BRepBuilderAPI_MakeFace mkFace(pln, -dMax,dMax,-dMax,dMax);
    TopoDS_Face aProjFace = mkFace.Face();
    if(aProjFace.IsNull())
        return new App::DocumentObjectExecReturn("DrawViewSection - Projected face is NULL");
    gp_Vec extrudeDir = dMax * gp_Vec(gpNormal);
    TopoDS_Shape prism = BRepPrimAPI_MakePrism(aProjFace, extrudeDir, false, true).Shape();

    // We need to copy the shape to not modify the BRepstructure
    BRepBuilderAPI_Copy BuilderCopy(partTopo.getShape());
    TopoDS_Shape myShape = BuilderCopy.Shape();

    BRepAlgoAPI_Cut mkCut(myShape, prism);
    if (!mkCut.IsDone())
        return new App::DocumentObjectExecReturn("Section cut has failed");

    TopoDS_Shape rawShape = mkCut.Shape();
    Bnd_Box testBox;
    BRepBndLib::Add(rawShape, testBox);
    testBox.SetGap(0.0);
    if (testBox.IsVoid()) {                        //prism & input don't intersect.  rawShape is garbage, don't bother.
        Base::Console().Log("INFO - DVS::execute - prism & input don't intersect\n");
        return DrawView::execute();
    }

    gp_Pnt inputCenter;
    try {
        inputCenter = TechDrawGeometry::findCentroid(rawShape,
                                                     Direction.getValue());
        TopoDS_Shape mirroredShape = TechDrawGeometry::mirrorShape(rawShape,
                                                    inputCenter,
                                                    Scale.getValue());
        geometryObject = buildGeometryObject(mirroredShape,inputCenter);   //this is original shape after cut by section prism

#if MOD_TECHDRAW_HANDLE_FACES
        extractFaces();
#endif //#if MOD_TECHDRAW_HANDLE_FACES
    }
    catch (Standard_Failure) {
        Handle_Standard_Failure e1 = Standard_Failure::Caught();
        Base::Console().Log("LOG - DVS::execute - base shape failed for %s - %s **\n",getNameInDocument(),e1->GetMessageString());
        return new App::DocumentObjectExecReturn(e1->GetMessageString());
    }

    try {
        TopoDS_Compound sectionCompound = findSectionPlaneIntersections(rawShape);
        TopoDS_Shape mirroredSection = TechDrawGeometry::mirrorShape(sectionCompound,
                                                                     inputCenter,
                                                                     Scale.getValue());

        TopoDS_Compound newFaces;
        BRep_Builder builder;
        builder.MakeCompound(newFaces);
        TopExp_Explorer expl(mirroredSection, TopAbs_FACE);
        for (; expl.More(); expl.Next()) {
            const TopoDS_Face& face = TopoDS::Face(expl.Current());
            TopoDS_Face pFace = projectFace(face,
                                            inputCenter,
                                            Direction.getValue());
             if (!pFace.IsNull()) {
                 builder.Add(newFaces,pFace);
             }

        }
        sectionFaces = newFaces;
    }
    catch (Standard_Failure) {
        Handle_Standard_Failure e2 = Standard_Failure::Caught();
        Base::Console().Log("LOG - DVS::execute - failed building section faces for %s - %s **\n",getNameInDocument(),e2->GetMessageString());
        return new App::DocumentObjectExecReturn(e2->GetMessageString());
    }

    return App::DocumentObject::StdReturn;
}
Esempio n. 12
0
bool FaceUniter::process()
{
    if (workShell.IsNull())
        return false;
    modifiedShapes.clear();
    deletedShapes.clear();
    typeObjects.push_back(&getPlaneObject());
    typeObjects.push_back(&getCylinderObject());
    //add more face types.

    ModelRefine::FaceTypeSplitter splitter;
    splitter.addShell(workShell);
    std::vector<FaceTypedBase *>::iterator typeIt;
    for(typeIt = typeObjects.begin(); typeIt != typeObjects.end(); ++typeIt)
        splitter.registerType((*typeIt)->getType());
    splitter.split();

    ModelRefine::FaceVectorType facesToRemove;
    ModelRefine::FaceVectorType facesToSew;

    ModelRefine::FaceAdjacencySplitter adjacencySplitter(workShell);

    for(typeIt = typeObjects.begin(); typeIt != typeObjects.end(); ++typeIt)
    {
        ModelRefine::FaceVectorType typedFaces = splitter.getTypedFaceVector((*typeIt)->getType());
        ModelRefine::FaceEqualitySplitter equalitySplitter;
        equalitySplitter.split(typedFaces, *typeIt);
        for (std::size_t indexEquality(0); indexEquality < equalitySplitter.getGroupCount(); ++indexEquality)
        {
            adjacencySplitter.split(equalitySplitter.getGroup(indexEquality));
//            std::cout << "      adjacency group count: " << adjacencySplitter.getGroupCount() << std::endl;
            for (std::size_t adjacentIndex(0); adjacentIndex < adjacencySplitter.getGroupCount(); ++adjacentIndex)
            {
//                    std::cout << "         face count is: " << adjacencySplitter.getGroup(adjacentIndex).size() << std::endl;
                TopoDS_Face newFace = (*typeIt)->buildFace(adjacencySplitter.getGroup(adjacentIndex));
                if (!newFace.IsNull())
                {
                    facesToSew.push_back(newFace);
                    if (facesToRemove.capacity() <= facesToRemove.size() + adjacencySplitter.getGroup(adjacentIndex).size())
                        facesToRemove.reserve(facesToRemove.size() + adjacencySplitter.getGroup(adjacentIndex).size());
                    FaceVectorType temp = adjacencySplitter.getGroup(adjacentIndex);
                    facesToRemove.insert(facesToRemove.end(), temp.begin(), temp.end());
                    // the first shape will be marked as modified, i.e. replaced by newFace, all others are marked as deleted
                    if (!temp.empty())
                    {
                        modifiedShapes.push_back(std::make_pair(temp.front(), newFace));
                        deletedShapes.insert(deletedShapes.end(), temp.begin()+1, temp.end());
                    }
                }
            }
        }
    }
    if (facesToSew.size() > 0)
    {
        modifiedSignal = true;
        workShell = ModelRefine::removeFaces(workShell, facesToRemove);
        TopExp_Explorer xp;
        bool emptyShell = true;
        for (xp.Init(workShell, TopAbs_FACE); xp.More(); xp.Next())
        {
            emptyShell = false;
            break;
        }

        if (!emptyShell || facesToSew.size() > 1)
        {
            BRepBuilderAPI_Sewing sew;
            sew.Add(workShell);
            FaceVectorType::iterator sewIt;
            for(sewIt = facesToSew.begin(); sewIt != facesToSew.end(); ++sewIt)
                sew.Add(*sewIt);
            sew.Perform();
            workShell = TopoDS::Shell(sew.SewedShape());
            // update the list of modifications
            for (std::vector<ShapePairType>::iterator it = modifiedShapes.begin(); it != modifiedShapes.end(); ++it)
            {
                if (sew.IsModified(it->second))
                {
                    it->second = sew.Modified(it->second);
                    break;
                }
            }
        }
        else
        {
            // workShell has no more faces and we add exactly one face
            BRep_Builder builder;
            builder.MakeShell(workShell);
            FaceVectorType::iterator sewIt;
            for(sewIt = facesToSew.begin(); sewIt != facesToSew.end(); ++sewIt)
                builder.Add(workShell, *sewIt);
        }

        BRepLib_FuseEdges edgeFuse(workShell, Standard_True);
        TopTools_DataMapOfShapeShape affectedFaces;
        edgeFuse.Faces(affectedFaces);
        TopTools_DataMapIteratorOfDataMapOfShapeShape mapIt;
        for (mapIt.Initialize(affectedFaces); mapIt.More(); mapIt.Next())
        {
            ShapeFix_Face faceFixer(TopoDS::Face(mapIt.Value()));
            faceFixer.Perform();
        }
        workShell = TopoDS::Shell(edgeFuse.Shape());
        // update the list of modifications
        TopTools_DataMapOfShapeShape faceMap;
        edgeFuse.Faces(faceMap);
        for (std::vector<ShapePairType>::iterator it = modifiedShapes.begin(); it != modifiedShapes.end(); ++it)
        {
            if (faceMap.IsBound(it->second))
            {
                const TopoDS_Shape& value = faceMap.Find(it->second);
                if (!value.IsSame(it->second))
                    it->second = value;
            }
        }
    }
    return true;
}
Esempio n. 13
0
App::DocumentObjectExecReturn *Pocket::execute(void)
{
    // Handle legacy features, these typically have Type set to 3 (previously NULL, now UpToFace),
    // empty FaceName (because it didn't exist) and a value for Length
    if (std::string(Type.getValueAsString()) == "UpToFace" &&
        (UpToFace.getValue() == NULL && Length.getValue() > Precision::Confusion()))
        Type.setValue("Length");

    // Validate parameters
    double L = Length.getValue();
    if ((std::string(Type.getValueAsString()) == "Length") && (L < Precision::Confusion()))
        return new App::DocumentObjectExecReturn("Pocket: Length of pocket too small");

    Part::Feature* obj = 0;
    TopoDS_Face face;
    try {
        obj = getVerifiedObject();
        face = getVerifiedFace();
    } catch (const Base::Exception& e) {
        return new App::DocumentObjectExecReturn(e.what());
    }

    // if the Base property has a valid shape, fuse the prism into it
    TopoDS_Shape base;
    try {
        base = getBaseShape();
    } catch (const Base::Exception&) {
        return new App::DocumentObjectExecReturn("No sketch support and no base shape: Please tell me where to remove the material of the pocket!");
    }

    // get the Sketch plane
    Base::Placement SketchPos    = obj->Placement.getValue(); 
    Base::Vector3d  SketchVector = getProfileNormal();

    // turn around for pockets
    SketchVector *= -1;

    try {
        this->positionByPrevious();
        TopLoc_Location invObjLoc = this->getLocation().Inverted();

        base.Move(invObjLoc);

        gp_Dir dir(SketchVector.x,SketchVector.y,SketchVector.z);
        dir.Transform(invObjLoc.Transformation());

        if (face.IsNull())
            return new App::DocumentObjectExecReturn("Pocket: Creating a face from sketch failed");
        face.Move(invObjLoc);

        std::string method(Type.getValueAsString());
        if (method == "UpToFirst" || method == "UpToFace") {
            if (base.IsNull())
                return new App::DocumentObjectExecReturn("Pocket: Extruding up to a face is only possible if the sketch is located on a face");

            // Note: This will return an unlimited planar face if support is a datum plane
            TopoDS_Face supportface = getSupportFace();
            supportface.Move(invObjLoc);

            if (Reversed.getValue())
                dir.Reverse();

            // Find a valid face or datum plane to extrude up to
            TopoDS_Face upToFace;
            if (method == "UpToFace") {
                getUpToFaceFromLinkSub(upToFace, UpToFace);
                upToFace.Move(invObjLoc);
            }
            getUpToFace(upToFace, base, supportface, face, method, dir, Offset.getValue());

            // BRepFeat_MakePrism(..., 2, 1) in combination with PerForm(upToFace) is buggy when the
            // prism that is being created is contained completely inside the base solid
            // In this case the resulting shape is empty. This is not a problem for the Pad or Pocket itself
            // but it leads to an invalid SubShape
            // The bug only occurs when the upToFace is limited (by a wire), not for unlimited upToFace. But
            // other problems occur with unlimited concave upToFace so it is not an option to always unlimit upToFace
            // Check supportface for limits, otherwise Perform() throws an exception
            TopExp_Explorer Ex(supportface,TopAbs_WIRE);
            if (!Ex.More())
                supportface = TopoDS_Face();
            BRepFeat_MakePrism PrismMaker;
            PrismMaker.Init(base, face, supportface, dir, 0, 1);
            PrismMaker.Perform(upToFace);

            if (!PrismMaker.IsDone())
                return new App::DocumentObjectExecReturn("Pocket: Up to face: Could not extrude the sketch!");
            TopoDS_Shape prism = PrismMaker.Shape();

            // And the really expensive way to get the SubShape...
            BRepAlgoAPI_Cut mkCut(base, prism);
            if (!mkCut.IsDone())
                return new App::DocumentObjectExecReturn("Pocket: Up to face: Could not get SubShape!");
            // FIXME: In some cases this affects the Shape property: It is set to the same shape as the SubShape!!!!
            TopoDS_Shape result = refineShapeIfActive(mkCut.Shape());
            this->AddSubShape.setValue(result);
            this->Shape.setValue(prism);
        } else {
            TopoDS_Shape prism;
            generatePrism(prism, face, method, dir, L, 0.0,
                          Midplane.getValue(), Reversed.getValue());
            if (prism.IsNull())
                return new App::DocumentObjectExecReturn("Pocket: Resulting shape is empty");

            // set the subtractive shape property for later usage in e.g. pattern
            prism = refineShapeIfActive(prism);
            this->AddSubShape.setValue(prism);

            // Cut the SubShape out of the base feature
            BRepAlgoAPI_Cut mkCut(base, prism);
            if (!mkCut.IsDone())
                return new App::DocumentObjectExecReturn("Pocket: Cut out of base feature failed");
            TopoDS_Shape result = mkCut.Shape();
            // we have to get the solids (fuse sometimes creates compounds)
            TopoDS_Shape solRes = this->getSolid(result);
            if (solRes.IsNull())
                return new App::DocumentObjectExecReturn("Pocket: Resulting shape is not a solid");
            solRes = refineShapeIfActive(solRes);
            remapSupportShape(solRes);
            this->Shape.setValue(solRes);
        }

        return App::DocumentObject::StdReturn;
    }
    catch (Standard_Failure) {
        Handle_Standard_Failure e = Standard_Failure::Caught();
        if (std::string(e->GetMessageString()) == "TopoDS::Face" &&
            (std::string(Type.getValueAsString()) == "UpToFirst" || std::string(Type.getValueAsString()) == "UpToFace"))
            return new App::DocumentObjectExecReturn("Could not create face from sketch.\n"
                "Intersecting sketch entities or multiple faces in a sketch are not allowed "
                "for making a pocket up to a face.");
        else
            return new App::DocumentObjectExecReturn(e->GetMessageString());
    }
    catch (Base::Exception& e) {
        return new App::DocumentObjectExecReturn(e.what());
    }
}
Esempio n. 14
0
App::DocumentObjectExecReturn *Draft::execute(void)
{
    // Get parameters
    // Base shape
    Part::TopoShape TopShape;
    try {
        TopShape = getBaseShape();
    } catch (Base::Exception& e) {
        return new App::DocumentObjectExecReturn(e.what());
    }

    // Faces where draft should be applied
    // Note: Cannot be const reference currently because of BRepOffsetAPI_DraftAngle::Remove() bug, see below
    std::vector<std::string> SubVals = Base.getSubValuesStartsWith("Face");
    if (SubVals.size() == 0)
        return new App::DocumentObjectExecReturn("No faces specified");

    // Draft angle
    double angle = Angle.getValue() / 180.0 * M_PI;

    // Pull direction
    gp_Dir pullDirection;
    App::DocumentObject* refDirection = PullDirection.getValue();    
    if (refDirection != NULL) {
        if (refDirection->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) {
                    PartDesign::Line* line = static_cast<PartDesign::Line*>(refDirection);
                    Base::Vector3d d = line->getDirection();
                    pullDirection = gp_Dir(d.x, d.y, d.z);
        } else if (refDirection->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
            std::vector<std::string> subStrings = PullDirection.getSubValues();
            if (subStrings.empty() || subStrings[0].empty())
                throw Base::Exception("No pull direction reference specified");

            Part::Feature* refFeature = static_cast<Part::Feature*>(refDirection);
            Part::TopoShape refShape = refFeature->Shape.getShape();
            TopoDS_Shape ref = refShape.getSubShape(subStrings[0].c_str());

            if (ref.ShapeType() == TopAbs_EDGE) {
                TopoDS_Edge refEdge = TopoDS::Edge(ref);
                if (refEdge.IsNull())
                    throw Base::Exception("Failed to extract pull direction reference edge");
                BRepAdaptor_Curve adapt(refEdge);
                if (adapt.GetType() != GeomAbs_Line)
                    throw Base::Exception("Pull direction reference edge must be linear");

                pullDirection = adapt.Line().Direction();
            } else {
                throw Base::Exception("Pull direction reference must be an edge or a datum line");
            }
        } else {
            throw Base::Exception("Pull direction reference must be an edge of a feature or a datum line");
        }

        TopLoc_Location invObjLoc = this->getLocation().Inverted();
        pullDirection.Transform(invObjLoc.Transformation());
    }

    // Neutral plane
    gp_Pln neutralPlane;
    App::DocumentObject* refPlane = NeutralPlane.getValue();
    if (refPlane == NULL) {
        // Try to guess a neutral plane from the first selected face
        // Get edges of first selected face
        TopoDS_Shape face = TopShape.getSubShape(SubVals[0].c_str());
        TopTools_IndexedMapOfShape mapOfEdges;
        TopExp::MapShapes(face, TopAbs_EDGE, mapOfEdges);
        bool found = false;

        for (int i = 1; i <= mapOfEdges.Extent(); i++) {
            // Note: What happens if mapOfEdges(i) is the degenerated edge of a cone?
            // But in that case the draft is not possible anyway!
            BRepAdaptor_Curve c(TopoDS::Edge(mapOfEdges(i)));
            gp_Pnt p1 = c.Value(c.FirstParameter());
            gp_Pnt p2 = c.Value(c.LastParameter());

            if (c.IsClosed()) {
                // Edge is a circle or a circular arc (other types are not allowed for drafting)
                neutralPlane = gp_Pln(p1, c.Circle().Axis().Direction());
                found = true;
                break;
            } else {
                // Edge is linear
                // Find midpoint of edge and create auxiliary plane through midpoint normal to edge
                gp_Pnt pm = c.Value((c.FirstParameter() + c.LastParameter()) / 2.0);
                Handle(Geom_Plane) aux = new Geom_Plane(pm, gp_Dir(p2.X() - p1.X(), p2.Y() - p1.Y(), p2.Z() - p1.Z()));
                // Intersect plane with face. Is there no easier way?
                BRepAdaptor_Surface adapt(TopoDS::Face(face), Standard_False);
                Handle(Geom_Surface) sf = adapt.Surface().Surface();
                GeomAPI_IntSS intersector(aux, sf, Precision::Confusion());
                if (!intersector.IsDone())
                    continue;
                Handle(Geom_Curve) icurve = intersector.Line(1);
                if (!icurve->IsKind(STANDARD_TYPE(Geom_Line)))
                    continue;
                // TODO: How to extract the line from icurve without creating an edge first?
                TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(icurve);
                BRepAdaptor_Curve c(edge);
                neutralPlane = gp_Pln(pm, c.Line().Direction());
                found = true;
                break;
            }
        }

        if (!found)
            throw Base::Exception("No neutral plane specified and none can be guessed");
    } else {
        if (refPlane->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId())) {
            PartDesign::Plane* plane = static_cast<PartDesign::Plane*>(refPlane);
            Base::Vector3d b = plane->getBasePoint();
            Base::Vector3d n = plane->getNormal();
            neutralPlane = gp_Pln(gp_Pnt(b.x, b.y, b.z), gp_Dir(n.x, n.y, n.z));
        } else if (refPlane->getTypeId().isDerivedFrom(App::Plane::getClassTypeId())) {
            neutralPlane = Feature::makePlnFromPlane(refPlane);
        } else if (refPlane->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
            std::vector<std::string> subStrings = NeutralPlane.getSubValues();
            if (subStrings.empty() || subStrings[0].empty())
                throw Base::Exception("No neutral plane reference specified");

            Part::Feature* refFeature = static_cast<Part::Feature*>(refPlane);
            Part::TopoShape refShape = refFeature->Shape.getShape();
            TopoDS_Shape ref = refShape.getSubShape(subStrings[0].c_str());

            if (ref.ShapeType() == TopAbs_FACE) {
                TopoDS_Face refFace = TopoDS::Face(ref);
                if (refFace.IsNull())
                    throw Base::Exception("Failed to extract neutral plane reference face");
                BRepAdaptor_Surface adapt(refFace);
                if (adapt.GetType() != GeomAbs_Plane)
                    throw Base::Exception("Neutral plane reference face must be planar");

                neutralPlane = adapt.Plane();
            } else if (ref.ShapeType() == TopAbs_EDGE) {
                if (refDirection != NULL) {
                    // Create neutral plane through edge normal to pull direction
                    TopoDS_Edge refEdge = TopoDS::Edge(ref);
                    if (refEdge.IsNull())
                        throw Base::Exception("Failed to extract neutral plane reference edge");
                    BRepAdaptor_Curve c(refEdge);
                    if (c.GetType() != GeomAbs_Line)
                        throw Base::Exception("Neutral plane reference edge must be linear");
                    double a = c.Line().Angle(gp_Lin(c.Value(c.FirstParameter()), pullDirection));
                    if (std::fabs(a - M_PI_2) > Precision::Confusion())
                        throw Base::Exception("Neutral plane reference edge must be normal to pull direction");
                    neutralPlane = gp_Pln(c.Value(c.FirstParameter()), pullDirection);
                } else {
                    throw Base::Exception("Neutral plane reference can only be an edge if pull direction is defined");
                }
            } else {
                throw Base::Exception("Neutral plane reference must be a face");
            }
        } else {
            throw Base::Exception("Neutral plane reference must be face of a feature or a datum plane");
        }

        TopLoc_Location invObjLoc = this->getLocation().Inverted();
        neutralPlane.Transform(invObjLoc.Transformation());
    }

    if (refDirection == NULL) {
        // Choose pull direction normal to neutral plane
        pullDirection = neutralPlane.Axis().Direction();
    }

    // Reversed pull direction
    bool reversed = Reversed.getValue();
    if (reversed)
        angle *= -1.0;

    this->positionByBaseFeature();
    // create an untransformed copy of the base shape
    Part::TopoShape baseShape(TopShape);
    baseShape.setTransform(Base::Matrix4D());
    try {
        BRepOffsetAPI_DraftAngle mkDraft;
        // Note:
        // LocOpe_SplitDrafts can split a face with a wire and apply draft to both parts
        //       Not clear though whether the face must have free boundaries
        // LocOpe_DPrism can create a stand-alone draft prism. The sketch can only have a single
        //       wire, though.
        // BRepFeat_MakeDPrism requires a support for the operation but will probably support multiple
        //       wires in the sketch

        bool success;

        do {
            success = true;
            mkDraft.Init(baseShape.getShape());

            for (std::vector<std::string>::iterator it=SubVals.begin(); it != SubVals.end(); ++it) {
                TopoDS_Face face = TopoDS::Face(baseShape.getSubShape(it->c_str()));
                // TODO: What is the flag for?
                mkDraft.Add(face, pullDirection, angle, neutralPlane);
                if (!mkDraft.AddDone()) {
                    // Note: the function ProblematicShape returns the face on which the error occurred
                    // Note: mkDraft.Remove() stumbles on a bug in Draft_Modification::Remove() and is
                    //       therefore unusable. See http://forum.freecadweb.org/viewtopic.php?f=10&t=3209&start=10#p25341
                    //       The only solution is to discard mkDraft and start over without the current face
                    // mkDraft.Remove(face);
                    Base::Console().Error("Adding face failed on %s. Omitted\n", it->c_str());
                    success = false;
                    SubVals.erase(it);
                    break;
                }
            }
        }
        while (!success);

        mkDraft.Build();
        if (!mkDraft.IsDone())
            return new App::DocumentObjectExecReturn("Failed to create draft");

        TopoDS_Shape shape = mkDraft.Shape();
        if (shape.IsNull())
            return new App::DocumentObjectExecReturn("Resulting shape is null");

        this->Shape.setValue(getSolid(shape));
        return App::DocumentObject::StdReturn;
    }
    catch (Standard_Failure) {
        Handle(Standard_Failure) e = Standard_Failure::Caught();
        return new App::DocumentObjectExecReturn(e->GetMessageString());
    }
}
Esempio n. 15
0
bool FaceUniter::process()
{
    if (workShell.IsNull())
        return false;
    modifiedShapes.clear();
    deletedShapes.clear();
    typeObjects.push_back(&getPlaneObject());
    typeObjects.push_back(&getCylinderObject());
    //add more face types.

    ModelRefine::FaceTypeSplitter splitter;
    splitter.addShell(workShell);
    std::vector<FaceTypedBase *>::iterator typeIt;
    for(typeIt = typeObjects.begin(); typeIt != typeObjects.end(); ++typeIt)
        splitter.registerType((*typeIt)->getType());
    splitter.split();

    ModelRefine::FaceVectorType facesToRemove;
    ModelRefine::FaceVectorType facesToSew;

    ModelRefine::FaceAdjacencySplitter adjacencySplitter(workShell);

    for(typeIt = typeObjects.begin(); typeIt != typeObjects.end(); ++typeIt)
    {
        ModelRefine::FaceVectorType typedFaces = splitter.getTypedFaceVector((*typeIt)->getType());
        ModelRefine::FaceEqualitySplitter equalitySplitter;
        equalitySplitter.split(typedFaces, *typeIt);
        for (std::size_t indexEquality(0); indexEquality < equalitySplitter.getGroupCount(); ++indexEquality)
        {
            adjacencySplitter.split(equalitySplitter.getGroup(indexEquality));
//            std::cout << "      adjacency group count: " << adjacencySplitter.getGroupCount() << std::endl;
            for (std::size_t adjacentIndex(0); adjacentIndex < adjacencySplitter.getGroupCount(); ++adjacentIndex)
            {
//                    std::cout << "         face count is: " << adjacencySplitter.getGroup(adjacentIndex).size() << std::endl;
                TopoDS_Face newFace = (*typeIt)->buildFace(adjacencySplitter.getGroup(adjacentIndex));
                if (!newFace.IsNull())
                {
                    facesToSew.push_back(newFace);
                    if (facesToRemove.capacity() <= facesToRemove.size() + adjacencySplitter.getGroup(adjacentIndex).size())
                        facesToRemove.reserve(facesToRemove.size() + adjacencySplitter.getGroup(adjacentIndex).size());
                    FaceVectorType temp = adjacencySplitter.getGroup(adjacentIndex);
                    facesToRemove.insert(facesToRemove.end(), temp.begin(), temp.end());
                    // the first shape will be marked as modified, i.e. replaced by newFace, all others are marked as deleted
                    // jrheinlaender: IMHO this is not correct because references to the deleted faces will be broken, whereas they should
                    // be replaced by references to the new face. To achieve this all shapes should be marked as
                    // modified, producing one single new face. This is the inverse behaviour to faces that are split e.g.
                    // by a boolean cut, where one old shape is marked as modified, producing multiple new shapes
                    if (!temp.empty())
                    {
                        for (FaceVectorType::iterator f = temp.begin(); f != temp.end(); ++f)
                              modifiedShapes.push_back(std::make_pair(*f, newFace));
                    }
                }
            }
        }
    }
    if (facesToSew.size() > 0)
    {
        modifiedSignal = true;
        workShell = ModelRefine::removeFaces(workShell, facesToRemove);
        TopExp_Explorer xp;
        bool emptyShell = true;
        for (xp.Init(workShell, TopAbs_FACE); xp.More(); xp.Next())
        {
            emptyShell = false;
            break;
        }

        if (!emptyShell || facesToSew.size() > 1)
        {
            BRepBuilderAPI_Sewing sew;
            sew.Add(workShell);
            FaceVectorType::iterator sewIt;
            for(sewIt = facesToSew.begin(); sewIt != facesToSew.end(); ++sewIt)
                sew.Add(*sewIt);
            sew.Perform();
            try {
                workShell = TopoDS::Shell(sew.SewedShape());
            } catch (Standard_Failure) {
                return false;
            }
            // update the list of modifications
            for (std::vector<ShapePairType>::iterator it = modifiedShapes.begin(); it != modifiedShapes.end(); ++it)
            {
                if (sew.IsModified(it->second))
                {
                    it->second = sew.Modified(it->second);
                    break;
                }
            }
        }
        else
        {
            // workShell has no more faces and we add exactly one face
            BRep_Builder builder;
            builder.MakeShell(workShell);
            FaceVectorType::iterator sewIt;
            for(sewIt = facesToSew.begin(); sewIt != facesToSew.end(); ++sewIt)
                builder.Add(workShell, *sewIt);
        }
        
        BRepLib_FuseEdges edgeFuse(workShell);
// TODO: change this version after occ fix. Freecad Mantis 1450
#if OCC_VERSION_HEX <= 0x070000
        TopTools_IndexedMapOfShape map;
        collectConicEdges(workShell, map);
        edgeFuse.AvoidEdges(map);
#endif
        TopTools_DataMapOfShapeShape affectedFaces;
        edgeFuse.Faces(affectedFaces);
        TopTools_DataMapIteratorOfDataMapOfShapeShape mapIt;
        for (mapIt.Initialize(affectedFaces); mapIt.More(); mapIt.Next())
        {
            ShapeFix_Face faceFixer(TopoDS::Face(mapIt.Value()));
            faceFixer.Perform();
        }
        workShell = TopoDS::Shell(edgeFuse.Shape());
        // update the list of modifications
        TopTools_DataMapOfShapeShape faceMap;
        edgeFuse.Faces(faceMap);
        for (mapIt.Initialize(faceMap); mapIt.More(); mapIt.Next())
        {
            bool isModifiedFace = false;
            for (std::vector<ShapePairType>::iterator it = modifiedShapes.begin(); it != modifiedShapes.end(); ++it)
            {
                if (mapIt.Key().IsSame(it->second)) {
                    // Note: IsEqual() for some reason does not work
                    it->second = mapIt.Value();
                    isModifiedFace = true;
                }
            }
            if (!isModifiedFace)
            {
                // Catch faces that were not united but whose boundary was changed (probably because
                // several adjacent faces were united)
                // See https://sourceforge.net/apps/mantisbt/free-cad/view.php?id=873
                modifiedShapes.push_back(std::make_pair(mapIt.Key(), mapIt.Value()));
            }
        }
        // Handle edges that were fused. See https://sourceforge.net/apps/mantisbt/free-cad/view.php?id=873
        TopTools_DataMapOfIntegerListOfShape oldEdges;
        TopTools_DataMapOfIntegerShape newEdges;
        edgeFuse.Edges(oldEdges);
        edgeFuse.ResultEdges(newEdges);
        TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape edgeMapIt;
        for (edgeMapIt.Initialize(oldEdges); edgeMapIt.More(); edgeMapIt.Next())
        {
            const TopTools_ListOfShape& edges = edgeMapIt.Value();
            int idx = edgeMapIt.Key();
            TopTools_ListIteratorOfListOfShape edgeIt;
            for (edgeIt.Initialize(edges); edgeIt.More(); edgeIt.Next())
            {
                modifiedShapes.push_back(std::make_pair(edgeIt.Value(), newEdges(idx)));
            }
            // TODO: Handle vertices that have disappeared in the fusion of the edges
        }
    }
    return true;
}
void BuildShapeMesh(osg::Geode *geode, const TopoDS_Shape &shape, const osg::Vec4 &color, double deflection)
{
	bool bSetNormal = true;
	osg::ref_ptr<deprecated_osg::Geometry> triGeom = new deprecated_osg::Geometry();
	osg::ref_ptr<osg::Vec3Array> theVertices = new osg::Vec3Array();
	osg::ref_ptr<osg::Vec3Array> theNormals = new osg::Vec3Array();

	BRepMesh::Mesh(shape, deflection);

	TopExp_Explorer faceExplorer;
	for (faceExplorer.Init(shape, TopAbs_FACE); faceExplorer.More(); faceExplorer.Next())
	{
		TopLoc_Location theLocation;
		TopoDS_Face theFace = TopoDS::Face(faceExplorer.Current());
	
		if (theFace.IsNull())
			continue;

		const Handle_Poly_Triangulation &theTriangulation = BRep_Tool::Triangulation(theFace, theLocation);
		BRepLProp_SLProps theProp(BRepAdaptor_Surface(theFace), 1, Precision::Confusion());
	
		Standard_Integer nTriangles = theTriangulation->NbTriangles();
	
		for (Standard_Integer i = 1; i <= nTriangles; i++)
		{
			const Poly_Triangle& theTriangle = theTriangulation->Triangles().Value(i);
			gp_Pnt theVertex1 = theTriangulation->Nodes().Value(theTriangle(1));
			gp_Pnt theVertex2 = theTriangulation->Nodes().Value(theTriangle(2));
			gp_Pnt theVertex3 = theTriangulation->Nodes().Value(theTriangle(3));

			const gp_Pnt2d &theUV1 = theTriangulation->UVNodes().Value(theTriangle(1));
			const gp_Pnt2d &theUV2 = theTriangulation->UVNodes().Value(theTriangle(2));
			const gp_Pnt2d &theUV3 = theTriangulation->UVNodes().Value(theTriangle(3));

			theVertex1.Transform(theLocation.Transformation());
			theVertex2.Transform(theLocation.Transformation());
			theVertex3.Transform(theLocation.Transformation());

			// find the normal for the triangle mesh.
			gp_Vec V12(theVertex1, theVertex2);
			gp_Vec V13(theVertex1, theVertex3);
			gp_Vec theNormal = V12 ^ V13;
			gp_Vec theNormal1 = theNormal;
			gp_Vec theNormal2 = theNormal;
			gp_Vec theNormal3 = theNormal;

			if (theNormal.Magnitude() > Precision::Confusion())
			{
				theNormal.Normalize();
				theNormal1.Normalize();
				theNormal2.Normalize();
				theNormal3.Normalize();
			}

			theProp.SetParameters(theUV1.X(), theUV1.Y());
			if (theProp.IsNormalDefined())
			{
				theNormal1 = theProp.Normal();
			}

			theProp.SetParameters(theUV2.X(), theUV2.Y());
			if (theProp.IsNormalDefined())
			{
				theNormal2 = theProp.Normal();
			}

			theProp.SetParameters(theUV3.X(), theUV3.Y());
			if (theProp.IsNormalDefined())
			{
				theNormal3 = theProp.Normal();
			}

			if (theFace.Orientation() == TopAbs_REVERSED)
			{
				theNormal.Reverse();
				theNormal1.Reverse();
				theNormal2.Reverse();
				theNormal3.Reverse();
			}

			theVertices->push_back(osg::Vec3(theVertex1.X(), theVertex1.Y(), theVertex1.Z()));
			theVertices->push_back(osg::Vec3(theVertex2.X(), theVertex2.Y(), theVertex2.Z()));
			theVertices->push_back(osg::Vec3(theVertex3.X(), theVertex3.Y(), theVertex3.Z()));

			if (bSetNormal)
			{
				theNormals->push_back(osg::Vec3(theNormal1.X(), theNormal1.Y(), theNormal1.Z()));
				theNormals->push_back(osg::Vec3(theNormal2.X(), theNormal2.Y(), theNormal2.Z()));
				theNormals->push_back(osg::Vec3(theNormal3.X(), theNormal3.Y(), theNormal3.Z()));
			}
			else
			{
				theNormals->push_back(osg::Vec3(theNormal.X(), theNormal.Y(), theNormal.Z()));
				theNormals->push_back(osg::Vec3(theNormal.X(), theNormal.Y(), theNormal.Z()));
				theNormals->push_back(osg::Vec3(theNormal.X(), theNormal.Y(), theNormal.Z()));
			}
		}
	}

	triGeom->setVertexArray(theVertices.get());
	triGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, theVertices->size()));

	triGeom->setNormalArray(theNormals);
	triGeom->setNormalBinding(deprecated_osg::Geometry::BIND_PER_VERTEX);

	osg::ref_ptr<osg::Vec4Array> colArr = new osg::Vec4Array();
	colArr->push_back(color);
	triGeom->setColorArray(colArr, osg::Array::BIND_OVERALL);

	geode->addDrawable(triGeom);
}
const std::list<gp_Trsf> LinearPattern::getTransformations(const std::vector<App::DocumentObject*>)
{
    double distance = Length.getValue();
    if (distance < Precision::Confusion())
        throw Base::Exception("Pattern length too small");
    int occurrences = Occurrences.getValue();
    if (occurrences < 2)
        throw Base::Exception("At least two occurrences required");
    bool reversed = Reversed.getValue();

    double offset = distance / (occurrences - 1);

    App::DocumentObject* refObject = Direction.getValue();
    if (refObject == NULL)
        throw Base::Exception("No direction reference specified");

    std::vector<std::string> subStrings = Direction.getSubValues();
    if (subStrings.empty())
        throw Base::Exception("No direction reference specified");

    gp_Dir dir;
    if (refObject->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) {
        Part::Part2DObject* refSketch = static_cast<Part::Part2DObject*>(refObject);
        Base::Axis axis;
        if (subStrings[0] == "H_Axis")
            axis = refSketch->getAxis(Part::Part2DObject::H_Axis);
        else if (subStrings[0] == "V_Axis")
            axis = refSketch->getAxis(Part::Part2DObject::V_Axis);
        else if (subStrings[0] == "N_Axis")
            axis = refSketch->getAxis(Part::Part2DObject::N_Axis);
        else if (subStrings[0].size() > 4 && subStrings[0].substr(0,4) == "Axis") {
            int AxId = std::atoi(subStrings[0].substr(4,4000).c_str());
            if (AxId >= 0 && AxId < refSketch->getAxisCount())
                axis = refSketch->getAxis(AxId);
        }
        axis *= refSketch->Placement.getValue();
        dir = gp_Dir(axis.getDirection().x, axis.getDirection().y, axis.getDirection().z);
    } else if (refObject->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId())) {
        PartDesign::Plane* plane = static_cast<PartDesign::Plane*>(refObject);
        Base::Vector3d d = plane->getNormal();
        dir = gp_Dir(d.x, d.y, d.z);
    } else if (refObject->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) {
        PartDesign::Line* line = static_cast<PartDesign::Line*>(refObject);
        Base::Vector3d d = line->getDirection();
        dir = gp_Dir(d.x, d.y, d.z);
    } else if (refObject->getTypeId().isDerivedFrom(App::Line::getClassTypeId())) {
        App::Line* line = static_cast<App::Line*>(refObject);
        Base::Rotation rot = line->Placement.getValue().getRotation();
        Base::Vector3d d(1,0,0);
        rot.multVec(d, d);
        dir = gp_Dir(d.x, d.y, d.z);
    } else if (refObject->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
        if (subStrings[0].empty())
            throw Base::Exception("No direction reference specified");
        Part::Feature* refFeature = static_cast<Part::Feature*>(refObject);
        Part::TopoShape refShape = refFeature->Shape.getShape();
        TopoDS_Shape ref = refShape.getSubShape(subStrings[0].c_str());

        if (ref.ShapeType() == TopAbs_FACE) {
            TopoDS_Face refFace = TopoDS::Face(ref);
            if (refFace.IsNull())
                throw Base::Exception("Failed to extract direction plane");
            BRepAdaptor_Surface adapt(refFace);
            if (adapt.GetType() != GeomAbs_Plane)
                throw Base::Exception("Direction face must be planar");

            dir = adapt.Plane().Axis().Direction();
        } else if (ref.ShapeType() == TopAbs_EDGE) {
            TopoDS_Edge refEdge = TopoDS::Edge(ref);
            if (refEdge.IsNull())
                throw Base::Exception("Failed to extract direction edge");
            BRepAdaptor_Curve adapt(refEdge);
            if (adapt.GetType() != GeomAbs_Line)
                throw Base::Exception("Direction edge must be a straight line");

            dir = adapt.Line().Direction();
        } else {
            throw Base::Exception("Direction reference must be edge or face");
        }
    } else {
        throw Base::Exception("Direction reference must be edge/face of a feature or a datum line/plane");
    }
    TopLoc_Location invObjLoc = this->getLocation().Inverted();
    dir.Transform(invObjLoc.Transformation());

    gp_Vec direction(dir.X(), dir.Y(), dir.Z());

    if (reversed)
        direction.Reverse();

    // Note: The original feature is NOT included in the list of transformations! Therefore
    // we start with occurrence number 1, not number 0
    std::list<gp_Trsf> transformations;
    gp_Trsf trans;
    transformations.push_back(trans); // identity transformation

    for (int i = 1; i < occurrences; i++) {
        trans.SetTranslation(direction * i * offset);
        transformations.push_back(trans);
    }

    return transformations;
}
bool NETGENPlugin_NETGEN_2D_ONLY::Evaluate(SMESH_Mesh& aMesh,
        const TopoDS_Shape& aShape,
        MapShapeNbElems& aResMap)
{
    TopoDS_Face F = TopoDS::Face(aShape);
    if(F.IsNull())
        return false;

    // collect info from edges
    int nb0d = 0, nb1d = 0;
    bool IsQuadratic = false;
    bool IsFirst = true;
    double fullLen = 0.0;
    TopTools_MapOfShape tmpMap;
    for (TopExp_Explorer exp(F, TopAbs_EDGE); exp.More(); exp.Next()) {
        TopoDS_Edge E = TopoDS::Edge(exp.Current());
        if( tmpMap.Contains(E) )
            continue;
        tmpMap.Add(E);
        SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current());
        MapShapeNbElemsItr anIt = aResMap.find(aSubMesh);
        if( anIt==aResMap.end() ) {
            SMESH_subMesh *sm = aMesh.GetSubMesh(F);
            SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
            smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this));
            return false;
        }
        std::vector<int> aVec = (*anIt).second;
        nb0d += aVec[SMDSEntity_Node];
        nb1d += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]);
        double aLen = SMESH_Algo::EdgeLength(E);
        fullLen += aLen;
        if(IsFirst) {
            IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]);
            IsFirst = false;
        }
    }
    tmpMap.Clear();

    // compute edge length
    double ELen = 0;
    if (_hypLengthFromEdges || (!_hypLengthFromEdges && !_hypMaxElementArea)) {
        if ( nb1d > 0 )
            ELen = fullLen / nb1d;
    }
    if ( _hypMaxElementArea ) {
        double maxArea = _hypMaxElementArea->GetMaxArea();
        ELen = sqrt(2. * maxArea/sqrt(3.0));
    }
    GProp_GProps G;
    BRepGProp::SurfaceProperties(F,G);
    double anArea = G.Mass();

    const int hugeNb = numeric_limits<int>::max()/10;
    if ( anArea / hugeNb > ELen*ELen )
    {
        SMESH_subMesh *sm = aMesh.GetSubMesh(F);
        SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
        smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated.\nToo small element length",this));
        return false;
    }
    int nbFaces = (int) ( anArea / ( ELen*ELen*sqrt(3.) / 4 ) );
    int nbNodes = (int) ( ( nbFaces*3 - (nb1d-1)*2 ) / 6 + 1 );
    std::vector<int> aVec(SMDSEntity_Last);
    for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i]=0;
    if( IsQuadratic ) {
        aVec[SMDSEntity_Node] = nbNodes;
        aVec[SMDSEntity_Quad_Triangle] = nbFaces;
    }
    else {
        aVec[SMDSEntity_Node] = nbNodes;
        aVec[SMDSEntity_Triangle] = nbFaces;
    }
    SMESH_subMesh *sm = aMesh.GetSubMesh(F);
    aResMap.insert(std::make_pair(sm,aVec));

    return true;
}
Esempio n. 19
0
StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace,
                                         list<TopoDS_Edge>& theEdges,
                                         SMESH_Mesh*        theMesh,
                                         const bool         theIsForward,
                                         const bool         theIgnoreMediumNodes)
{
  int nbEdges = theEdges.size();
  myEdge.resize( nbEdges );
  myC2d.resize( nbEdges );
  myFirst.resize( nbEdges );
  myLast.resize( nbEdges );
  myNormPar.resize( nbEdges );
  myLength = 0;
  myNbPonits = myNbSegments = 0;
  myMesh = theMesh;
  myMissingVertexNodes = false;
  myIgnoreMediumNodes = theIgnoreMediumNodes;
  if ( nbEdges == 0 ) return;

  SMESHDS_Mesh* meshDS = theMesh->GetMeshDS();
  vector<double> len( nbEdges );

  int nbDegen = 0;
  list<TopoDS_Edge>::iterator edge = theEdges.begin();
  for ( int index = 0; edge != theEdges.end(); ++index, ++edge )
  {
    int i = theIsForward ? index : nbEdges - index - 1;
    len[i] = SMESH_Algo::EdgeLength( *edge );
    if ( len[i] < DBL_MIN ) nbDegen++;
    myLength += len[i];
    myEdge[i] = *edge;
    if ( !theIsForward ) myEdge[i].Reverse();

    if ( theFace.IsNull() )
      BRep_Tool::Range( *edge, myFirst[i], myLast[i] );
    else
      myC2d[i] = BRep_Tool::CurveOnSurface( *edge, theFace, myFirst[i], myLast[i] );
    if ( myEdge[i].Orientation() == TopAbs_REVERSED )
      std::swap( myFirst[i], myLast[i] );

    if ( SMESHDS_SubMesh* sm = meshDS->MeshElements( *edge )) {
      int nbN = sm->NbNodes();
      if ( theIgnoreMediumNodes ) {
        SMDS_ElemIteratorPtr elemIt = sm->GetElements();
        if ( elemIt->more() && elemIt->next()->IsQuadratic() )
          nbN -= sm->NbElements();
      }
      myNbPonits += nbN;
      myNbSegments += sm->NbElements();
    }
    if ( SMESH_Algo::VertexNode( TopExp::FirstVertex( *edge, 1), meshDS ))
      myNbPonits += 1; // for the first end
    else
      myMissingVertexNodes = true;
  }
  if ( SMESH_Algo::VertexNode( TopExp::LastVertex( theEdges.back(), 1), meshDS ))
    myNbPonits++; // for the last end
  else
    myMissingVertexNodes = true;

  if ( nbEdges > 1 && myLength > DBL_MIN ) {
    const double degenNormLen = 1.e-5;
    double totLength = myLength;
    if ( nbDegen )
      totLength += myLength * degenNormLen * nbDegen;
    double prevNormPar = 0;
    for ( int i = 0; i < nbEdges; ++i ) {
      if ( len[ i ] < DBL_MIN )
        len[ i ] = myLength * degenNormLen;
      myNormPar[ i ] = prevNormPar + len[i]/totLength;
      prevNormPar = myNormPar[ i ];
    }
  }
  myNormPar[nbEdges-1] = 1.;
  //dump();
}
Esempio n. 20
0
bool SMESH_Algo::IsReversedSubMesh (const TopoDS_Face&  theFace,
                                    SMESHDS_Mesh*       theMeshDS)
{
  if ( theFace.IsNull() || !theMeshDS )
    return false;

  // find out orientation of a meshed face
  int faceID = theMeshDS->ShapeToIndex( theFace );
  TopoDS_Shape aMeshedFace = theMeshDS->IndexToShape( faceID );
  bool isReversed = ( theFace.Orientation() != aMeshedFace.Orientation() );

  const SMESHDS_SubMesh * aSubMeshDSFace = theMeshDS->MeshElements( faceID );
  if ( !aSubMeshDSFace )
    return isReversed;

  // find element with node located on face and get its normal
  const SMDS_FacePosition* facePos = 0;
  int vertexID = 0;
  gp_Pnt nPnt[3];
  gp_Vec Ne;
  bool normalOK = false;
  SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements();
  while ( iteratorElem->more() ) // loop on elements on theFace
  {
    const SMDS_MeshElement* elem = iteratorElem->next();
    if ( elem && elem->NbNodes() > 2 ) {
      SMDS_ElemIteratorPtr nodesIt = elem->nodesIterator();
      const SMDS_FacePosition* fPos = 0;
      int i = 0, vID = 0;
      while ( nodesIt->more() ) { // loop on nodes
        const SMDS_MeshNode* node
          = static_cast<const SMDS_MeshNode *>(nodesIt->next());
        if ( i == 3 ) i = 2;
        nPnt[ i++ ].SetCoord( node->X(), node->Y(), node->Z() );
        // check position
        const SMDS_PositionPtr& pos = node->GetPosition();
        if ( !pos ) continue;
        if ( pos->GetTypeOfPosition() == SMDS_TOP_FACE ) {
          fPos = dynamic_cast< const SMDS_FacePosition* >( pos.get() );
        }
        else if ( pos->GetTypeOfPosition() == SMDS_TOP_VERTEX ) {
          vID = pos->GetShapeId();
        }
      }
      if ( fPos || ( !normalOK && vID )) {
        // compute normal
        gp_Vec v01( nPnt[0], nPnt[1] ), v02( nPnt[0], nPnt[2] );
        if ( v01.SquareMagnitude() > RealSmall() &&
             v02.SquareMagnitude() > RealSmall() )
        {
          Ne = v01 ^ v02;
          normalOK = ( Ne.SquareMagnitude() > RealSmall() );
        }
        // we need position on theFace or at least on vertex
        if ( normalOK ) {
          vertexID = vID;
          if ((facePos = fPos))
            break;
        }
      }
    }
  }
  if ( !normalOK )
    return isReversed;

  // node position on face
  double u,v;
  if ( facePos ) {
    u = facePos->GetUParameter();
    v = facePos->GetVParameter();
  }
  else if ( vertexID ) {
    TopoDS_Shape V = theMeshDS->IndexToShape( vertexID );
    if ( V.IsNull() || V.ShapeType() != TopAbs_VERTEX )
      return isReversed;
    gp_Pnt2d uv = BRep_Tool::Parameters( TopoDS::Vertex( V ), theFace );
    u = uv.X();
    v = uv.Y();
  }
  else
  {
    return isReversed;
  }

  // face normal at node position
  TopLoc_Location loc;
  Handle(Geom_Surface) surf = BRep_Tool::Surface( theFace, loc );
  if ( surf.IsNull() || surf->Continuity() < GeomAbs_C1 ) return isReversed;
  gp_Vec d1u, d1v;
  surf->D1( u, v, nPnt[0], d1u, d1v );
  gp_Vec Nf = (d1u ^ d1v).Transformed( loc );

  if ( theFace.Orientation() == TopAbs_REVERSED )
    Nf.Reverse();

  return Ne * Nf < 0.;
}
App::DocumentObjectExecReturn *DrawViewDetail::execute(void)
{
    if (!keepUpdated()) {
        return App::DocumentObject::StdReturn;
    }

    App::DocumentObject* baseObj = BaseView.getValue();
    if (!baseObj)  {
        Base::Console().Log("INFO - DVD::execute - No BaseView - creation?\n");
        return DrawView::execute();
    }

    DrawViewPart* dvp = nullptr;
    if (!baseObj->getTypeId().isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) {
        return new App::DocumentObjectExecReturn("BaseView object is not a DrawViewPart object");
    } else {
        dvp = static_cast<DrawViewPart*>(baseObj);
    }

    TopoDS_Shape shape = dvp->getSourceShapeFused();
    if (shape.IsNull()) {
        return new App::DocumentObjectExecReturn("DVD - Linked shape object is invalid");
    }

    Base::Vector3d anchor = AnchorPoint.getValue();    //this is a 2D point (in unrotated coords)
    Base::Vector3d dirDetail = dvp->Direction.getValue();

    double shapeRotate = dvp->Rotation.getValue();                      //degrees CW?
    if (dvp->isDerivedFrom(TechDraw::DrawProjGroupItem::getClassTypeId())) {
        DrawProjGroupItem* dpgi= static_cast<TechDraw::DrawProjGroupItem*>(dvp);
        shapeRotate += dpgi->getRotateAngle() * 180.0/M_PI;            // to degrees from radians
    }
 
    double radius = getFudgeRadius();
    double scale = getScale();

    BRepBuilderAPI_Copy BuilderCopy(shape);
    TopoDS_Shape myShape = BuilderCopy.Shape();

    //rotate the copied shape to match orientation of BaseView and center it on origin
    gp_Pnt gpCenter = TechDrawGeometry::findCentroid(myShape,           //centre of unrotated shape
                                                     dirDetail);
    Base::Vector3d shapeCenter = Base::Vector3d(gpCenter.X(),gpCenter.Y(),gpCenter.Z());
    gp_Ax2 viewAxis = getViewAxis(shapeCenter, dirDetail, false);
    myShape = TechDrawGeometry::rotateShape(myShape,                    //rotate to match Base shape
                                            viewAxis,
                                            -shapeRotate);
    myShape = TechDrawGeometry::moveShape(myShape,                     //centre on origin
                                          -shapeCenter);
    gpCenter = TechDrawGeometry::findCentroid(myShape,
                                              dirDetail);
    shapeCenter = Base::Vector3d(gpCenter.X(),gpCenter.Y(),gpCenter.Z());

    Bnd_Box bbxSource;
    bbxSource.SetGap(0.0);
    BRepBndLib::Add(myShape, bbxSource);
    double diag = sqrt(bbxSource.SquareExtent());

    Base::Vector3d extentFar,extentNear;
    extentFar = shapeCenter + dirDetail * diag;
    extentNear = shapeCenter + dirDetail * diag * -1.0;

    anchor = Base::Vector3d(anchor.x,anchor.y, 0.0);
    viewAxis = getViewAxis(shapeCenter, dirDetail, false);                //change view axis to (0,0,0)
    Base::Vector3d offsetCenter3D = DrawUtil::toR3(viewAxis, anchor);     //displacement in R3
    Base::Vector3d stdZ(0.0,0.0,1.0);
    if (DrawUtil::checkParallel(dirDetail,stdZ)) {
        extentNear = extentNear + offsetCenter3D;
    } else {
        extentNear = extentNear - offsetCenter3D;
    }

    gp_Pnt gpnt(extentNear.x,extentNear.y,extentNear.z);
    gp_Dir gdir(dirDetail.x,dirDetail.y,dirDetail.z);
    gp_Pln gpln(gpnt,gdir);
    double hideToolRadius = radius * 1.0;
    BRepBuilderAPI_MakeFace mkFace(gpln, -hideToolRadius,hideToolRadius,-hideToolRadius,hideToolRadius);
    TopoDS_Face aProjFace = mkFace.Face();
    if(aProjFace.IsNull()) {
        return new App::DocumentObjectExecReturn("DrawViewDetail - Projected face is NULL");
    }
    Base::Vector3d extrudeVec = dirDetail* (extentFar-extentNear).Length();
    gp_Vec extrudeDir(extrudeVec.x,extrudeVec.y,extrudeVec.z);
    TopoDS_Shape tool = BRepPrimAPI_MakePrism(aProjFace, extrudeDir, false, true).Shape();

    BRepAlgoAPI_Common mkCommon(myShape,tool);
    if (!mkCommon.IsDone()) {
        Base::Console().Log("DVD::execute - mkCommon not done\n");
        return new App::DocumentObjectExecReturn("DVD::execute - mkCommon not done");
    }
    if (mkCommon.Shape().IsNull()) {
        Base::Console().Log("DVD::execute - mkCommon.Shape is Null\n");
        return new App::DocumentObjectExecReturn("DVD::execute - mkCommon.Shape is Null");
    }

    //Did we get a solid?
    TopExp_Explorer xp;
    xp.Init(mkCommon.Shape(),TopAbs_SOLID);
    if (!(xp.More() == Standard_True)) {
        Base::Console().Warning("DVD::execute - mkCommon.Shape is not a solid!\n");
    }
    TopoDS_Shape detail = mkCommon.Shape();
    Bnd_Box testBox;
    testBox.SetGap(0.0);
    BRepBndLib::Add(detail, testBox);
    if (testBox.IsVoid()) {
        Base::Console().Message("DrawViewDetail - detail area contains no geometry\n");
        return new App::DocumentObjectExecReturn("DVDetail - detail area contains no geometry");
    }

//for debugging show compound instead of common
//    BRep_Builder builder;
//    TopoDS_Compound Comp;
//    builder.MakeCompound(Comp);
//    builder.Add(Comp, tool);
//    builder.Add(Comp, myShape);

    gp_Pnt inputCenter;
    try {
        inputCenter = TechDrawGeometry::findCentroid(tool,
                                                     Direction.getValue());
        TopoDS_Shape mirroredShape = TechDrawGeometry::mirrorShape(detail,
                                                    inputCenter,
                                                    scale);
        viewAxis = getViewAxis(Base::Vector3d(inputCenter.X(),inputCenter.Y(),inputCenter.Z()),Direction.getValue());
        if (!DrawUtil::fpCompare(Rotation.getValue(),0.0)) {
            mirroredShape = TechDrawGeometry::rotateShape(mirroredShape,
                                                          viewAxis,
                                                          Rotation.getValue());         //degrees cw?
        }

        geometryObject = buildGeometryObject(mirroredShape,viewAxis);
        geometryObject->pruneVertexGeom(Base::Vector3d(0.0,0.0,0.0),Radius.getValue() * scale);      //remove vertices beyond clipradius

#if MOD_TECHDRAW_HANDLE_FACES
    if (handleFaces()) {
        try {
            extractFaces();
        }
        catch (Standard_Failure& e4) {
            Base::Console().Log("LOG - DVD::execute - extractFaces failed for %s - %s **\n",getNameInDocument(),e4.GetMessageString());
            return new App::DocumentObjectExecReturn(e4.GetMessageString());
        }
    }

#endif //#if MOD_TECHDRAW_HANDLE_FACES
    }
    catch (Standard_Failure& e1) {
        Base::Console().Message("LOG - DVD::execute - failed to create detail %s - %s **\n",getNameInDocument(),e1.GetMessageString());

        return new App::DocumentObjectExecReturn(e1.GetMessageString());
    }

    requestPaint();
    dvp->requestPaint();

    return App::DocumentObject::StdReturn;
}