void BRepOffsetAPI_MakeOffsetFix::AddWire(const TopoDS_Wire& Spine) { TopoDS_Wire wire = Spine; int numEdges = 0; TopExp_Explorer xp(wire, TopAbs_EDGE); while (xp.More()) { numEdges++; xp.Next(); } if (numEdges == 1) { TopLoc_Location edgeLocation; BRepBuilderAPI_MakeWire mkWire; TopExp_Explorer xp(wire, TopAbs_EDGE); while (xp.More()) { // The trick is to reset the placement of an edge before // passing it to BRepOffsetAPI_MakeOffset because then it // will create the expected result. // Afterwards apply the placement again on the result shape. // See the method MakeWire() TopoDS_Edge edge = TopoDS::Edge(xp.Current()); edgeLocation = edge.Location(); edge.Location(TopLoc_Location()); mkWire.Add(edge); myLocations.push_back(std::make_pair(edge, edgeLocation)); xp.Next(); } wire = mkWire.Wire(); } mkOffset.AddWire(wire); myResult.Nullify(); }
// sometimes, we ask to replace the ending points of the curve // in gluing operations for example void OCCEdge::replaceEndingPointsInternals(GVertex *g0, GVertex *g1) { TopoDS_Vertex aV1 = *((TopoDS_Vertex*)v0->getNativePtr()); TopoDS_Vertex aV2 = *((TopoDS_Vertex*)v1->getNativePtr()); TopoDS_Vertex aVR1 = *((TopoDS_Vertex*)g0->getNativePtr()); TopoDS_Vertex aVR2 = *((TopoDS_Vertex*)g1->getNativePtr()); // printf("%p %p --- %p %p replacing %d %d by %d %d in occedge %d\n", // v0,v1,g0,g1,v0->tag(),v1->tag(),g0->tag(),g1->tag(),tag()); Standard_Boolean bIsDE = BRep_Tool::Degenerated(c); TopoDS_Edge aEx = c; aEx.Orientation(TopAbs_FORWARD); Standard_Real t1=s0; Standard_Real t2=s1; aVR1.Orientation(TopAbs_FORWARD); aVR2.Orientation(TopAbs_REVERSED); if (bIsDE) { Standard_Real aTol; BRep_Builder aBB; TopoDS_Edge E; //TopAbs_Orientation anOrE; //anOrE = c.Orientation(); aTol = BRep_Tool::Tolerance(c); E = aEx; E.EmptyCopy(); aBB.Add(E, aVR1); aBB.Add(E, aVR2); aBB.Range(E, t1, t2); aBB.Degenerated(E, Standard_True); aBB.UpdateEdge(E, aTol); _replacement=E; } else { #if (OCC_VERSION_MAJOR == 6) && (OCC_VERSION_MINOR < 6) BOPTools_Tools::MakeSplitEdge(aEx, aVR1, t1, aVR2, t2, _replacement); #else BOPTools_AlgoTools::MakeSplitEdge(aEx, aVR1, t1, aVR2, t2, _replacement); #endif } TopoDS_Edge temp = c; c = _replacement; _replacement = temp; curve = BRep_Tool::Curve(c, s0, s1); //build the reverse curve c_rev = c; c_rev.Reverse(); }
bool Edgecluster::IsValidEdge(const TopoDS_Edge& edge) { if ( edge.IsNull() ) return false; if ( BRep_Tool::Degenerated(edge) ) return false; BRepAdaptor_Curve bac(edge); Standard_Real fparam = bac.FirstParameter(); Standard_Real lparam = bac.LastParameter(); gp_Pnt fpoint = bac.Value(fparam); gp_Pnt lpoint = bac.Value(lparam); //do not test the distance first last in case of a full circle edge (fpoint == lastpoint) //if ( fpoint.IsEqual(lpoint,1e-5 ) ) // return false; gp_Pnt mpoint = bac.Value((fparam+lparam)*0.5); Standard_Real dist = mpoint.Distance(lpoint); if ( dist <= 1e-5 ) return false; dist = mpoint.Distance(fpoint); if ( dist <= 1e-5 ) return false; return true; }
//======================================================================= //function : GetEdgeOff //purpose : //======================================================================= Standard_Boolean GEOMAlgo_Tools3D::GetEdgeOff(const TopoDS_Edge& theE1, const TopoDS_Face& theF2, TopoDS_Edge& theE2) { Standard_Boolean bFound; TopAbs_Orientation aOr1, aOr1C, aOr2; TopExp_Explorer anExp; // bFound=Standard_False; aOr1=theE1.Orientation(); aOr1C=TopAbs::Reverse(aOr1); // anExp.Init(theF2, TopAbs_EDGE); for (; anExp.More(); anExp.Next()) { const TopoDS_Edge& aEF2=TopoDS::Edge(anExp.Current()); if (aEF2.IsSame(theE1)) { aOr2=aEF2.Orientation(); if (aOr2==aOr1C) { theE2=aEF2; bFound=!bFound; return bFound; } } } return bFound; }
//======================================================================= //function :IsSplitToReverse //purpose : //======================================================================= Standard_Boolean GEOMAlgo_Tools3D::IsSplitToReverse(const TopoDS_Edge& theSplit, const TopoDS_Edge& theEdge, IntTools_Context& theContext) { Standard_Boolean bRet, aFlag, bIsDegenerated; Standard_Real aTE, aTS, aScPr, aTa, aTb, aT1, aT2; TopAbs_Orientation aOrSr, aOrSp; Handle(Geom_Curve) aCEdge, aCSplit; gp_Vec aVE, aVS; gp_Pnt aP; // bRet=Standard_False; // bIsDegenerated=(BRep_Tool::Degenerated(theSplit) || BRep_Tool::Degenerated(theEdge)); if (bIsDegenerated) { return bRet; } // aCEdge =BRep_Tool::Curve(theEdge , aT1, aT2); aCSplit=BRep_Tool::Curve(theSplit, aTa, aTb); // if (aCEdge==aCSplit) { aOrSr=theEdge.Orientation(); aOrSp=theSplit.Orientation(); bRet=(aOrSr!=aOrSp); return bRet; } // aTS=BOPTools_Tools2D::IntermediatePoint(aTa, aTb); aCSplit->D0(aTS, aP); aFlag=BOPTools_Tools2D::EdgeTangent(theSplit, aTS, aVS); gp_Dir aDTS(aVS); // aFlag=theContext.ProjectPointOnEdge(aP, theEdge, aTE); aFlag=BOPTools_Tools2D::EdgeTangent(theEdge, aTE, aVE); gp_Dir aDTE(aVE); // aScPr=aDTS*aDTE; bRet=(aScPr<0.); // return bRet; }
TopoDS_Edge StdMeshers_Hexa_3D::EdgeNotInFace(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, const TopoDS_Face & aFace, const TopoDS_Vertex & aVertex, const TopTools_IndexedDataMapOfShapeListOfShape & MS) { //MESSAGE("StdMeshers_Hexa_3D::EdgeNotInFace"); TopTools_IndexedDataMapOfShapeListOfShape MF; TopExp::MapShapesAndAncestors(aFace, TopAbs_VERTEX, TopAbs_EDGE, MF); const TopTools_ListOfShape & ancestorsInSolid = MS.FindFromKey(aVertex); const TopTools_ListOfShape & ancestorsInFace = MF.FindFromKey(aVertex); // SCRUTE(ancestorsInSolid.Extent()); // SCRUTE(ancestorsInFace.Extent()); ASSERT(ancestorsInSolid.Extent() == 6); // 6 (edges doublees) ASSERT(ancestorsInFace.Extent() == 2); TopoDS_Edge E; E.Nullify(); TopTools_ListIteratorOfListOfShape its(ancestorsInSolid); for (; its.More(); its.Next()) { TopoDS_Shape ancestor = its.Value(); TopTools_ListIteratorOfListOfShape itf(ancestorsInFace); bool isInFace = false; for (; itf.More(); itf.Next()) { TopoDS_Shape ancestorInFace = itf.Value(); if (ancestorInFace.IsSame(ancestor)) { isInFace = true; break; } } if (!isInFace) { E = TopoDS::Edge(ancestor); break; } } return E; }
//======================================================================= //function : SamePnt2d //purpose : //======================================================================= static Standard_Boolean SamePnt2d(TopoDS_Vertex V, TopoDS_Edge& E1, TopoDS_Edge& E2, TopoDS_Face& F) { Standard_Real f1,f2,l1,l2; gp_Pnt2d P1,P2; TopoDS_Shape aLocalF = F.Oriented(TopAbs_FORWARD); TopoDS_Face FF = TopoDS::Face(aLocalF); Handle(Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(E1,FF,f1,l1); Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(E2,FF,f2,l2); if (E1.Orientation () == TopAbs_FORWARD) P1 = C1->Value(f1); else P1 = C1->Value(l1); if (E2.Orientation () == TopAbs_FORWARD) P2 = C2->Value(l2); else P2 = C2->Value(f2); Standard_Real Tol = 100*BRep_Tool::Tolerance(V); Standard_Real Dist = P1.Distance(P2); return Dist < Tol; }
bool SMESH_Algo::GetSortedNodesOnEdge(const SMESHDS_Mesh* theMesh, const TopoDS_Edge& theEdge, const bool ignoreMediumNodes, map< double, const SMDS_MeshNode* > & theNodes) { theNodes.clear(); if ( !theMesh || theEdge.IsNull() ) return false; SMESHDS_SubMesh * eSubMesh = theMesh->MeshElements( theEdge ); if ( !eSubMesh || !eSubMesh->GetElements()->more() ) return false; // edge is not meshed int nbNodes = 0; set < double > paramSet; if ( eSubMesh ) { // loop on nodes of an edge: sort them by param on edge SMDS_NodeIteratorPtr nIt = eSubMesh->GetNodes(); while ( nIt->more() ) { const SMDS_MeshNode* node = nIt->next(); if ( ignoreMediumNodes ) { SMDS_ElemIteratorPtr elemIt = node->GetInverseElementIterator(); if ( elemIt->more() && elemIt->next()->IsMediumNode( node )) continue; } const SMDS_PositionPtr& pos = node->GetPosition(); if ( pos->GetTypeOfPosition() != SMDS_TOP_EDGE ) return false; const SMDS_EdgePosition* epos = static_cast<const SMDS_EdgePosition*>(node->GetPosition().get()); theNodes.insert( make_pair( epos->GetUParameter(), node )); ++nbNodes; } } // add vertex nodes TopoDS_Vertex v1, v2; TopExp::Vertices(theEdge, v1, v2); const SMDS_MeshNode* n1 = VertexNode( v1, (SMESHDS_Mesh*) theMesh ); const SMDS_MeshNode* n2 = VertexNode( v2, (SMESHDS_Mesh*) theMesh ); Standard_Real f, l; BRep_Tool::Range(theEdge, f, l); if ( v1.Orientation() != TopAbs_FORWARD ) std::swap( f, l ); if ( n1 && ++nbNodes ) theNodes.insert( make_pair( f, n1 )); if ( n2 && ++nbNodes ) theNodes.insert( make_pair( l, n2 )); return theNodes.size() == nbNodes; }
bool SMESH_Algo::GetNodeParamOnEdge(const SMESHDS_Mesh* theMesh, const TopoDS_Edge& theEdge, vector< double > & theParams) { theParams.clear(); if ( !theMesh || theEdge.IsNull() ) return false; SMESHDS_SubMesh * eSubMesh = theMesh->MeshElements( theEdge ); if ( !eSubMesh || !eSubMesh->GetElements()->more() ) return false; // edge is not meshed //int nbEdgeNodes = 0; set < double > paramSet; if ( eSubMesh ) { // loop on nodes of an edge: sort them by param on edge SMDS_NodeIteratorPtr nIt = eSubMesh->GetNodes(); while ( nIt->more() ) { const SMDS_MeshNode* node = nIt->next(); const SMDS_PositionPtr& pos = node->GetPosition(); if ( pos->GetTypeOfPosition() != SMDS_TOP_EDGE ) return false; const SMDS_EdgePosition* epos = static_cast<const SMDS_EdgePosition*>(node->GetPosition().get()); if ( !paramSet.insert( epos->GetUParameter() ).second ) return false; // equal parameters } } // add vertex nodes params TopoDS_Vertex V1,V2; TopExp::Vertices( theEdge, V1, V2); if ( VertexNode( V1, theMesh ) && !paramSet.insert( BRep_Tool::Parameter(V1,theEdge) ).second ) return false; // there are equal parameters if ( VertexNode( V2, theMesh ) && !paramSet.insert( BRep_Tool::Parameter(V2,theEdge) ).second ) return false; // there are equal parameters // fill the vector theParams.resize( paramSet.size() ); set < double >::iterator par = paramSet.begin(); vector< double >::iterator vecPar = theParams.begin(); for ( ; par != paramSet.end(); ++par, ++vecPar ) *vecPar = *par; return theParams.size() > 1; }
StdMeshers_FaceSide * StdMeshers_CompositeSegment_1D::GetFaceSide(SMESH_Mesh& aMesh, const TopoDS_Edge& anEdge, const TopoDS_Face& aFace, const bool ignoreMeshed) { list< TopoDS_Edge > edges; edges.push_back( anEdge ); list <const SMESHDS_Hypothesis *> hypList; SMESH_Algo* theAlgo = aMesh.GetGen()->GetAlgo( aMesh, anEdge ); if ( theAlgo ) hypList = theAlgo->GetUsedHypothesis(aMesh, anEdge, false); for ( int forward = 0; forward < 2; ++forward ) { TopoDS_Edge eNext = nextC1Edge( anEdge, aMesh, forward ); while ( !eNext.IsNull() ) { if ( ignoreMeshed ) { // eNext must not have computed mesh if ( SMESHDS_SubMesh* sm = aMesh.GetMeshDS()->MeshElements(eNext) ) if ( sm->NbNodes() || sm->NbElements() ) break; } // eNext must have same hypotheses SMESH_Algo* algo = aMesh.GetGen()->GetAlgo( aMesh, eNext ); if ( !algo || string(theAlgo->GetName()) != algo->GetName() || hypList != algo->GetUsedHypothesis(aMesh, eNext, false)) break; if ( forward ) edges.push_back( eNext ); else edges.push_front( eNext ); eNext = nextC1Edge( eNext, aMesh, forward ); } } return new StdMeshers_FaceSide( aFace, edges, &aMesh, true, false ); }
void Edgecluster::Perform(const TopoDS_Edge& edge) { if ( edge.IsNull() ) return; TopoDS_Vertex V1,V2; TopExp::Vertices(edge,V1,V2); gp_Pnt P1 = BRep_Tool::Pnt(V1); gp_Pnt P2 = BRep_Tool::Pnt(V2); tEdgeVector emptyList; std::pair<tMapPntEdge::iterator,bool> iter = m_vertices.insert(tMapPntEdgePair(P1,emptyList)); iter.first->second.push_back(edge); iter = m_vertices.insert(tMapPntEdgePair(P2,emptyList)); iter.first->second.push_back(edge); }
int convert_to_ifc(const TopoDS_Edge& e, IfcSchema::IfcEdge*& edge, bool advanced) { double a, b; TopExp_Explorer exp(e, TopAbs_VERTEX); if (!exp.More()) return 0; TopoDS_Vertex v1 = TopoDS::Vertex(exp.Current()); exp.Next(); if (!exp.More()) return 0; TopoDS_Vertex v2 = TopoDS::Vertex(exp.Current()); IfcSchema::IfcVertex *vertex1, *vertex2; if (!(convert_to_ifc(v1, vertex1, advanced) && convert_to_ifc(v2, vertex2, advanced))) { return 0; } Handle_Geom_Curve crv = BRep_Tool::Curve(e, a, b); if (crv.IsNull()) { return 0; } if (crv->DynamicType() == STANDARD_TYPE(Geom_Line) && !advanced) { IfcSchema::IfcEdge* edge2 = new IfcSchema::IfcEdge(vertex1, vertex2); edge = new IfcSchema::IfcOrientedEdge(edge2, true); return 1; } else { IfcSchema::IfcCurve* curve; if (!convert_to_ifc(crv, curve, advanced)) { return 0; } /// @todo probably not correct const bool sense = e.Orientation() == TopAbs_FORWARD; IfcSchema::IfcEdge* edge2 = new IfcSchema::IfcEdgeCurve(vertex1, vertex2, curve, true); edge = new IfcSchema::IfcOrientedEdge(edge2, sense); return 1; } }
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()); } }
void ProfileBased::getAxis(const App::DocumentObject *pcReferenceAxis, const std::vector<std::string> &subReferenceAxis, Base::Vector3d& base, Base::Vector3d& dir) { dir = Base::Vector3d(0,0,0); // If unchanged signals that no valid axis was found if (pcReferenceAxis == NULL) return; App::DocumentObject* profile = Profile.getValue(); gp_Pln sketchplane; if (profile->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) { Part::Part2DObject* sketch = getVerifiedSketch(); Base::Placement SketchPlm = sketch->Placement.getValue(); Base::Vector3d SketchVector = Base::Vector3d(0, 0, 1); Base::Rotation SketchOrientation = SketchPlm.getRotation(); SketchOrientation.multVec(SketchVector, SketchVector); Base::Vector3d SketchPos = SketchPlm.getPosition(); sketchplane = gp_Pln(gp_Pnt(SketchPos.x, SketchPos.y, SketchPos.z), gp_Dir(SketchVector.x, SketchVector.y, SketchVector.z)); if (pcReferenceAxis == profile) { bool hasValidAxis = false; Base::Axis axis; if (subReferenceAxis[0] == "V_Axis") { hasValidAxis = true; axis = sketch->getAxis(Part::Part2DObject::V_Axis); } else if (subReferenceAxis[0] == "H_Axis") { hasValidAxis = true; axis = sketch->getAxis(Part::Part2DObject::H_Axis); } else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0, 4) == "Axis") { int AxId = std::atoi(subReferenceAxis[0].substr(4, 4000).c_str()); if (AxId >= 0 && AxId < sketch->getAxisCount()) { hasValidAxis = true; axis = sketch->getAxis(AxId); } } if (hasValidAxis) { axis *= SketchPlm; base = axis.getBase(); dir = axis.getDirection(); return; } //else - an edge of the sketch was selected as an axis } } else if (profile->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { Base::Placement SketchPlm = getVerifiedObject()->Placement.getValue(); Base::Vector3d SketchVector = getProfileNormal(); Base::Vector3d SketchPos = SketchPlm.getPosition(); sketchplane = gp_Pln(gp_Pnt(SketchPos.x, SketchPos.y, SketchPos.z), gp_Dir(SketchVector.x, SketchVector.y, SketchVector.z)); } // get reference axis if (pcReferenceAxis->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) { const PartDesign::Line* line = static_cast<const PartDesign::Line*>(pcReferenceAxis); base = line->getBasePoint(); dir = line->getDirection(); // Check that axis is perpendicular with sketch plane! if (sketchplane.Axis().Direction().IsParallel(gp_Dir(dir.x, dir.y, dir.z), Precision::Angular())) throw Base::ValueError("Rotation axis must not be perpendicular with the sketch plane"); return; } if (pcReferenceAxis->getTypeId().isDerivedFrom(App::Line::getClassTypeId())) { const App::Line* line = static_cast<const App::Line*>(pcReferenceAxis); base = Base::Vector3d(0,0,0); line->Placement.getValue().multVec(Base::Vector3d (1,0,0), dir); // Check that axis is perpendicular with sketch plane! if (sketchplane.Axis().Direction().IsParallel(gp_Dir(dir.x, dir.y, dir.z), Precision::Angular())) throw Base::ValueError("Rotation axis must not be perpendicular with the sketch plane"); return; } if (pcReferenceAxis->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { if (subReferenceAxis.empty()) throw Base::ValueError("No rotation axis reference specified"); const Part::Feature* refFeature = static_cast<const Part::Feature*>(pcReferenceAxis); Part::TopoShape refShape = refFeature->Shape.getShape(); TopoDS_Shape ref = refShape.getSubShape(subReferenceAxis[0].c_str()); if (ref.ShapeType() == TopAbs_EDGE) { TopoDS_Edge refEdge = TopoDS::Edge(ref); if (refEdge.IsNull()) throw Base::ValueError("Failed to extract rotation edge"); BRepAdaptor_Curve adapt(refEdge); if (adapt.GetType() != GeomAbs_Line) throw Base::TypeError("Rotation edge must be a straight line"); gp_Pnt b = adapt.Line().Location(); base = Base::Vector3d(b.X(), b.Y(), b.Z()); gp_Dir d = adapt.Line().Direction(); dir = Base::Vector3d(d.X(), d.Y(), d.Z()); // Check that axis is co-planar with sketch plane! // Check that axis is perpendicular with sketch plane! if (sketchplane.Axis().Direction().IsParallel(d, Precision::Angular())) throw Base::ValueError("Rotation axis must not be perpendicular with the sketch plane"); return; } else { throw Base::TypeError("Rotation reference must be an edge"); } } throw Base::TypeError("Rotation axis reference is invalid"); }
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 SMESH_MesherHelper::LoadNodeColumns(TParam2ColumnMap & theParam2ColumnMap, const TopoDS_Face& theFace, const TopoDS_Edge& theBaseEdge, SMESHDS_Mesh* theMesh) { // get vertices of theBaseEdge TopoDS_Vertex vfb, vlb, vft; // first and last, bottom and top vertices TopoDS_Edge eFrw = TopoDS::Edge( theBaseEdge.Oriented( TopAbs_FORWARD )); TopExp::Vertices( eFrw, vfb, vlb ); // find the other edges of theFace and orientation of e1 TopoDS_Edge e1, e2, eTop; bool rev1, CumOri = false; TopExp_Explorer exp( theFace, TopAbs_EDGE ); int nbEdges = 0; for ( ; exp.More(); exp.Next() ) { if ( ++nbEdges > 4 ) { return false; // more than 4 edges in theFace } TopoDS_Edge e = TopoDS::Edge( exp.Current() ); if ( theBaseEdge.IsSame( e )) continue; TopoDS_Vertex vCommon; if ( !TopExp::CommonVertex( theBaseEdge, e, vCommon )) eTop = e; else if ( vCommon.IsSame( vfb )) { e1 = e; vft = TopExp::LastVertex( e1, CumOri ); rev1 = vfb.IsSame( vft ); if ( rev1 ) vft = TopExp::FirstVertex( e1, CumOri ); } else e2 = e; } if ( nbEdges < 4 ) { return false; // less than 4 edges in theFace } if ( e2.IsNull() && vfb.IsSame( vlb )) e2 = e1; // submeshes corresponding to shapes SMESHDS_SubMesh* smFace = theMesh->MeshElements( theFace ); SMESHDS_SubMesh* smb = theMesh->MeshElements( theBaseEdge ); SMESHDS_SubMesh* smt = theMesh->MeshElements( eTop ); SMESHDS_SubMesh* sm1 = theMesh->MeshElements( e1 ); SMESHDS_SubMesh* sm2 = theMesh->MeshElements( e2 ); SMESHDS_SubMesh* smVfb = theMesh->MeshElements( vfb ); SMESHDS_SubMesh* smVlb = theMesh->MeshElements( vlb ); SMESHDS_SubMesh* smVft = theMesh->MeshElements( vft ); if (!smFace || !smb || !smt || !sm1 || !sm2 || !smVfb || !smVlb || !smVft ) { RETURN_BAD_RESULT( "NULL submesh " <<smFace<<" "<<smb<<" "<<smt<<" "<< sm1<<" "<<sm2<<" "<<smVfb<<" "<<smVlb<<" "<<smVft); } if ( smb->NbNodes() != smt->NbNodes() || sm1->NbNodes() != sm2->NbNodes() ) { RETURN_BAD_RESULT(" Diff nb of nodes on opposite edges" ); } if (smVfb->NbNodes() != 1 || smVlb->NbNodes() != 1 || smVft->NbNodes() != 1) { RETURN_BAD_RESULT("Empty submesh of vertex"); } // define whether mesh is quadratic bool isQuadraticMesh = false; SMDS_ElemIteratorPtr eIt = smFace->GetElements(); if ( !eIt->more() ) { RETURN_BAD_RESULT("No elements on the face"); } const SMDS_MeshElement* e = eIt->next(); isQuadraticMesh = e->IsQuadratic(); if ( sm1->NbNodes() * smb->NbNodes() != smFace->NbNodes() ) { // check quadratic case if ( isQuadraticMesh ) { // what if there are quadrangles and triangles mixed? // int n1 = sm1->NbNodes()/2; // int n2 = smb->NbNodes()/2; // int n3 = sm1->NbNodes() - n1; // int n4 = smb->NbNodes() - n2; // int nf = sm1->NbNodes()*smb->NbNodes() - n3*n4; // if( nf != smFace->NbNodes() ) { // MESSAGE( "Wrong nb face nodes: " << // sm1->NbNodes()<<" "<<smb->NbNodes()<<" "<<smFace->NbNodes()); // return false; // } } else { RETURN_BAD_RESULT( "Wrong nb face nodes: " << sm1->NbNodes()<<" "<<smb->NbNodes()<<" "<<smFace->NbNodes()); } } // IJ size int vsize = sm1->NbNodes() + 2; int hsize = smb->NbNodes() + 2; if(isQuadraticMesh) { vsize = vsize - sm1->NbNodes()/2 -1; hsize = hsize - smb->NbNodes()/2 -1; } // load nodes from theBaseEdge std::set<const SMDS_MeshNode*> loadedNodes; const SMDS_MeshNode* nullNode = 0; std::vector<const SMDS_MeshNode*> & nVecf = theParam2ColumnMap[ 0.]; nVecf.resize( vsize, nullNode ); loadedNodes.insert( nVecf[ 0 ] = smVfb->GetNodes()->next() ); std::vector<const SMDS_MeshNode*> & nVecl = theParam2ColumnMap[ 1.]; nVecl.resize( vsize, nullNode ); loadedNodes.insert( nVecl[ 0 ] = smVlb->GetNodes()->next() ); double f, l; BRep_Tool::Range( eFrw, f, l ); double range = l - f; SMDS_NodeIteratorPtr nIt = smb->GetNodes(); const SMDS_MeshNode* node; while ( nIt->more() ) { node = nIt->next(); if(IsMedium(node, SMDSAbs_Edge)) continue; const SMDS_EdgePosition* pos = dynamic_cast<const SMDS_EdgePosition*>( node->GetPosition().get() ); if ( !pos ) { return false; } double u = ( pos->GetUParameter() - f ) / range; std::vector<const SMDS_MeshNode*> & nVec = theParam2ColumnMap[ u ]; nVec.resize( vsize, nullNode ); loadedNodes.insert( nVec[ 0 ] = node ); } if ( theParam2ColumnMap.size() != hsize ) { RETURN_BAD_RESULT( "Wrong node positions on theBaseEdge" ); } // load nodes from e1 std::map< double, const SMDS_MeshNode*> sortedNodes; // sort by param on edge nIt = sm1->GetNodes(); while ( nIt->more() ) { node = nIt->next(); if(IsMedium(node)) continue; const SMDS_EdgePosition* pos = dynamic_cast<const SMDS_EdgePosition*>( node->GetPosition().get() ); if ( !pos ) { return false; } sortedNodes.insert( std::make_pair( pos->GetUParameter(), node )); } loadedNodes.insert( nVecf[ vsize - 1 ] = smVft->GetNodes()->next() ); std::map< double, const SMDS_MeshNode*>::iterator u_n = sortedNodes.begin(); int row = rev1 ? vsize - 1 : 0; int dRow = rev1 ? -1 : +1; for ( ; u_n != sortedNodes.end(); u_n++ ) { row += dRow; loadedNodes.insert( nVecf[ row ] = u_n->second ); } // try to load the rest nodes // get all faces from theFace TIDSortedElemSet allFaces, foundFaces; eIt = smFace->GetElements(); while ( eIt->more() ) { const SMDS_MeshElement* e = eIt->next(); if ( e->GetType() == SMDSAbs_Face ) allFaces.insert( e ); } // Starting from 2 neighbour nodes on theBaseEdge, look for a face // the nodes belong to, and between the nodes of the found face, // look for a not loaded node considering this node to be the next // in a column of the starting second node. Repeat, starting // from nodes next to the previous starting nodes in their columns, // and so on while a face can be found. Then go the the next pair // of nodes on theBaseEdge. TParam2ColumnMap::iterator par_nVec_1 = theParam2ColumnMap.begin(); TParam2ColumnMap::iterator par_nVec_2 = par_nVec_1; // loop on columns int col = 0; for ( par_nVec_2++; par_nVec_2 != theParam2ColumnMap.end(); par_nVec_1++, par_nVec_2++ ) { col++; row = 0; const SMDS_MeshNode* n1 = par_nVec_1->second[ row ]; const SMDS_MeshNode* n2 = par_nVec_2->second[ row ]; const SMDS_MeshElement* face = 0; bool lastColOnClosedFace = ( nVecf[ row ] == n2 ); do { // look for a face by 2 nodes face = SMESH_MeshEditor::FindFaceInSet( n1, n2, allFaces, foundFaces ); if ( face ) { int nbFaceNodes = face->NbNodes(); if ( face->IsQuadratic() ) nbFaceNodes /= 2; if ( nbFaceNodes>4 ) { RETURN_BAD_RESULT(" Too many nodes in a face: " << nbFaceNodes ); } // look for a not loaded node of the <face> bool found = false; const SMDS_MeshNode* n3 = 0; // a node defferent from n1 and n2 for ( int i = 0; i < nbFaceNodes && !found; ++i ) { node = face->GetNode( i ); found = loadedNodes.insert( node ).second; if ( !found && node != n1 && node != n2 ) n3 = node; } if ( lastColOnClosedFace && row + 1 < vsize ) { node = nVecf[ row + 1 ]; found = ( face->GetNodeIndex( node ) >= 0 ); } if ( found ) { if ( ++row > vsize - 1 ) { RETURN_BAD_RESULT( "Too many nodes in column "<< col <<": "<< row+1); } par_nVec_2->second[ row ] = node; foundFaces.insert( face ); n2 = node; if ( nbFaceNodes==4 ) { n1 = par_nVec_1->second[ row ]; } } else if ( nbFaceNodes==3 && n3 == par_nVec_1->second[ row + 1 ] ) { n1 = n3; } else { RETURN_BAD_RESULT( "Not quad mesh, column "<< col ); } } } while ( face && n1 && n2 ); if ( row < vsize - 1 ) { MESSAGE( "Too few nodes in column "<< col <<": "<< row+1); MESSAGE( "Base node 1: "<< par_nVec_1->second[0]); MESSAGE( "Base node 2: "<< par_nVec_2->second[0]); if ( n1 ) { MESSAGE( "Current node 1: "<< n1); } else { MESSAGE( "Current node 1: NULL"); } if ( n2 ) { MESSAGE( "Current node 2: "<< n2); } else { MESSAGE( "Current node 2: NULL"); } MESSAGE( "first base node: "<< theParam2ColumnMap.begin()->second[0]); MESSAGE( "last base node: "<< theParam2ColumnMap.rbegin()->second[0]); return false; } } // loop on columns return true; }
//============================================================================= 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(); }
bool RoomLayoutPillarController::PreRender3D() { auto& imp_ = *ImpUPtr_; plane3df plan(0,0,0,0,1,0); auto line = GetRenderContextSPtr()->Smgr_->getSceneCollisionManager()->getRayFromScreenCoordinates(imp_.CursorIPos_); plan.getIntersectionWithLine(line.start, line.getVector(), imp_.CurrentPos_); imp_.CurrentPos_.Y = 0; gp_Pnt cursorPnt(imp_.CurrentPos_.X, imp_.CurrentPos_.Y, imp_.CurrentPos_.Z); switch (imp_.State_) { case EPilarState::EPS_SWEEPING: { if ( GetPickingODL().expired() ) { break; } auto activePilar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock()); activePilar->SetSweeping(true); if ( imp_.CtrllHolding_ ) { imp_.State_ = EPilarState::EPS_MODIFY_INIT; break; } if ( imp_.LMousePressDown_ ) { auto box = activePilar->GetBaseBndBox(); auto pos = activePilar->GetTranslation(); Standard_Real xMin,xMax,yMin,yMax,zMin,zMax; box.Get(xMin, yMin, zMin, xMax, yMax, zMax); imp_.EventInfo_ = SEventPillarInfo(); imp_.EventInfo_->XLength_ = static_cast<float>(xMax-xMin); imp_.EventInfo_->YLength_ = static_cast<float>(yMax-yMin); imp_.EventInfo_->ZLength_ = static_cast<float>(zMax-zMin); imp_.EventInfo_->OffsetHeight_ = activePilar->GetOffsetHeight(); imp_.SavePos_ = imp_.CurrentPos_; imp_.State_ = EPilarState::EPS_MOUSEHOLDING; } } break; case EPilarState::EPS_MODIFY_INIT: { auto activePilar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock()); activePilar->SetSweeping(true); if ( !imp_.CtrllHolding_ ) { GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_NORMAL); imp_.State_ = EPilarState::EPS_SWEEPING; imp_.CtrllHolding_ = false; break; } auto box = activePilar->GetBaseBndBox(); Standard_Real xMin,xMax,yMin,yMax,zMin,zMax; box.Get(xMin, yMin, zMin, xMax, yMax, zMax); auto modifyAlign = 100; Bnd_Box smallBox,bigBox; smallBox.Update(xMin+modifyAlign < 0 ? xMin+modifyAlign : 0, yMin+modifyAlign < 0 ? yMin+modifyAlign : 0, zMin+modifyAlign < 0 ? zMin+modifyAlign : 0, xMax-modifyAlign > 0 ? xMax-modifyAlign : 0, yMax-modifyAlign > 0 ? yMax-modifyAlign : 0, zMax-modifyAlign > 0 ? zMax-modifyAlign : 0); bigBox.Update(xMin-modifyAlign, yMin-modifyAlign, zMin-modifyAlign, xMax+modifyAlign, yMax+modifyAlign, zMax+modifyAlign); auto relationCursorPnt = cursorPnt.Transformed(activePilar->GetAbsoluteTransform().Inverted()); relationCursorPnt.SetY(0); if ( Standard_True == bigBox.IsOut(relationCursorPnt) ) { GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_NORMAL); imp_.State_ = EPilarState::EPS_SWEEPING; imp_.CtrllHolding_ = false; break; } if ( Standard_False == smallBox.IsOut(relationCursorPnt) ) { GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_NORMAL); break; } gp_Dir cursorDir = gp_Vec(gp::Origin(), relationCursorPnt); { auto rad = gp::DX().AngleWithRef(cursorDir, gp::DY()); rad = rad < 0 ? M_PI * 2 + rad : rad; auto mod = std::fmod(rad, M_PI_2); if ( mod < M_PI_4 ) { rad -= mod; } else { rad = rad - mod + M_PI_2; } cursorDir = gp::DX().Rotated(gp::OY(), rad); mod = std::fmod(rad, M_PI); if ( mod < Precision::Angular() ) { GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_SIZEWE); } else { GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_SIZENS); } } if ( imp_.LMousePressDown_ ) { auto edge = BRepBuilderAPI_MakeEdge(gp_Lin(gp::Origin().Transformed(activePilar->GetAbsoluteTransform()), cursorDir.Transformed(activePilar->GetAbsoluteTransform()))).Edge(); BRepAdaptor_Curve moveBC(edge); GeomAPI_ProjectPointOnCurve ppc(relationCursorPnt.Transformed(activePilar->GetAbsoluteTransform()), moveBC.Curve().Curve()); imp_.ModifyEdge_ = moveBC; imp_.ModifyPar_ = ppc.LowerDistanceParameter(); imp_.State_ = EPilarState::EPS_MODIFY; break; } } break; case EPilarState::EPS_MODIFY: { auto activePilar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock()); activePilar->SetPicking(true); if ( imp_.LMouseLeftUp_ ) { activePilar->UpdateMesh(); imp_.State_ = EPilarState::EPS_SWEEPING; break; } GeomAPI_ProjectPointOnCurve ppcCur(cursorPnt, imp_.ModifyEdge_.Curve().Curve()); auto curPar = ppcCur.LowerDistanceParameter(); if ( std::abs(curPar - imp_.ModifyPar_) < Precision::Confusion() ) { break; } //偏移的起始点、终点(绝对) gp_Pnt fromPnt,toPnt; imp_.ModifyEdge_.D0(imp_.ModifyPar_, fromPnt); imp_.ModifyEdge_.D0(curPar, toPnt); gp_Vec moveOffset(fromPnt, toPnt); auto relationMoveOffset = moveOffset.Transformed(activePilar->GetAbsoluteTransform().Inverted()); auto modifyDir = imp_.ModifyEdge_.Line().Direction().Transformed(activePilar->GetAbsoluteTransform().Inverted()); auto modifyOffset = relationMoveOffset; { modifyOffset.SetX(modifyOffset.X() * modifyDir.X()); modifyOffset.SetY(modifyOffset.Y() * modifyDir.Y()); modifyOffset.SetZ(modifyOffset.Z() * modifyDir.Z()); } auto curPillarSize = activePilar->GetSize(); if ( Standard_False == imp_.ModifyEdge_.Line().Direction().IsEqual(gp_Dir(moveOffset), Precision::Angular()) ) {//防止大小缩成0 auto testSize = curPillarSize + modifyOffset.XYZ(); auto minSize = 100; auto alignSize = testSize - gp_XYZ(minSize,minSize,minSize); if ( alignSize.X() < Precision::Confusion() || alignSize.Y() < Precision::Confusion() || alignSize.Z() < Precision::Confusion() ) { break; } } Bnd_Box pillarBox; auto pillarBoxSize = curPillarSize + modifyOffset.XYZ(); gp_Trsf pillarTranslation,pillarRotation,pillarTransformation; { pillarBox.Update(-pillarBoxSize.X()/2, -pillarBoxSize.Y()/2, -pillarBoxSize.Z()/2, pillarBoxSize.X()/2, pillarBoxSize.Y()/2, pillarBoxSize.Z()/2); auto translation = activePilar->GetTranslation() + relationMoveOffset.XYZ()/2; pillarTranslation.SetTranslationPart(translation); pillarRotation.SetRotation(activePilar->GetRotation()); } pillarTransformation = pillarTranslation * pillarRotation; auto offsetHeight = activePilar->GetOffsetHeight(); //新的位置 gp_Pnt newPnt = gp::Origin().Transformed(pillarTransformation); //吸附距离 static auto alignDis = 200.0; //当前的吸附物体 auto alignODLs = activePilar->GetAlignList(); alignODLs.erase(std::remove_if(alignODLs.begin(), alignODLs.end(), [&pillarBox,&pillarTransformation](const BaseODLSPtr& alignODL) { if ( !alignODL ) { return true; } return alignODL->GetBaseBndBox().Distance(pillarBox.Transformed(alignODL->GetAbsoluteTransform().Inverted() * pillarTransformation)) > alignDis; }), alignODLs.end()); activePilar->SetAlignList(BaseODLList()); std::multimap<double,BaseODLSPtr> disMap; for ( auto& curODL : RootODL_.lock()->GetChildrenList() ) { if ( EODLT_PILLAR != curODL->GetType() && EODLT_WALL != curODL->GetType() ) { continue; } if ( std::find(alignODLs.begin(), alignODLs.end(), curODL) != alignODLs.end() ) { continue; } if ( EODLT_PILLAR == curODL->GetType() && curODL == activePilar ) { continue; } auto dis = curODL->GetBaseBndBox().Distance(pillarBox.Transformed(curODL->GetAbsoluteTransform().Inverted() * pillarTransformation)); if ( dis > alignDis ) { continue; } disMap.emplace(dis, curODL); } for ( auto& curODL : disMap ) { alignODLs.push_back(curODL.second); } for ( auto& curODL : alignODLs ) { auto alignTransformation = curODL->GetAbsoluteTransform(); //调整柱box的旋转 auto activeRotationPillarBox = pillarBox; { gp_Trsf tfsODL; tfsODL.SetRotation(alignTransformation.GetRotation()); activeRotationPillarBox = activeRotationPillarBox.Transformed(tfsODL.Inverted() * pillarRotation); } Bnd_Box movingBox,alignODLBox; { auto curBox = curODL->GetBaseBndBox(); Standard_Real xAlignMin,yAlignMin,zAlignMin,xAlignMax,yAlignMax,zAlignMax; curBox.Get(xAlignMin, yAlignMin, zAlignMin, xAlignMax, yAlignMax, zAlignMax); Standard_Real xPillarMin,yPillarMin,zPillarMin,xPillarMax,yPillarMax,zPillarMax; activeRotationPillarBox.Get(xPillarMin, yPillarMin, zPillarMin, xPillarMax, yPillarMax, zPillarMax); movingBox.Update(xAlignMin+xPillarMin, yAlignMin+yPillarMin, zAlignMin+zPillarMin, xAlignMax+xPillarMax, yAlignMax+yPillarMax, zAlignMax+zPillarMax); alignODLBox.Update(xAlignMin+xPillarMin-alignDis, yAlignMin+yPillarMin-alignDis, zAlignMin+zPillarMin-alignDis, xAlignMax+xPillarMax+alignDis, yAlignMax+yPillarMax+alignDis, zAlignMax+zPillarMax+alignDis); } auto inODLPnt = newPnt.Transformed(curODL->GetAbsoluteTransform().Inverted()); if ( Standard_True == alignODLBox.IsOut(inODLPnt) ) { continue; } //当前被停靠物体的box shape Standard_Real xMin,yMin,zMin,xMax,yMax,zMax; movingBox.Get(xMin, yMin, zMin, xMax, yMax, zMax); auto alignBoxShape = BRepPrimAPI_MakeBox(gp_Pnt(xMin, yMin, zMin), gp_Pnt(xMax, yMax, zMax)).Shape(); TopExp_Explorer exp(alignBoxShape, TopAbs_SHELL); BRepExtrema_DistShapeShape dss(imp_.ModifyEdge_.Edge().Moved(curODL->GetAbsoluteTransform().Inverted()), exp.Current()); auto needContinue = false; std::map<double, gp_Pnt> tmp; for ( auto index=1; index<=dss.NbSolution(); ++index ) { if ( dss.SupportTypeShape2(index) == BRepExtrema_IsOnEdge ) { activePilar->AddAlign(curODL); needContinue = true; break; } auto pntOnEdge = dss.PointOnShape1(index); auto pntOnBox = dss.PointOnShape2(index); if ( pntOnEdge.Distance(pntOnBox) > Precision::Confusion() ) { continue; } tmp.emplace(pntOnEdge.Distance(inODLPnt), pntOnEdge); } if ( needContinue ) { continue; } auto foundPnt = tmp.begin()->second.Transformed(curODL->GetAbsoluteTransform()); if ( foundPnt.Distance(newPnt) < 1) { activePilar->AddAlign(curODL); continue; } else { newPnt = foundPnt; break; } } auto finalOffset = gp_Vec(pillarTranslation.TranslationPart(), newPnt); auto finalRelationOffset = finalOffset.Transformed(pillarTransformation.Inverted()); auto finalModifyOffset = finalRelationOffset; { finalModifyOffset.SetX(finalModifyOffset.X()*modifyDir.X()); finalModifyOffset.SetY(finalModifyOffset.Y()*modifyDir.Y()); finalModifyOffset.SetZ(finalModifyOffset.Z()*modifyDir.Z()); } auto finalSize = pillarBoxSize + finalModifyOffset.XYZ(); auto finalTranslation = pillarTranslation.TranslationPart() + finalRelationOffset.XYZ()/2; activePilar->SetSize(finalSize); activePilar->SetTranslation(finalTranslation); { vector3df newPos(static_cast<float>(finalTranslation.X()), static_cast<float>(finalTranslation.Y()), static_cast<float>(finalTranslation.Z())); activePilar->GetDataSceneNode()->setPosition(newPos); } activePilar->Update2DMesh(); imp_.ModifyPar_ = curPar; } break; case EPilarState::EPS_MOUSEHOLDING: { auto activePillar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock()); activePillar->SetPicking(true); if ( imp_.SavePos_.getDistanceFromSQ(imp_.CurrentPos_) > 100 * 100 ) { imp_.State_ = EPilarState::EPS_MOVING; imp_.Valid_ = true; } else if ( imp_.LMouseLeftUp_ ) { imp_.PropertyCallBack_ = boost::none; imp_.State_ = EPilarState::EPS_PROPERTY; auto pointer = reinterpret_cast<int>(static_cast<void*>(&(*imp_.EventInfo_))); ::PostMessage((HWND)GetRenderContextSPtr()->GetHandle(), WM_IRR_DLG_MSG, WM_USER_ROOMLAYOUT_PILLAR_PROPERTY, pointer); } } break; case EPilarState::EPS_PROPERTY: { if ( !imp_.PropertyCallBack_ ) { break; } auto activePillar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock()); switch (*(imp_.PropertyCallBack_)) { case EUT_ROOMLAYOUT_PILLAR_NONE: { imp_.State_ = EPilarState::EPS_SWEEPING; } break; case EUT_ROOMLAYOUT_PILLAR_UPDATE: { activePillar->SetSize(imp_.EventInfo_->XLength_, imp_.EventInfo_->YLength_, imp_.EventInfo_->ZLength_); activePillar->SetOffsetHeight(imp_.EventInfo_->OffsetHeight_); { auto curTrans = activePillar->GetTranslation(); curTrans.SetY(imp_.EventInfo_->YLength_/2 + imp_.EventInfo_->OffsetHeight_); activePillar->SetTranslation(curTrans); auto curPos = activePillar->GetDataSceneNode()->getPosition(); curPos.Y = static_cast<float>(imp_.EventInfo_->YLength_/2 + imp_.EventInfo_->OffsetHeight_); activePillar->GetDataSceneNode()->setPosition(curPos); } activePillar->UpdateMesh(); imp_.State_ = EPilarState::EPS_SWEEPING; } break; case EUT_ROOMLAYOUT_PILLAR_MOVE: { imp_.State_ = EPilarState::EPS_MOVING; } break; case EUT_ROOMLAYOUT_PILLAR_DELETE: { activePillar->RemoveFromParent(); imp_.State_ = EPilarState::EPS_SWEEPING; } break; default: assert(0); break; } } break; case EPilarState::EPS_CREATING_INIT: { assert(imp_.EventInfo_); auto newPilar = PillarODL::Create<PillarODL>(GetRenderContextSPtr()); newPilar->SetSize(imp_.EventInfo_->XLength_, imp_.EventInfo_->YLength_, imp_.EventInfo_->ZLength_); newPilar->SetOffsetHeight(imp_.EventInfo_->OffsetHeight_); newPilar->UpdateMesh(); RootODL_.lock()->AddChild(newPilar); auto newPos = imp_.CurrentPos_; newPos.Y = imp_.EventInfo_->YLength_/2; newPilar->SetTranslation(gp_XYZ(newPos.X, newPos.Y, newPos.Z)); newPilar->GetDataSceneNode()->setPosition(newPos); SetPickingODL(newPilar); imp_.State_ = EPilarState::EPS_MOVING; } break; case EPilarState::EPS_MOVING: { auto activePilar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock()); activePilar->SetPicking(true); activePilar->SetVaildPosition(imp_.Valid_); if ( imp_.LMouseLeftUp_ ) { if ( imp_.Valid_ ) { ImpUPtr_->Valid_ = false; ImpUPtr_->EventInfo_ = boost::none; imp_.State_ = EPilarState::EPS_SWEEPING; break; } } if ( imp_.EscapePressDown_ ) { activePilar->RemoveFromParent(); imp_.State_ = EPilarState::EPS_SWEEPING; break; } //当前柱的Box auto activeTransitionBox = activePilar->GetBaseBndBox(); { gp_Trsf tfs; tfs.SetTranslationPart(activePilar->GetTranslation()); activeTransitionBox = activeTransitionBox.Transformed(tfs); } activePilar->SetRotation(gp_Quaternion(gp::DZ(), gp::DZ())); activePilar->GetDataSceneNode()->setRotation(vector3df(0)); auto size = activePilar->GetSize(); auto offset = activePilar->GetOffsetHeight(); //新的位置 auto newPos = imp_.CurrentPos_; newPos.Y = static_cast<float>(size.Y()/2) + offset; gp_Pnt newPnt(newPos.X, newPos.Y, newPos.Z); //吸附距离 static auto alignDis = 200.0; //当前的吸附物体 auto alignODLs = activePilar->GetAlignList(); alignODLs.erase(std::remove_if(alignODLs.begin(), alignODLs.end(), [&activePilar, &activeTransitionBox](const BaseODLSPtr& alignODL) { if ( !alignODL ) { return true; } return alignODL->GetBaseBndBox().Distance(activeTransitionBox.Transformed(alignODL->GetAbsoluteTransform().Inverted())) > alignDis; }), alignODLs.end()); activePilar->SetAlignList(BaseODLList()); std::multimap<double,BaseODLSPtr> disMap; for ( auto& curODL : RootODL_.lock()->GetChildrenList() ) { if ( EODLT_PILLAR != curODL->GetType() && EODLT_WALL != curODL->GetType() ) { continue; } if ( std::find(alignODLs.begin(), alignODLs.end(), curODL) != alignODLs.end() ) { continue; } if ( EODLT_PILLAR == curODL->GetType() && curODL == activePilar ) { continue; } auto dis = curODL->GetBaseBndBox().Distance(activeTransitionBox.Transformed(curODL->GetAbsoluteTransform().Inverted())); if ( dis > alignDis ) { continue; } disMap.emplace(dis, curODL); } for ( auto& curODL : disMap ) { alignODLs.push_back(curODL.second); } //锁定旋转 auto lockRotation = false; //锁定位置 auto lockPosition = false; //移动方向 TopoDS_Edge movingEdge; for ( auto& curODL : alignODLs ) { auto alignTransformation = curODL->GetAbsoluteTransform(); //如果锁定了旋转,则调整柱的box auto activeRotationPillarBox = activePilar->GetBaseBndBox(); if ( lockRotation ) { gp_Trsf tfsODL, tfsPillar; tfsODL.SetRotation(alignTransformation.GetRotation()); tfsPillar.SetRotation(activePilar->GetRotation()); activeRotationPillarBox = activeRotationPillarBox.Transformed(tfsODL.Inverted() * tfsPillar); } Bnd_Box movingBox; { auto curBox = curODL->GetBaseBndBox(); Standard_Real xAlignMin,yAlignMin,zAlignMin,xAlignMax,yAlignMax,zAlignMax; curBox.Get(xAlignMin, yAlignMin, zAlignMin, xAlignMax, yAlignMax, zAlignMax); Standard_Real xPillarMin,yPillarMin,zPillarMin,xPillarMax,yPillarMax,zPillarMax; activeRotationPillarBox.Get(xPillarMin, yPillarMin, zPillarMin, xPillarMax, yPillarMax, zPillarMax); movingBox.Update(xAlignMin+xPillarMin, yAlignMin+yPillarMin, zAlignMin+zPillarMin, xAlignMax+xPillarMax, yAlignMax+yPillarMax, zAlignMax+zPillarMax); } auto inODLPnt = newPnt.Transformed(curODL->GetAbsoluteTransform().Inverted()); //当位置锁定了以后,只需要判断是不是相交 if ( lockPosition ) { if ( Standard_True == movingBox.IsOut(inODLPnt) ) { continue; } Bnd_Box pntBox; pntBox.Add(inODLPnt); if ( pntBox.Distance(movingBox) < Precision::Confusion() ) { continue; } imp_.Valid_ = false; break; } Bnd_Box alignODLBox; { auto curBox = curODL->GetBaseBndBox(); Standard_Real xAlignMin,yAlignMin,zAlignMin,xAlignMax,yAlignMax,zAlignMax; curBox.Get(xAlignMin, yAlignMin, zAlignMin, xAlignMax, yAlignMax, zAlignMax); Standard_Real xPillarMin,yPillarMin,zPillarMin,xPillarMax,yPillarMax,zPillarMax; activeRotationPillarBox.Get(xPillarMin, yPillarMin, zPillarMin, xPillarMax, yPillarMax, zPillarMax); alignODLBox.Update(xAlignMin+xPillarMin-alignDis, yAlignMin+yPillarMin-alignDis, zAlignMin+zPillarMin-alignDis, xAlignMax+xPillarMax+alignDis, yAlignMax+yPillarMax+alignDis, zAlignMax+zPillarMax+alignDis); } if ( Standard_True == alignODLBox.IsOut(inODLPnt) ) { continue; } //当前被停靠物体的box shape Standard_Real xMin,yMin,zMin,xMax,yMax,zMax; movingBox.Get(xMin, yMin, zMin, xMax, yMax, zMax); auto alignBoxShape = BRepPrimAPI_MakeBox(gp_Pnt(xMin, yMin, zMin), gp_Pnt(xMax, yMax, zMax)).Shape(); TopExp_Explorer exp(alignBoxShape, TopAbs_SHELL); if ( !lockRotation ) {//找到第一个被停靠物体 BRepExtrema_DistShapeShape dss(BRepBuilderAPI_MakeVertex(inODLPnt).Shape(), exp.Current()); assert(0 != dss.NbSolution()); inODLPnt = dss.PointOnShape2(1); newPnt = inODLPnt.Transformed(curODL->GetAbsoluteTransform()).XYZ(); auto rot = curODL->GetAbsoluteTransform().GetRotation(); Standard_Real rX,rY,rZ; rot.GetEulerAngles(gp_Extrinsic_XYZ, rX, rY, rZ); vector3df rotation(static_cast<float>(irr::core::radToDeg(rX)), static_cast<float>(irr::core::radToDeg(rY)), static_cast<float>(irr::core::radToDeg(rZ))); activePilar->GetDataSceneNode()->setRotation(rotation); activePilar->SetRotation(rot); gp_Dir movingDir; if ( std::abs(std::abs(inODLPnt.X()) - xMax) < Precision::Confusion() ) { movingDir = gp::DZ(); } else { movingDir = gp::DX(); } auto curMovingEdge = BRepBuilderAPI_MakeEdge(gp_Lin(inODLPnt, movingDir)).Edge(); movingEdge = TopoDS::Edge(curMovingEdge.Moved(curODL->GetAbsoluteTransform())); activePilar->AddAlign(curODL); imp_.Valid_ = true; lockRotation = true; } else {//第二个被停靠物体 BRepExtrema_DistShapeShape dss(movingEdge.Moved(curODL->GetAbsoluteTransform().Inverted()), exp.Current()); auto foundSecond = false; std::map<double, gp_Pnt> tmp; for ( auto index=1; index<=dss.NbSolution(); ++index ) { auto pntOnEdge = dss.PointOnShape1(index); auto pntOnBox = dss.PointOnShape2(index); if ( pntOnEdge.Distance(pntOnBox) > Precision::Confusion() ) { continue; } tmp.emplace(pntOnEdge.Distance(inODLPnt), pntOnEdge); foundSecond = true; } if ( !foundSecond ) { imp_.Valid_ = false; break; } newPnt = tmp.begin()->second.Transformed(curODL->GetAbsoluteTransform()); activePilar->AddAlign(curODL); lockPosition = true; } } if ( activePilar->GetAlignList().empty() ) { imp_.Valid_ = true; } newPos.X = static_cast<float>(newPnt.X()); newPos.Y = static_cast<float>(newPnt.Y()); newPos.Z = static_cast<float>(newPnt.Z()); activePilar->GetDataSceneNode()->setPosition(newPos); activePilar->SetTranslation(newPnt.XYZ()); for ( auto& curAlign : activePilar->GetAlignList() ) { curAlign->SetSweeping(true); } } break; default: break; } imp_.LMousePressDown_ = false; imp_.LMouseLeftUp_ = false; imp_.EscapePressDown_ = false; return false; }
//======================================================================= //function : GlueEdgesWithPCurves //purpose : Glues the pcurves of the sequence of edges // and glues their 3d curves //======================================================================= static TopoDS_Edge GlueEdgesWithPCurves(const TopTools_SequenceOfShape& aChain, const TopoDS_Vertex& FirstVertex, const TopoDS_Vertex& LastVertex) { Standard_Integer i, j; TopoDS_Edge FirstEdge = TopoDS::Edge(aChain(1)); //TColGeom2d_SequenceOfCurve PCurveSeq; TColGeom_SequenceOfSurface SurfSeq; //TopTools_SequenceOfShape LocSeq; BRep_ListIteratorOfListOfCurveRepresentation itr( (Handle(BRep_TEdge)::DownCast(FirstEdge.TShape()))->Curves() ); for (; itr.More(); itr.Next()) { Handle(BRep_CurveRepresentation) CurveRep = itr.Value(); if (CurveRep->IsCurveOnSurface()) { //PCurveSeq.Append(CurveRep->PCurve()); SurfSeq.Append(CurveRep->Surface()); /* TopoDS_Shape aLocShape; aLocShape.Location(CurveRep->Location()); LocSeq.Append(aLocShape); */ } } Standard_Real fpar, lpar; BRep_Tool::Range(FirstEdge, fpar, lpar); TopoDS_Edge PrevEdge = FirstEdge; TopoDS_Vertex CV; Standard_Real MaxTol = 0.; TopoDS_Edge ResEdge; BRep_Builder BB; Standard_Integer nb_curve = aChain.Length(); //number of curves TColGeom_Array1OfBSplineCurve tab_c3d(0,nb_curve-1); //array of the curves TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2); //array of the tolerances TopoDS_Vertex PrevVertex = FirstVertex; for (i = 1; i <= nb_curve; i++) { TopoDS_Edge anEdge = TopoDS::Edge(aChain(i)); TopoDS_Vertex VF, VL; TopExp::Vertices(anEdge, VF, VL); Standard_Boolean ToReverse = (!VF.IsSame(PrevVertex)); Standard_Real Tol1 = BRep_Tool::Tolerance(VF); Standard_Real Tol2 = BRep_Tool::Tolerance(VL); if (Tol1 > MaxTol) MaxTol = Tol1; if (Tol2 > MaxTol) MaxTol = Tol2; if (i > 1) { TopExp::CommonVertex(PrevEdge, anEdge, CV); Standard_Real Tol = BRep_Tool::Tolerance(CV); tabtolvertex(i-2) = Tol; } Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar); Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(aCurve, fpar, lpar); tab_c3d(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve); GeomConvert::C0BSplineToC1BSplineCurve(tab_c3d(i-1), Precision::Confusion()); if (ToReverse) tab_c3d(i-1)->Reverse(); PrevVertex = (ToReverse)? VF : VL; PrevEdge = anEdge; } Handle(TColGeom_HArray1OfBSplineCurve) concatcurve; //array of the concatenated curves Handle(TColStd_HArray1OfInteger) ArrayOfIndices; //array of the remining Vertex GeomConvert::ConcatC1(tab_c3d, tabtolvertex, ArrayOfIndices, concatcurve, Standard_False, Precision::Confusion()); //C1 concatenation if (concatcurve->Length() > 1) { GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower())); for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++) Concat.Add( concatcurve->Value(i), MaxTol, Standard_True ); concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve()); } Handle(Geom_BSplineCurve) ResCurve = concatcurve->Value(concatcurve->Lower()); TColGeom2d_SequenceOfBoundedCurve ResPCurves; TopLoc_Location aLoc; for (j = 1; j <= SurfSeq.Length(); j++) { TColGeom2d_Array1OfBSplineCurve tab_c2d(0,nb_curve-1); //array of the pcurves PrevVertex = FirstVertex; PrevEdge = FirstEdge; //TopLoc_Location theLoc = LocSeq(j).Location(); for (i = 1; i <= nb_curve; i++) { TopoDS_Edge anEdge = TopoDS::Edge(aChain(i)); TopoDS_Vertex VF, VL; TopExp::Vertices(anEdge, VF, VL); Standard_Boolean ToReverse = (!VF.IsSame(PrevVertex)); /* Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, SurfSeq(j), anEdge.Location()*theLoc, fpar, lpar); */ Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, SurfSeq(j), aLoc, fpar, lpar); Handle(Geom2d_TrimmedCurve) aTrPCurve = new Geom2d_TrimmedCurve(aPCurve, fpar, lpar); tab_c2d(i-1) = Geom2dConvert::CurveToBSplineCurve(aTrPCurve); Geom2dConvert::C0BSplineToC1BSplineCurve(tab_c2d(i-1), Precision::Confusion()); if (ToReverse) tab_c2d(i-1)->Reverse(); PrevVertex = (ToReverse)? VF : VL; PrevEdge = anEdge; } Handle(TColGeom2d_HArray1OfBSplineCurve) concatc2d; //array of the concatenated curves Handle(TColStd_HArray1OfInteger) ArrayOfInd2d; //array of the remining Vertex Geom2dConvert::ConcatC1(tab_c2d, tabtolvertex, ArrayOfInd2d, concatc2d, Standard_False, Precision::Confusion()); //C1 concatenation if (concatc2d->Length() > 1) { Geom2dConvert_CompCurveToBSplineCurve Concat2d(concatc2d->Value(concatc2d->Lower())); for (i = concatc2d->Lower()+1; i <= concatc2d->Upper(); i++) Concat2d.Add( concatc2d->Value(i), MaxTol, Standard_True ); concatc2d->SetValue(concatc2d->Lower(), Concat2d.BSplineCurve()); } Handle(Geom2d_BSplineCurve) aResPCurve = concatc2d->Value(concatc2d->Lower()); ResPCurves.Append(aResPCurve); } ResEdge = BRepLib_MakeEdge(ResCurve, FirstVertex, LastVertex, ResCurve->FirstParameter(), ResCurve->LastParameter()); BB.SameRange(ResEdge, Standard_False); BB.SameParameter(ResEdge, Standard_False); for (j = 1; j <= ResPCurves.Length(); j++) { BB.UpdateEdge(ResEdge, ResPCurves(j), SurfSeq(j), aLoc, MaxTol); BB.Range(ResEdge, SurfSeq(j), aLoc, ResPCurves(j)->FirstParameter(), ResPCurves(j)->LastParameter()); } BRepLib::SameParameter(ResEdge, MaxTol, Standard_True); return ResEdge; }
//---------------------------------------------------------------- // Function: TopoDS_Shape level function to update the core Surface // for any movement or Boolean operation of the body. // Author: Jane Hu //---------------------------------------------------------------- CubitStatus OCCSurface::update_OCC_entity(TopoDS_Face& old_surface, TopoDS_Shape& new_surface, BRepBuilderAPI_MakeShape *op, TopoDS_Vertex* removed_vertex, LocOpe_SplitShape* sp) { //set the Wires TopTools_IndexedMapOfShape M, M2; TopoDS_Shape shape, shape2, shape_edge, shape_vertex; TopExp::MapShapes(old_surface, TopAbs_WIRE, M); TopTools_ListOfShape shapes; BRepFilletAPI_MakeFillet2d* test_op = NULL; for (int ii=1; ii<=M.Extent(); ii++) { TopoDS_Wire wire = TopoDS::Wire(M(ii)); TopTools_ListOfShape shapes; if(op) { test_op = dynamic_cast<BRepFilletAPI_MakeFillet2d*>(op); if(!test_op) shapes.Assign(op->Modified(wire)); if(shapes.Extent() == 0) shapes.Assign(op->Generated(wire)); if(!new_surface.IsNull()) TopExp::MapShapes(new_surface,TopAbs_WIRE, M2); } else if(sp) shapes.Assign(sp->DescendantShapes(wire)); if (shapes.Extent() == 1) { shape = shapes.First(); if(M2.Extent() == 1) { shape2 = TopoDS::Wire(M2(1)); if(!shape.IsSame(shape2)) shape = shape2; } else if(M2.Extent() > 1) shape.Nullify(); } else if(shapes.Extent() > 1) shape.Nullify(); else if(op->IsDeleted(wire) || shapes.Extent() == 0) { TopTools_IndexedMapOfShape M_new; TopExp::MapShapes(new_surface, TopAbs_WIRE, M_new); if (M_new.Extent()== 1) shape = M_new(1); else shape.Nullify(); } else { shape = wire; continue; } //set curves BRepTools_WireExplorer Ex; for(Ex.Init(wire); Ex.More();Ex.Next()) { TopoDS_Edge edge = Ex.Current(); if(op && !test_op) { shapes.Assign(op->Modified(edge)); if(shapes.Extent() == 0) shapes.Assign(op->Generated(edge)); } else if(sp) shapes.Assign(sp->DescendantShapes(edge)); if (shapes.Extent() == 1) { //in fillet creating mothod, one edge could generated a face, so check //it here. TopAbs_ShapeEnum type = shapes.First().TShape()->ShapeType(); if(type != TopAbs_EDGE) shape_edge.Nullify(); else shape_edge = shapes.First(); } else if (shapes.Extent() > 1) { //update all attributes first. TopTools_ListIteratorOfListOfShape it; it.Initialize(shapes); for(; it.More(); it.Next()) { shape_edge = it.Value(); OCCQueryEngine::instance()->copy_attributes(edge, shape_edge); } shape_edge.Nullify(); } else if (op->IsDeleted(edge)) shape_edge.Nullify(); else if (test_op) { if(!test_op->IsModified(edge)) shape_edge = edge; else shape_edge = (test_op->Modified(edge)).First(); } else shape_edge = edge; //update vertex TopoDS_Vertex vertex = Ex.CurrentVertex(); shapes.Clear(); if(test_op) assert(removed_vertex != NULL); if(op && ! test_op ) shapes.Assign(op->Modified(vertex)); else if(sp) shapes.Assign(sp->DescendantShapes(vertex)); if (shapes.Extent() == 1) shape_vertex = shapes.First(); else if(shapes.Extent() > 1) { //update all attributes first. TopTools_ListIteratorOfListOfShape it; it.Initialize(shapes); for(; it.More(); it.Next()) { shape_vertex = it.Value(); OCCQueryEngine::instance()->copy_attributes(vertex, shape_vertex); } shape_vertex.Nullify() ; } else if(op->IsDeleted(vertex) || (test_op && vertex.IsSame( *removed_vertex))) shape_vertex.Nullify() ; else shape_vertex = vertex; if(!vertex.IsSame(shape_vertex) ) OCCQueryEngine::instance()->update_OCC_map(vertex, shape_vertex); if (!edge.IsSame(shape_edge)) OCCQueryEngine::instance()->update_OCC_map(edge, shape_edge); } if (!wire.IsSame(shape)) OCCQueryEngine::instance()->update_OCC_map(wire, shape); } double dTOL = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); if (!old_surface.IsSame(new_surface)) { TopAbs_ShapeEnum shapetype = TopAbs_SHAPE; if(!new_surface.IsNull()) shapetype = new_surface.TShape()->ShapeType(); if(shapetype == TopAbs_FACE || new_surface.IsNull()) OCCQueryEngine::instance()->update_OCC_map(old_surface, new_surface); else { TopTools_IndexedMapOfShape M; TopExp::MapShapes(new_surface, TopAbs_FACE, M); TopoDS_Shape new_shape; if(M.Extent() == 1) new_shape = M(1); else if(M.Extent() > 1) { for(int i = 1; i <= M.Extent(); i++) { GProp_GProps myProps; BRepGProp::SurfaceProperties(old_surface, myProps); double orig_mass = myProps.Mass(); gp_Pnt orig_pnt = myProps.CentreOfMass(); BRepGProp::SurfaceProperties(M(i), myProps); double after_mass = myProps.Mass(); gp_Pnt after_pnt = myProps.CentreOfMass(); if(fabs(-after_mass + orig_mass) <= dTOL && orig_pnt.IsEqual(after_pnt, dTOL)) { new_shape = M(i); break; } } } OCCQueryEngine::instance()->update_OCC_map(old_surface, new_shape); } } return CUBIT_SUCCESS; }
bool Edgecluster::PerformEdges(gp_Pnt& point) { tMapPntEdge::iterator iter = m_vertices.find(point); if ( iter == m_vertices.end() ) return false; tEdgeVector& edges = iter->second; tEdgeVector::iterator edgeIt = edges.begin(); //no more edges. pb if ( edgeIt == edges.end() ) { //Delete also the current vertex m_vertices.erase(iter); return false; } TopoDS_Edge theEdge = *edgeIt; //we are storing the edge, so remove it from the vertex association edges.erase(edgeIt); //if no more edges, remove the vertex if ( edges.empty() ) m_vertices.erase(iter); TopoDS_Vertex V1,V2; TopExp::Vertices(theEdge,V1,V2); gp_Pnt P1 = BRep_Tool::Pnt(V1); gp_Pnt P2 = BRep_Tool::Pnt(V2); if ( theEdge.Orientation() == TopAbs_REVERSED ) { //switch the points gp_Pnt tmpP = P1; P1 = P2; P2 = tmpP; } gp_Pnt nextPoint; if ( P2.IsEqual(point,0.2) ) { //need to reverse the edge theEdge.Reverse(); nextPoint = P1; } else { nextPoint = P2; } //need to erase the edge from the second point iter = m_vertices.find(nextPoint); if ( iter != m_vertices.end() ) { tEdgeVector& nextEdges = iter->second; for ( edgeIt = nextEdges.begin() ; edgeIt != nextEdges.end(); ++edgeIt ) { if ( theEdge.IsSame(*edgeIt) ) { nextEdges.erase(edgeIt); break; } } } //put the edge at the end of the list m_edges.push_back(theEdge); //Update the point for the next do-while loop point = nextPoint; return true; }
//======================================================================= //function : Execute //purpose : //======================================================================= Standard_Integer GEOMImpl_MeasureDriver::Execute(TFunction_Logbook& log) const { if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); GEOMImpl_IMeasure aCI (aFunction); Standard_Integer aType = aFunction->GetType(); TopoDS_Shape aShape; if (aType == CDG_MEASURE) { Handle(GEOM_Function) aRefBase = aCI.GetBase(); TopoDS_Shape aShapeBase = aRefBase->GetValue(); if (aShapeBase.IsNull()) { Standard_NullObject::Raise("Shape for centre of mass calculation is null"); } gp_Ax3 aPos = GEOMImpl_IMeasureOperations::GetPosition(aShapeBase); gp_Pnt aCenterMass = aPos.Location(); aShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape(); } else if (aType == VERTEX_BY_INDEX) { Handle(GEOM_Function) aRefBase = aCI.GetBase(); TopoDS_Shape aShapeBase = aRefBase->GetValue(); if (aShapeBase.IsNull()) { Standard_NullObject::Raise("Shape for centre of mass calculation is null"); } int index = aCI.GetIndex(); gp_Pnt aVertex; if (aShapeBase.ShapeType() == TopAbs_VERTEX) { if ( index != 1 ) Standard_NullObject::Raise("Vertex index is out of range"); else aVertex = BRep_Tool::Pnt(TopoDS::Vertex(aShapeBase)); } else if (aShapeBase.ShapeType() == TopAbs_EDGE) { TopoDS_Vertex aV1, aV2; TopoDS_Edge anEdgeE = TopoDS::Edge(aShapeBase); TopExp::Vertices(anEdgeE, aV1, aV2); gp_Pnt aP1 = BRep_Tool::Pnt(aV1); gp_Pnt aP2 = BRep_Tool::Pnt(aV2); if (index < 0 || index > 1) Standard_NullObject::Raise("Vertex index is out of range"); if ( ( anEdgeE.Orientation() == TopAbs_FORWARD && index == 0 ) || ( anEdgeE.Orientation() == TopAbs_REVERSED && index == 1 ) ) aVertex = aP1; else aVertex = aP2; } else if (aShapeBase.ShapeType() == TopAbs_WIRE) { TopTools_IndexedMapOfShape anEdgeShapes; TopTools_IndexedMapOfShape aVertexShapes; TopoDS_Vertex aV1, aV2; TopoDS_Wire aWire = TopoDS::Wire(aShapeBase); TopExp_Explorer exp (aWire, TopAbs_EDGE); for (; exp.More(); exp.Next()) { anEdgeShapes.Add(exp.Current()); TopoDS_Edge E = TopoDS::Edge(exp.Current()); TopExp::Vertices(E, aV1, aV2); if ( aVertexShapes.Extent() == 0) aVertexShapes.Add(aV1); if ( !aV1.IsSame( aVertexShapes(aVertexShapes.Extent()) ) ) aVertexShapes.Add(aV1); if ( !aV2.IsSame( aVertexShapes(aVertexShapes.Extent()) ) ) aVertexShapes.Add(aV2); } if (index < 0 || index > aVertexShapes.Extent()) Standard_NullObject::Raise("Vertex index is out of range"); if (aWire.Orientation() == TopAbs_FORWARD) aVertex = BRep_Tool::Pnt(TopoDS::Vertex(aVertexShapes(index+1))); else aVertex = BRep_Tool::Pnt(TopoDS::Vertex(aVertexShapes(aVertexShapes.Extent() - index))); } else { Standard_NullObject::Raise("Shape for vertex calculation is not an edge or wire"); } aShape = BRepBuilderAPI_MakeVertex(aVertex).Shape(); } else if (aType == VECTOR_FACE_NORMALE) { // Face Handle(GEOM_Function) aRefBase = aCI.GetBase(); TopoDS_Shape aShapeBase = aRefBase->GetValue(); if (aShapeBase.IsNull()) { Standard_NullObject::Raise("Face for normale calculation is null"); } if (aShapeBase.ShapeType() != TopAbs_FACE) { Standard_NullObject::Raise("Shape for normale calculation is not a face"); } TopoDS_Face aFace = TopoDS::Face(aShapeBase); // Point gp_Pnt p1 (0,0,0); Handle(GEOM_Function) aPntFunc = aCI.GetPoint(); if (!aPntFunc.IsNull()) { TopoDS_Shape anOptPnt = aPntFunc->GetValue(); if (anOptPnt.IsNull()) Standard_NullObject::Raise("Invalid shape given for point argument"); p1 = BRep_Tool::Pnt(TopoDS::Vertex(anOptPnt)); } else { gp_Ax3 aPos = GEOMImpl_IMeasureOperations::GetPosition(aFace); p1 = aPos.Location(); } // Point parameters on surface Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace); Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf); gp_Pnt2d pUV = aSurfAna->ValueOfUV(p1, Precision::Confusion()); // Normal direction gp_Vec Vec1,Vec2; BRepAdaptor_Surface SF (aFace); SF.D1(pUV.X(), pUV.Y(), p1, Vec1, Vec2); if (Vec1.Magnitude() < Precision::Confusion()) { gp_Vec tmpV; gp_Pnt tmpP; SF.D1(pUV.X(), pUV.Y()-0.1, tmpP, Vec1, tmpV); } else if (Vec2.Magnitude() < Precision::Confusion()) { gp_Vec tmpV; gp_Pnt tmpP; SF.D1(pUV.X()-0.1, pUV.Y(), tmpP, tmpV, Vec2); } gp_Vec V = Vec1.Crossed(Vec2); Standard_Real mod = V.Magnitude(); if (mod < Precision::Confusion()) Standard_NullObject::Raise("Normal vector of a face has null magnitude"); // Set length of normal vector to average radius of curvature Standard_Real radius = 0.0; GeomLProp_SLProps aProperties (aSurf, pUV.X(), pUV.Y(), 2, Precision::Confusion()); if (aProperties.IsCurvatureDefined()) { Standard_Real radius1 = Abs(aProperties.MinCurvature()); Standard_Real radius2 = Abs(aProperties.MaxCurvature()); if (Abs(radius1) > Precision::Confusion()) { radius = 1.0 / radius1; if (Abs(radius2) > Precision::Confusion()) { radius = (radius + 1.0 / radius2) / 2.0; } } else { if (Abs(radius2) > Precision::Confusion()) { radius = 1.0 / radius2; } } } // Set length of normal vector to average dimension of the face // (only if average radius of curvature is not appropriate) if (radius < Precision::Confusion()) { Bnd_Box B; Standard_Real Xmin, Xmax, Ymin, Ymax, Zmin, Zmax; BRepBndLib::Add(aFace, B); B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax); radius = ((Xmax - Xmin) + (Ymax - Ymin) + (Zmax - Zmin)) / 3.0; } if (radius < Precision::Confusion()) radius = 1.0; V *= radius / mod; // consider the face orientation if (aFace.Orientation() == TopAbs_REVERSED || aFace.Orientation() == TopAbs_INTERNAL) { V = - V; } // Edge gp_Pnt p2 = p1.Translated(V); BRepBuilderAPI_MakeEdge aBuilder (p1, p2); if (!aBuilder.IsDone()) Standard_NullObject::Raise("Vector construction failed"); aShape = aBuilder.Shape(); } else { } if (aShape.IsNull()) return 0; aFunction->SetValue(aShape); log.SetTouched(Label()); return 1; }
//======================================================================= //function : SelectEdge //purpose : Find the edge <NE> connected <CE> by the vertex <CV> in the list <LE>. // <NE> Is erased of the list. If <CE> is too in the list <LE> // with the same orientation, it's erased of the list //======================================================================= static Standard_Boolean SelectEdge(const TopoDS_Face& F, const TopoDS_Edge& CE, const TopoDS_Vertex& CV, TopoDS_Edge& NE, TopTools_ListOfShape& LE) { TopTools_ListIteratorOfListOfShape itl; NE.Nullify(); for ( itl.Initialize(LE); itl.More(); itl.Next()) { if (itl.Value().IsEqual(CE)) { LE.Remove(itl); break; } } if (LE.Extent() > 1) { //-------------------------------------------------------------- // Several possible edges. // - Test the edges differents of CE //-------------------------------------------------------------- Standard_Real cf, cl, f, l; TopoDS_Face FForward = F; Handle(Geom2d_Curve) Cc, C; FForward.Orientation(TopAbs_FORWARD); Cc = BRep_Tool::CurveOnSurface(CE,FForward,cf,cl); Standard_Real dist,distmin = 100*BRep_Tool::Tolerance(CV); Standard_Real uc,u; if (CE.Orientation () == TopAbs_FORWARD) uc = cl; else uc = cf; gp_Pnt2d P2,PV = Cc->Value(uc); Standard_Real delta = FindDelta(LE,FForward); for ( itl.Initialize(LE); itl.More(); itl.Next()) { const TopoDS_Edge& E = TopoDS::Edge(itl.Value()); if (!E.IsSame(CE)) { C = BRep_Tool::CurveOnSurface(E,FForward,f,l); if (E.Orientation () == TopAbs_FORWARD) u = f; else u = l; P2 = C->Value(u); dist = PV.Distance(P2); if (dist <= distmin){ distmin = dist; } } } Standard_Real anglemax = - PI; TopoDS_Edge SelectedEdge; for ( itl.Initialize(LE); itl.More(); itl.Next()) { const TopoDS_Edge& E = TopoDS::Edge(itl.Value()); if (!E.IsSame(CE)) { C = BRep_Tool::CurveOnSurface(E,FForward,f,l); if (E.Orientation () == TopAbs_FORWARD) u = f; else u = l; P2 = C->Value(u); dist = PV.Distance(P2); if (dist <= distmin + (1./3)*delta){ gp_Pnt2d PC, P; gp_Vec2d CTg1, CTg2, Tg1, Tg2; Cc->D2(uc, PC, CTg1, CTg2); C->D2(u, P, Tg1, Tg2); Standard_Real angle; if (CE.Orientation () == TopAbs_REVERSED && E.Orientation () == TopAbs_FORWARD) { angle = CTg1.Angle(Tg1.Reversed()); } else if (CE.Orientation () == TopAbs_FORWARD && E.Orientation () == TopAbs_REVERSED) { angle = (CTg1.Reversed()).Angle(Tg1); } else if (CE.Orientation () == TopAbs_REVERSED && E.Orientation () == TopAbs_REVERSED) { angle = CTg1.Angle(Tg1); } else if (CE.Orientation () == TopAbs_FORWARD && E.Orientation () == TopAbs_FORWARD) { angle = (CTg1.Reversed()).Angle(Tg1.Reversed()); } if (angle >= anglemax) { anglemax = angle ; SelectedEdge = E; } } } } for ( itl.Initialize(LE); itl.More(); itl.Next()) { const TopoDS_Edge& E = TopoDS::Edge(itl.Value()); if (E.IsEqual(SelectedEdge)) { NE = TopoDS::Edge(E); LE.Remove(itl); break; } } } else if (LE.Extent() == 1) { NE = TopoDS::Edge(LE.First()); LE.RemoveFirst(); } else { return Standard_False; } return Standard_True; }
const std::list<gp_Trsf> PolarPattern::getTransformations(const std::vector<App::DocumentObject*>) { float angle = Angle.getValue(); if (angle < Precision::Confusion()) throw Base::Exception("Pattern angle too small"); int occurrences = Occurrences.getValue(); if (occurrences < 2) throw Base::Exception("At least two occurrences required"); bool reversed = Reversed.getValue(); double offset; if (std::abs(angle - 360.0) < Precision::Confusion()) offset = Base::toRadians<double>(angle) / occurrences; // Because e.g. two occurrences in 360 degrees need to be 180 degrees apart else offset = Base::toRadians<double>(angle) / (occurrences - 1); App::DocumentObject* refObject = Axis.getValue(); if (refObject == NULL) throw Base::Exception("No axis reference specified"); if (!refObject->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) throw Base::Exception("Axis reference must be edge of a feature"); std::vector<std::string> subStrings = Axis.getSubValues(); if (subStrings.empty() || subStrings[0].empty()) throw Base::Exception("No axis reference specified"); gp_Pnt axbase; gp_Dir axdir; 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(); axbase = gp_Pnt(axis.getBase().x, axis.getBase().y, axis.getBase().z); axdir = gp_Dir(axis.getDirection().x, axis.getDirection().y, axis.getDirection().z); } else { 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_EDGE) { TopoDS_Edge refEdge = TopoDS::Edge(ref); if (refEdge.IsNull()) throw Base::Exception("Failed to extract axis edge"); BRepAdaptor_Curve adapt(refEdge); if (adapt.GetType() != GeomAbs_Line) throw Base::Exception("Axis edge must be a straight line"); axbase = adapt.Value(adapt.FirstParameter()); axdir = adapt.Line().Direction(); } else { throw Base::Exception("Axis reference must be an edge"); } } TopLoc_Location invObjLoc = this->getLocation().Inverted(); axbase.Transform(invObjLoc.Transformation()); axdir.Transform(invObjLoc.Transformation()); gp_Ax2 axis(axbase, axdir); if (reversed) axis.SetDirection(axis.Direction().Reversed()); // 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.SetRotation(axis.Axis(), i * offset); transformations.push_back(trans); } return transformations; }
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; }
void Tesselate_Presentation::tesselateShape(const TopoDS_Shape& aShape) { // setResultTitle("Tesselate shape"); TCollection_AsciiString aText = ( "/////////////////////////////////////////////////////////////////" EOL "// Tesselate shape." EOL "/////////////////////////////////////////////////////////////////" EOL EOL ) ; Standard_Real aDeflection = DATA[myIndex][0]; Standard_Integer aNumOfFace = (Standard_Integer)DATA[myIndex][1]; Standard_Integer aNumOfEdge = (Standard_Integer)DATA[myIndex][2]; aText += "Standard_Real aDeflection;" EOL "// aDeflection = ... ;" EOL EOL "// removes all the triangulations of the faces ," EOL "//and all the polygons on the triangulations of the edges:" EOL "BRepTools::Clean(aShape);" EOL EOL "// adds a triangulation of the shape aShape with the deflection aDeflection:" EOL "BRepMesh::Mesh(aShape,aDeflection);" EOL EOL "TopExp_Explorer aExpFace,aExpEdge;" EOL "for(aExpFace.Init(aShape,TopAbs_FACE);aExpFace.More();aExpFace.Next())" EOL "{ " EOL " TopoDS_Face aFace = TopoDS::Face(aExpFace.Current());" EOL " TopLoc_Location aLocation;" EOL EOL " // takes the triangulation of the face aFace:" EOL " Handle_Poly_Triangulation aTr = BRep_Tool::Triangulation(aFace,aLocation);" EOL EOL " if(!aTr.IsNull()) // if this triangulation is not NULL" EOL " { " EOL " // takes the array of nodes for this triangulation:" EOL " const TColgp_Array1OfPnt& aNodes = aTr->Nodes();" EOL " // takes the array of triangles for this triangulation:" EOL " const Poly_Array1OfTriangle& triangles = aTr->Triangles();" EOL EOL " // create array of node points in absolute coordinate system" EOL " TColgp_Array1OfPnt aPoints(1, aNodes.Length());" EOL " for( Standard_Integer i = 1; i < aNodes.Length()+1; i++)" EOL " aPoints(i) = aNodes(i).Transformed(aLocation);" EOL EOL " // Takes the node points of each triangle of this triangulation." EOL " // takes a number of triangles:" EOL " Standard_Integer nnn = aTr->NbTriangles();" EOL " Standard_Integer nt,n1,n2,n3;" EOL " for( nt = 1 ; nt < nnn+1 ; nt++)" EOL " {" EOL " // takes the node indices of each triangle in n1,n2,n3:" EOL " triangles(nt).Get(n1,n2,n3);" EOL " // takes the node points:" EOL " gp_Pnt aPnt1 = aPoints(n1);" EOL " gp_Pnt aPnt2 = aPoints(n2);" EOL " gp_Pnt aPnt3 = aPoints(n3);" EOL " } " EOL EOL " // Takes the polygon associated to an edge." EOL " aExpEdge.Init(aFace,TopAbs_EDGE);" EOL " TopoDS_Edge aEdge;" EOL " // for example,working with the first edge:" EOL " if(aExpEdge.More())" EOL " aEdge = TopoDS::Edge(aExpEdge.Current());" EOL EOL " if(!aEdge.IsNull()) // if this edge is not NULL" EOL " {" EOL " // takes the polygon associated to the edge aEdge:" EOL " Handle_Poly_PolygonOnTriangulation aPol = " EOL " BRep_Tool::PolygonOnTriangulation(aEdge,aTr,aEdge.Location());" EOL EOL " if(!aPol.IsNull()) // if this polygon is not NULL" EOL " // takes the array of nodes for this polygon" EOL " // (indexes in the array of nodes for triangulation of theFace):" EOL " const TColStd_Array1OfInteger& aNodesOfPol = aPol->Nodes();" EOL " }" EOL " }" EOL "}" EOL EOL "//==================================================" EOL EOL ; aText += " Result with deflection = "; aText += TCollection_AsciiString(aDeflection); aText += " :" EOL; GetDocument()->PocessTextInDialog("Compute the triangulation on a shape", aText); // setResultText(aText.ToCString()); //========================================================================== BRepTools::Clean(aShape); BRepMesh::Mesh(aShape,aDeflection); BRep_Builder aBuilder,aBuild1,aBuild2; TopoDS_Compound aCompound,aComp1,aComp2; aBuilder.MakeCompound(aCompound); aBuild1.MakeCompound(aComp1); aBuild2.MakeCompound(aComp2); TopTools_SequenceOfShape aVertices; Standard_Integer aCount = 0; Standard_Integer aNumOfNodes = 0; Standard_Integer aNumOfTriangles = 0; Handle_AIS_InteractiveObject aShowEdge,aShowFace,aShowShape; TopExp_Explorer aExpFace,aExpEdge; for(aExpFace.Init(aShape,TopAbs_FACE);aExpFace.More();aExpFace.Next()) { aCount++; TopoDS_Face aFace = TopoDS::Face(aExpFace.Current()); TopLoc_Location aLocation; Handle_Poly_Triangulation aTr = BRep_Tool::Triangulation(aFace,aLocation); if(!aTr.IsNull()) { const TColgp_Array1OfPnt& aNodes = aTr->Nodes(); aNumOfNodes += aTr->NbNodes(); Standard_Integer aLower = aNodes.Lower(); Standard_Integer anUpper = aNodes.Upper(); const Poly_Array1OfTriangle& triangles = aTr->Triangles(); aNumOfTriangles += aTr->NbTriangles(); if(aCount == aNumOfFace) { Standard_Integer aNbOfNodesOfFace = aTr->NbNodes(); Standard_Integer aNbOfTrianglesOfFace = aTr->NbTriangles(); aExpEdge.Init(aFace,TopAbs_EDGE); TopoDS_Edge aEdge; for( Standard_Integer i = 0; aExpEdge.More() && i < aNumOfEdge ; aExpEdge.Next(), i++) aEdge = TopoDS::Edge(aExpEdge.Current()); if(!aEdge.IsNull()) { Handle_Poly_PolygonOnTriangulation aPol = BRep_Tool::PolygonOnTriangulation(aEdge,aTr,aEdge.Location()); if(!aPol.IsNull()) { const TColStd_Array1OfInteger& aNodesOfPol = aPol->Nodes(); Standard_Integer aNbOfNodesOfEdge = aPol->NbNodes(); aText += "Number of nodes of the edge = "; aText += TCollection_AsciiString(aNbOfNodesOfEdge) + EOL; aText += "Number of nodes of the face = "; aText += TCollection_AsciiString(aNbOfNodesOfFace) + EOL; aText += "Number of triangles of the face = "; aText += TCollection_AsciiString(aNbOfTrianglesOfFace) + EOL; GetDocument()->PocessTextInDialog("Compute the triangulation on a shape", aText); // setResultText(aText.ToCString()); Standard_Integer aLower = aNodesOfPol.Lower(), anUpper = aNodesOfPol.Upper(); for( int i = aLower; i < anUpper ; i++) { gp_Pnt aPnt1 = aNodes(aNodesOfPol(i)).Transformed(aLocation); gp_Pnt aPnt2 = aNodes(aNodesOfPol(i+1)).Transformed(aLocation); TopoDS_Vertex aVertex1 = BRepBuilderAPI_MakeVertex (aPnt1); TopoDS_Vertex aVertex2 = BRepBuilderAPI_MakeVertex (aPnt2); if(!aVertex1.IsNull() && !aVertex2.IsNull() && // if vertices are "alive" !BRep_Tool::Pnt(aVertex1).IsEqual( BRep_Tool::Pnt(aVertex2),Precision::Confusion())) // if they are different { aEdge = BRepBuilderAPI_MakeEdge (aVertex1,aVertex2); aBuild2.Add(aComp2,aVertex1); if(!aEdge.IsNull()) aBuild2.Add(aComp2,aEdge); if(i == anUpper-1) aBuild2.Add(aComp2,aVertex2); } } getAISContext()->EraseAll(); aShowShape = drawShape(aShape); if(WAIT_A_SECOND) return; aShowEdge = drawShape(aComp2,Quantity_NOC_GREEN); getAISContext()->Erase(aShowShape); if(WAIT_A_SECOND) return; } } } TopTools_DataMapOfIntegerShape aEdges; TopTools_SequenceOfShape aVertices; for( Standard_Integer i = 1; i < aNodes.Length()+1; i++) { gp_Pnt aPnt = aNodes(i).Transformed(aLocation); TopoDS_Vertex aVertex = BRepBuilderAPI_MakeVertex(aPnt); if(!aVertex.IsNull()) { aBuilder.Add(aCompound,aVertex); if(aCount == aNumOfFace ) aBuild1.Add(aComp1,aVertex); aVertices.Append(aVertex); } } Standard_Integer nnn = aTr->NbTriangles(); Standard_Integer nt,n1,n2,n3; for( nt = 1 ; nt < nnn+1 ; nt++) { triangles(nt).Get(n1,n2,n3); Standard_Integer key[3]; TopoDS_Vertex aV1,aV2; key[0] = _key(n1, n2); if(!aEdges.IsBound(key[0])) { aV1 = TopoDS::Vertex(aVertices(n1)); aV2 = TopoDS::Vertex(aVertices(n2)); if(!aV1.IsNull() && !aV2.IsNull() && !BRep_Tool::Pnt(aV1).IsEqual(BRep_Tool::Pnt(aV2),Precision::Confusion())) { TopoDS_Edge aEdge = BRepBuilderAPI_MakeEdge (aV1,aV2); if(!aEdge.IsNull()) { aEdges.Bind(key[0], aEdge); aBuilder.Add(aCompound,aEdges(key[0])); if(aCount == aNumOfFace) aBuild1.Add(aComp1,aEdges(key[0])); } } } key[1] = _key(n2,n3); if(!aEdges.IsBound(key[1])) { aV1 = TopoDS::Vertex(aVertices(n2)); aV2 = TopoDS::Vertex(aVertices(n3)); if(!aV1.IsNull() && !aV2.IsNull() && !BRep_Tool::Pnt(aV1).IsEqual(BRep_Tool::Pnt(aV2),Precision::Confusion())) { TopoDS_Edge aEdge = BRepBuilderAPI_MakeEdge (aV1,aV2); if(!aEdge.IsNull()) { aEdges.Bind(key[1],aEdge); aBuilder.Add(aCompound,aEdges(key[1])); if(aCount == aNumOfFace) aBuild1.Add(aComp1,aEdges(key[1])); } } } key[2] = _key(n3,n1); if(!aEdges.IsBound(key[2])) { aV1 = TopoDS::Vertex(aVertices(n3)); aV2 = TopoDS::Vertex(aVertices(n1)); if(!aV1.IsNull() && !aV2.IsNull() && !BRep_Tool::Pnt(aV1).IsEqual(BRep_Tool::Pnt(aV2),Precision::Confusion())) { TopoDS_Edge aEdge = BRepBuilderAPI_MakeEdge (aV1,aV2); if(!aEdge.IsNull()) { aEdges.Bind(key[2],aEdge); aBuilder.Add(aCompound,aEdges(key[2])); if(aCount == aNumOfFace) aBuild1.Add(aComp1,aEdges(key[2])); } } } } if(aCount == aNumOfFace) { aShowFace = drawShape(aComp1,Quantity_NOC_GREEN); getAISContext()->Erase(aShowEdge); } } else { aText += "Can't compute a triangulation on face "; aText += TCollection_AsciiString(aCount) + EOL; GetDocument()->PocessTextInDialog("Compute the triangulation on a shape", aText); // setResultText(aText.ToCString()); } } aText += "Number of nodes of the shape = "; aText += TCollection_AsciiString(aNumOfNodes) + EOL; aText += "Number of triangles of the shape = "; aText += TCollection_AsciiString(aNumOfTriangles) + EOL EOL; GetDocument()->PocessTextInDialog("Compute the triangulation on a shape", aText); // setResultText(aText.ToCString()); if(WAIT_A_SECOND) return; drawShape(aCompound,Quantity_NOC_GREEN); getAISContext()->Erase(aShowFace); }
//======================================================================= //function : GetApproxNormalToFaceOnEdge //purpose : //======================================================================= void GetApproxNormalToFaceOnEdge (const TopoDS_Edge& aEx, const TopoDS_Face& aFx, Standard_Real aT, gp_Pnt& aPF, gp_Dir& aDNF, IntTools_Context& aCtx) { Standard_Boolean bReverse; Standard_Real aT1, aT2, dT, aU, aV; gp_Dir aDTT, aDNFT, aDBT; gp_Pnt aPFT, aPFx; Handle(Geom_Curve) aC3D; Handle(Geom_Surface) aS; GeomAdaptor_Surface aGAS; GeomAbs_SurfaceType aTS; TopoDS_Face aF; TopoDS_Edge aE; // bReverse=Standard_False; aF=aFx; aE=aEx; if (aF.Orientation()==TopAbs_REVERSED){ bReverse=!bReverse; aE.Reverse(); // aF.Orientation(TopAbs_FORWARD); } // // Point at aT aC3D =BRep_Tool::Curve(aE, aT1, aT2); aC3D->D0(aT, aPFT); // // Normal at aT BOPTools_Tools3D::GetNormalToFaceOnEdge (aE, aF, aT, aDNFT); // Tangent at aT BOPTools_Tools3D::GetTangentToEdge(aE, aT, aDTT); // // Binormal at aT aDBT=aDNFT^aDTT; // dT=BOPTools_Tools3D::MinStepIn2d();//~1.e-5; dT=10.*dT; //---------------------------------------------- { aS=BRep_Tool::Surface(aF); aGAS.Load(aS); aTS=aGAS.GetType(); if (aTS==GeomAbs_BSplineSurface || aTS==GeomAbs_BezierSurface || aTS==GeomAbs_Plane) { Standard_Real aTolEx, aTolFx, aTol, dUR, dVR, dR; // aTolEx=BRep_Tool::Tolerance(aEx); aTolFx=BRep_Tool::Tolerance(aFx); aTol=2.*aTolEx+aTolFx; dUR=aGAS.UResolution(aTol); dVR=aGAS.VResolution(aTol); dR=(dUR>dVR)? dUR : dVR; if (dR>dT) { dT=dR; } } //modified by NIZNHY-PKV Thu Dec 02 10:39:09 2010f else if (GeomAbs_Torus || aTS==GeomAbs_Cylinder){ Standard_Real aTolEx, aTolFx, aTol; // aTolEx=BRep_Tool::Tolerance(aEx); aTolFx=BRep_Tool::Tolerance(aFx); aTol=2.*aTolEx+aTolFx; if (aTol>dT) { dT=aTol; } } //modified by NIZNHY-PKV Thu Dec 02 10:39:13 2010t } //---------------------------------------------- // aPFx.SetXYZ(aPFT.XYZ()+dT*aDBT.XYZ()); // aPF=aPFx; aDNF=aDNFT; if (bReverse) { aDNF.Reverse(); } // GeomAPI_ProjectPointOnSurf& aProjector=aCtx.ProjPS(aF); // aProjector.Perform(aPFx); if(aProjector.IsDone()) { aProjector.LowerDistanceParameters (aU, aV); aS->D0(aU, aV, aPF); BOPTools_Tools3D::GetNormalToSurface (aS, aU, aV, aDNF); if (bReverse){ aDNF.Reverse(); } } }
//======================================================================= //function : Execute //purpose : //======================================================================= Standard_Integer GEOMImpl_Fillet1dDriver::Execute(TFunction_Logbook& log) const { if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); GEOMImpl_IFillet1d aCI (aFunction); Handle(GEOM_Function) aRefShape = aCI.GetShape(); TopoDS_Shape aShape = aRefShape->GetValue(); if (aShape.IsNull()) return 0; if (aShape.ShapeType() != TopAbs_WIRE) Standard_ConstructionError::Raise("Wrong arguments: polyline as wire must be given"); TopoDS_Wire aWire = TopoDS::Wire(aShape); double rad = aCI.GetR(); if ( rad < Precision::Confusion()) return 0; // collect vertices for make fillet TopTools_ListOfShape aVertexList; TopTools_MapOfShape mapShape; int aLen = aCI.GetLength(); if ( aLen > 0 ) { for (int ind = 1; ind <= aLen; ind++) { TopoDS_Shape aShapeVertex; if (GEOMImpl_ILocalOperations::GetSubShape (aWire, aCI.GetVertex(ind), aShapeVertex)) if (mapShape.Add(aShapeVertex)) aVertexList.Append( aShapeVertex ); } } else { // get all vertices from wire TopExp_Explorer anExp( aWire, TopAbs_VERTEX ); for ( ; anExp.More(); anExp.Next() ) { if (mapShape.Add(anExp.Current())) aVertexList.Append( anExp.Current() ); } } if (aVertexList.IsEmpty()) Standard_ConstructionError::Raise("Invalid input no vertices to make fillet"); //INFO: this algorithm implemented in assumption that user can select both // vertices of some edges to make fillet. In this case we should remember // already modified initial edges to take care in next fillet step TopTools_DataMapOfShapeShape anEdgeToEdgeMap; //iterates on vertices, and make fillet on each couple of edges //collect result fillet edges in list TopTools_ListOfShape aListOfNewEdge; // remember relation between initial and modified map TopTools_IndexedDataMapOfShapeListOfShape aMapVToEdges; TopExp::MapShapesAndAncestors( aWire, TopAbs_VERTEX, TopAbs_EDGE, aMapVToEdges ); TopTools_ListIteratorOfListOfShape anIt( aVertexList ); for ( ; anIt.More(); anIt.Next() ) { TopoDS_Vertex aV = TopoDS::Vertex( anIt.Value() ); if ( aV.IsNull() || !aMapVToEdges.Contains( aV ) ) continue; const TopTools_ListOfShape& aVertexEdges = aMapVToEdges.FindFromKey( aV ); if ( aVertexEdges.Extent() != 2 ) continue; // no input data to make fillet TopoDS_Edge anEdge1 = TopoDS::Edge( aVertexEdges.First() ); TopoDS_Edge anEdge2 = TopoDS::Edge( aVertexEdges.Last() ); // check if initial edges already modified in previous fillet operation if ( anEdgeToEdgeMap.IsBound( anEdge1 ) ) anEdge1 = TopoDS::Edge(anEdgeToEdgeMap.Find( anEdge1 )); if ( anEdgeToEdgeMap.IsBound( anEdge2 ) ) anEdge2 = TopoDS::Edge(anEdgeToEdgeMap.Find( anEdge2 )); if ( anEdge1.IsNull() || anEdge2.IsNull() || anEdge1.IsSame( anEdge2 ) ) continue; //no input data to make fillet // create plane on 2 edges gp_Pln aPlane; if ( !takePlane(anEdge1, anEdge2, aV, aPlane) ) continue; // seems edges does not belong to same plane or parallel (fillet can not be build) GEOMImpl_Fillet1d aFilletAlgo(anEdge1, anEdge2, aPlane); if ( !aFilletAlgo.Perform(rad) ) continue; // can not create fillet with given radius // take fillet result in given vertex TopoDS_Edge aModifE1, aModifE2; TopoDS_Edge aNewE = aFilletAlgo.Result(BRep_Tool::Pnt(aV), aModifE1, aModifE2); if (aNewE.IsNull()) continue; // no result found // add new created edges and take modified edges aListOfNewEdge.Append( aNewE ); // check if face edges modified, // if yes, than map to original edges (from vertex-edges list), because edges can be modified before if (aModifE1.IsNull() || !anEdge1.IsSame( aModifE1 )) addEdgeRelation( anEdgeToEdgeMap, TopoDS::Edge(aVertexEdges.First()), aModifE1 ); if (aModifE2.IsNull() || !anEdge2.IsSame( aModifE2 )) addEdgeRelation( anEdgeToEdgeMap, TopoDS::Edge(aVertexEdges.Last()), aModifE2 ); } if ( anEdgeToEdgeMap.IsEmpty() && aListOfNewEdge.IsEmpty() ) { StdFail_NotDone::Raise("1D Fillet can't be computed on the given shape with the given radius"); return 0; } // create new wire instead of original for ( TopExp_Explorer anExp( aWire, TopAbs_EDGE ); anExp.More(); anExp.Next() ) { TopoDS_Shape anEdge = anExp.Current(); if ( !anEdgeToEdgeMap.IsBound( anEdge ) ) aListOfNewEdge.Append( anEdge ); else if (!anEdgeToEdgeMap.Find( anEdge ).IsNull()) aListOfNewEdge.Append( anEdgeToEdgeMap.Find( anEdge ) ); } GEOMImpl_IShapesOperations::SortShapes( aListOfNewEdge ); BRepBuilderAPI_MakeWire aWireTool; aWireTool.Add( aListOfNewEdge ); aWireTool.Build(); if (!aWireTool.IsDone()) return 0; aWire = aWireTool.Wire(); aFunction->SetValue(aWire); log.SetTouched(Label()); return 1; }