/// utility non-class member functions //! Returns the centroid of shape, as viewed according to direction and xAxis gp_Pnt TechDrawGeometry::findCentroid(const TopoDS_Shape &shape, const Base::Vector3d &direction, const Base::Vector3d &xAxis) { gp_Ax2 viewAxis; viewAxis = gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(direction.x, -direction.y, direction.z), gp_Dir(xAxis.x, -xAxis.y, xAxis.z)); // Y invert warning! gp_Trsf tempTransform; tempTransform.SetTransformation(viewAxis); BRepBuilderAPI_Transform builder(shape, tempTransform); Bnd_Box tBounds; BRepBndLib::Add(builder.Shape(), tBounds); tBounds.SetGap(0.0); Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; tBounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); Standard_Real x = (xMin + xMax) / 2.0, y = (yMin + yMax) / 2.0, z = (zMin + zMax) / 2.0; // Get centroid back into object space tempTransform.Inverted().Transforms(x, y, z); return gp_Pnt(x, y, z); }
//! Returns the centroid of shape, as viewed according to direction gp_Pnt TechDrawGeometry::findCentroid(const TopoDS_Shape &shape, const Base::Vector3d &direction) { Base::Vector3d origin(0.0,0.0,0.0); gp_Ax2 viewAxis = getViewAxis(origin,direction); gp_Trsf tempTransform; tempTransform.SetTransformation(viewAxis); BRepBuilderAPI_Transform builder(shape, tempTransform); Bnd_Box tBounds; BRepBndLib::Add(builder.Shape(), tBounds); tBounds.SetGap(0.0); Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; tBounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); Standard_Real x = (xMin + xMax) / 2.0, y = (yMin + yMax) / 2.0, z = (zMin + zMax) / 2.0; // Get centroid back into object space tempTransform.Inverted().Transforms(x, y, z); return gp_Pnt(x, y, z); }
Base::BoundBox3d PropertyPartShape::getBoundingBox() const { Base::BoundBox3d box; if (_Shape._Shape.IsNull()) return box; try { // If the shape is empty an exception may be thrown Bnd_Box bounds; BRepBndLib::Add(_Shape._Shape, bounds); bounds.SetGap(0.0); Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); box.MinX = xMin; box.MaxX = xMax; box.MinY = yMin; box.MaxY = yMax; box.MinZ = zMin; box.MaxZ = zMax; } catch (Standard_Failure) { } return box; }
void InventorShape::computeShape() { Bnd_Box bounds; BRepBndLib::Add(shape->getShape(), bounds); bounds.SetGap(0.0); Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * 0.2; BRepMesh::Mesh(shape->getShape(), deflection); SoGroup* faces = new SoGroup(); computeFaces(faces, shape->getShape()); separator->addChild(faces); SoGroup* edges = new SoGroup(); computeEdges(edges, shape->getShape()); separator->addChild(edges); SoGroup* vertices = new SoGroup(); computeVertices(vertices, shape->getShape()); separator->addChild(vertices); }
void Transformed::divideTools(const std::vector<TopoDS_Shape> &toolsIn, std::vector<TopoDS_Shape> &individualsOut, TopoDS_Compound &compoundOut) const { typedef std::pair<TopoDS_Shape, Bnd_Box> ShapeBoundPair; typedef std::list<ShapeBoundPair> PairList; typedef std::vector<ShapeBoundPair> PairVector; PairList pairList; std::vector<TopoDS_Shape>::const_iterator it; for (it = toolsIn.begin(); it != toolsIn.end(); ++it) { Bnd_Box bound; BRepBndLib::Add(*it, bound); bound.SetGap(0.0); ShapeBoundPair temp = std::make_pair(*it, bound); pairList.push_back(temp); } BRep_Builder builder; builder.MakeCompound(compoundOut); while(!pairList.empty()) { PairVector currentGroup; currentGroup.push_back(pairList.front()); pairList.pop_front(); PairList::iterator it = pairList.begin(); while(it != pairList.end()) { PairVector::const_iterator groupIt; bool found(false); for (groupIt = currentGroup.begin(); groupIt != currentGroup.end(); ++groupIt) { if (!(*it).second.IsOut((*groupIt).second))//touching means is out. { found = true; break; } } if (found) { currentGroup.push_back(*it); pairList.erase(it); it=pairList.begin(); continue; } it++; } if (currentGroup.size() == 1) builder.Add(compoundOut, currentGroup.front().first); else { PairVector::const_iterator groupIt; for (groupIt = currentGroup.begin(); groupIt != currentGroup.end(); ++groupIt) individualsOut.push_back((*groupIt).first); } } }
TopoDS_Shape ProjectionAlgos::invertY(const TopoDS_Shape& shape) { // make sure to have the y coordinates inverted gp_Trsf mat; Bnd_Box bounds; BRepBndLib::Add(shape, bounds); bounds.SetGap(0.0); Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); mat.SetMirror(gp_Ax2(gp_Pnt((xMin+xMax)/2,(yMin+yMax)/2,(zMin+zMax)/2), gp_Dir(0,1,0))); BRepBuilderAPI_Transform mkTrf(shape, mat); return mkTrf.Shape(); }
Base::BoundBox3d GeometryObject::calcBoundingBox() const { Bnd_Box testBox; testBox.SetGap(0.0); for (std::vector<BaseGeom *>::const_iterator it( edgeGeom.begin() ); it != edgeGeom.end(); ++it) { BRepBndLib::Add((*it)->occEdge, testBox); } if (testBox.IsVoid()) { Base::Console().Log("INFO - GO::calcBoundingBox - testBox is void\n"); } double xMin,xMax,yMin,yMax,zMin,zMax; testBox.Get(xMin,yMin,zMin,xMax,yMax,zMax); Base::BoundBox3d bbox(xMin,yMin,zMin,xMax,yMax,zMax); return bbox; }
//this routine is the big time consumer. gets called many times (and is slow?)) //note param gets modified here bool DrawProjectSplit::isOnEdge(TopoDS_Edge e, TopoDS_Vertex v, double& param, bool allowEnds) { bool result = false; bool outOfBox = false; param = -2; //eliminate obvious cases Bnd_Box sBox; BRepBndLib::Add(e, sBox); sBox.SetGap(0.1); if (sBox.IsVoid()) { Base::Console().Message("DPS::isOnEdge - Bnd_Box is void\n"); } else { gp_Pnt pt = BRep_Tool::Pnt(v); if (sBox.IsOut(pt)) { outOfBox = true; } } if (!outOfBox) { double dist = DrawUtil::simpleMinDist(v,e); if (dist < 0.0) { Base::Console().Error("DPS::isOnEdge - simpleMinDist failed: %.3f\n",dist); result = false; } else if (dist < Precision::Confusion()) { const gp_Pnt pt = BRep_Tool::Pnt(v); //have to duplicate method 3 to get param BRepAdaptor_Curve adapt(e); const Handle_Geom_Curve c = adapt.Curve().Curve(); double maxDist = 0.000001; //magic number. less than this gives false positives. //bool found = (void) GeomLib_Tool::Parameter(c,pt,maxDist,param); //already know point it on curve result = true; } if (result) { TopoDS_Vertex v1 = TopExp::FirstVertex(e); TopoDS_Vertex v2 = TopExp::LastVertex(e); if (DrawUtil::isSamePoint(v,v1) || DrawUtil::isSamePoint(v,v2)) { if (!allowEnds) { result = false; } } } } //!outofbox return result; }
void ViewProviderTransformed::recomputeFeature(void) { PartDesign::Transformed* pcTransformed = static_cast<PartDesign::Transformed*>(getObject()); pcTransformed->getDocument()->recomputeFeature(pcTransformed); const std::vector<App::DocumentObjectExecReturn*> log = pcTransformed->getDocument()->getRecomputeLog(); PartDesign::Transformed::rejectedMap rejected_trsf = pcTransformed->getRejectedTransformations(); unsigned rejected = 0; for (PartDesign::Transformed::rejectedMap::const_iterator r = rejected_trsf.begin(); r != rejected_trsf.end(); r++) rejected += r->second.size(); QString msg = QString::fromLatin1("%1"); if (rejected > 0) { msg = QString::fromLatin1("<font color='orange'>%1<br/></font>\r\n%2"); if (rejected == 1) msg = msg.arg(QObject::tr("One transformed shape does not intersect support")); else { msg = msg.arg(QObject::tr("%1 transformed shapes do not intersect support")); msg = msg.arg(rejected); } } if (log.size() > 0) { msg = msg.arg(QString::fromLatin1("<font color='red'>%1<br/></font>")); msg = msg.arg(QString::fromStdString(log.back()->Why)); } else { msg = msg.arg(QString::fromLatin1("<font color='green'>%1<br/></font>")); msg = msg.arg(QObject::tr("Transformation succeeded")); } signalDiagnosis(msg); // Clear all the rejected stuff while (pcRejectedRoot->getNumChildren() > 7) { SoSeparator* sep = static_cast<SoSeparator*>(pcRejectedRoot->getChild(7)); SoMultipleCopy* rejectedTrfms = static_cast<SoMultipleCopy*>(sep->getChild(2)); rejectedTrfms ->removeAllChildren(); sep->removeChild(1); sep->removeChild(0); pcRejectedRoot ->removeChild(7); } for (PartDesign::Transformed::rejectedMap::const_iterator o = rejected_trsf.begin(); o != rejected_trsf.end(); o++) { if (o->second.empty()) continue; TopoDS_Shape shape; if ((o->first)->getTypeId().isDerivedFrom(PartDesign::FeatureAddSub::getClassTypeId())) { PartDesign::FeatureAddSub* feature = static_cast<PartDesign::FeatureAddSub*>(o->first); shape = feature->AddSubShape.getShape().getShape(); } if (shape.IsNull()) continue; // Display the rejected transformations in red TopoDS_Shape cShape(shape); try { // calculating the deflection value Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; { Bnd_Box bounds; BRepBndLib::Add(cShape, bounds); bounds.SetGap(0.0); bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); } Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue(); // create or use the mesh on the data structure // Note: This DOES have an effect on cShape #if OCC_VERSION_HEX >= 0x060600 Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * M_PI; BRepMesh_IncrementalMesh(cShape,deflection,Standard_False, AngDeflectionRads,Standard_True); #else BRepMesh_IncrementalMesh(cShape,deflection); #endif // We must reset the location here because the transformation data // are set in the placement property TopLoc_Location aLoc; cShape.Location(aLoc); // count triangles and nodes in the mesh int nbrTriangles=0, nbrNodes=0; TopExp_Explorer Ex; for (Ex.Init(cShape,TopAbs_FACE);Ex.More();Ex.Next()) { Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc); // Note: we must also count empty faces if (!mesh.IsNull()) { nbrTriangles += mesh->NbTriangles(); nbrNodes += mesh->NbNodes(); } } // create memory for the nodes and indexes SoCoordinate3* rejectedCoords = new SoCoordinate3(); rejectedCoords ->point .setNum(nbrNodes); SoNormal* rejectedNorms = new SoNormal(); rejectedNorms ->vector .setNum(nbrNodes); SoIndexedFaceSet* rejectedFaceSet = new SoIndexedFaceSet(); rejectedFaceSet ->coordIndex .setNum(nbrTriangles*4); // get the raw memory for fast fill up SbVec3f* verts = rejectedCoords ->point .startEditing(); SbVec3f* norms = rejectedNorms ->vector .startEditing(); int32_t* index = rejectedFaceSet ->coordIndex .startEditing(); // preset the normal vector with null vector for (int i=0; i < nbrNodes; i++) norms[i]= SbVec3f(0.0,0.0,0.0); int ii = 0,FaceNodeOffset=0,FaceTriaOffset=0; for (Ex.Init(cShape, TopAbs_FACE); Ex.More(); Ex.Next(),ii++) { TopLoc_Location aLoc; const TopoDS_Face &actFace = TopoDS::Face(Ex.Current()); // get the mesh of the shape Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace,aLoc); if (mesh.IsNull()) continue; // getting the transformation of the shape/face gp_Trsf myTransf; Standard_Boolean identity = true; if (!aLoc.IsIdentity()) { identity = false; myTransf = aLoc.Transformation(); } // getting size of node and triangle array of this face int nbNodesInFace = mesh->NbNodes(); int nbTriInFace = mesh->NbTriangles(); // check orientation TopAbs_Orientation orient = actFace.Orientation(); // cycling through the poly mesh const Poly_Array1OfTriangle& Triangles = mesh->Triangles(); const TColgp_Array1OfPnt& Nodes = mesh->Nodes(); for (int g=1; g <= nbTriInFace; g++) { // Get the triangle Standard_Integer N1,N2,N3; Triangles(g).Get(N1,N2,N3); // change orientation of the triangle if the face is reversed if ( orient != TopAbs_FORWARD ) { Standard_Integer tmp = N1; N1 = N2; N2 = tmp; } // get the 3 points of this triangle gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3)); // transform the vertices to the place of the face if (!identity) { V1.Transform(myTransf); V2.Transform(myTransf); V3.Transform(myTransf); } // calculating per vertex normals // Calculate triangle normal gp_Vec v1(V1.X(),V1.Y(),V1.Z()),v2(V2.X(),V2.Y(),V2.Z()),v3(V3.X(),V3.Y(),V3.Z()); gp_Vec Normal = (v2-v1)^(v3-v1); // add the triangle normal to the vertex normal for all points of this triangle norms[FaceNodeOffset+N1-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); norms[FaceNodeOffset+N2-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); norms[FaceNodeOffset+N3-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); // set the vertices verts[FaceNodeOffset+N1-1].setValue((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z())); verts[FaceNodeOffset+N2-1].setValue((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z())); verts[FaceNodeOffset+N3-1].setValue((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z())); // set the index vector with the 3 point indexes and the end delimiter index[FaceTriaOffset*4+4*(g-1)] = FaceNodeOffset+N1-1; index[FaceTriaOffset*4+4*(g-1)+1] = FaceNodeOffset+N2-1; index[FaceTriaOffset*4+4*(g-1)+2] = FaceNodeOffset+N3-1; index[FaceTriaOffset*4+4*(g-1)+3] = SO_END_FACE_INDEX; } // counting up the per Face offsets FaceNodeOffset += nbNodesInFace; FaceTriaOffset += nbTriInFace; } // normalize all normals for (int i=0; i < nbrNodes; i++) norms[i].normalize(); // end the editing of the nodes rejectedCoords ->point .finishEditing(); rejectedNorms ->vector .finishEditing(); rejectedFaceSet ->coordIndex .finishEditing(); // fill in the transformation matrices SoMultipleCopy* rejectedTrfms = new SoMultipleCopy(); rejectedTrfms->matrix.setNum((o->second).size()); SbMatrix* mats = rejectedTrfms->matrix.startEditing(); std::list<gp_Trsf>::const_iterator trsf = (o->second).begin(); for (unsigned int i=0; i < (o->second).size(); i++,trsf++) { Base::Matrix4D mat; Part::TopoShape::convertToMatrix(*trsf,mat); mats[i] = convert(mat); } rejectedTrfms->matrix.finishEditing(); rejectedTrfms->addChild(rejectedFaceSet); SoSeparator* sep = new SoSeparator(); sep->addChild(rejectedCoords); sep->addChild(rejectedNorms); sep->addChild(rejectedTrfms); pcRejectedRoot->addChild(sep); } catch (...) { Base::Console().Error("Cannot compute Inventor representation for the rejected transformations of shape of %s.\n", pcTransformed->getNameInDocument()); } } }
//this routine is the big time consumer. gets called many times (and is slow?)) //note param gets modified here bool DrawViewPart::isOnEdge(TopoDS_Edge e, TopoDS_Vertex v, double& param, bool allowEnds) { bool result = false; bool outOfBox = false; param = -2; //eliminate obvious cases Bnd_Box sBox; BRepBndLib::Add(e, sBox); sBox.SetGap(0.1); if (sBox.IsVoid()) { Base::Console().Message("DVP::isOnEdge - Bnd_Box is void for %s\n",getNameInDocument()); } else { gp_Pnt pt = BRep_Tool::Pnt(v); if (sBox.IsOut(pt)) { outOfBox = true; } } if (!outOfBox) { if (m_interAlgo == 1) { //1) using projPointOnCurve. roughly similar to dist to shape w/ bndbox. hangs(?) w/o bndbox try { gp_Pnt pt = BRep_Tool::Pnt(v); BRepAdaptor_Curve adapt(e); Handle_Geom_Curve c = adapt.Curve().Curve(); GeomAPI_ProjectPointOnCurve proj(pt,c); int n = proj.NbPoints(); if (n > 0) { if (proj.LowerDistance() < Precision::Confusion()) { param = proj.LowerDistanceParameter(); result = true; } if (result) { TopoDS_Vertex v1 = TopExp::FirstVertex(e); TopoDS_Vertex v2 = TopExp::LastVertex(e); if (DrawUtil::isSamePoint(v,v1) || DrawUtil::isSamePoint(v,v2)) { if (!allowEnds) { result = false; } } } } } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); //no perp projection } } else if (m_interAlgo == 2) { //can't provide param as is double dist = simpleMinDist(v,e); if (dist < 0.0) { Base::Console().Error("DVP::isOnEdge - simpleMinDist failed: %.3f\n",dist); result = false; } else if (dist < Precision::Confusion()) { const gp_Pnt pt = BRep_Tool::Pnt(v); //have to duplicate method 3 to get param BRepAdaptor_Curve adapt(e); const Handle_Geom_Curve c = adapt.Curve().Curve(); double maxDist = 0.000001; //magic number. less than this gives false positives. //bool found = (void) GeomLib_Tool::Parameter(c,pt,maxDist,param); //already know point it on curve result = true; } if (result) { TopoDS_Vertex v1 = TopExp::FirstVertex(e); TopoDS_Vertex v2 = TopExp::LastVertex(e); if (DrawUtil::isSamePoint(v,v1) || DrawUtil::isSamePoint(v,v2)) { if (!allowEnds) { result = false; } } } } else if (m_interAlgo == 3) { const gp_Pnt pt = BRep_Tool::Pnt(v); BRepAdaptor_Curve adapt(e); const Handle_Geom_Curve c = adapt.Curve().Curve(); double par = -1; double maxDist = 0.000001; //magic number. less than this gives false positives. bool found = GeomLib_Tool::Parameter(c,pt,maxDist,par); if (found) { result = true; param = par; TopoDS_Vertex v1 = TopExp::FirstVertex(e); TopoDS_Vertex v2 = TopExp::LastVertex(e); if (DrawUtil::isSamePoint(v,v1) || DrawUtil::isSamePoint(v,v2)) { if (!allowEnds) { result = false; } } } } } //!outofbox return result; }
//======================================================================= //function : DetectVertices //purpose : //======================================================================= void GEOMAlgo_GlueAnalyser::DetectVertices() { myErrorStatus=0; // Standard_Integer j, i, aNbV, aIndex, aNbVSD; TColStd_ListIteratorOfListOfInteger aIt; Handle(Bnd_HArray1OfBox) aHAB; Bnd_BoundSortBox aBSB; TopoDS_Shape aSTmp, aVF; TopoDS_Vertex aVnew; TopTools_IndexedMapOfShape aMV, aMVProcessed; TopTools_ListIteratorOfListOfShape aItS; TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItIm; GEOMAlgo_IndexedDataMapOfIntegerShape aMIS; GEOMAlgo_IndexedDataMapOfShapeBox aMSB; // TopExp::MapShapes(myShape, TopAbs_VERTEX, aMV); aNbV=aMV.Extent(); if (!aNbV) { myErrorStatus=2; // no vertices in source shape return; } // aHAB=new Bnd_HArray1OfBox(1, aNbV); // for (i=1; i<=aNbV; ++i) { const TopoDS_Shape& aV=aMV(i); Bnd_Box aBox; // aBox.SetGap(myTol); BRepBndLib::Add(aV, aBox); aHAB->SetValue(i, aBox); aMIS.Add(i, aV); aMSB.Add(aV, aBox); } // aBSB.Initialize(aHAB); // for (i=1; i<=aNbV; ++i) { const TopoDS_Shape& aV=aMV(i); // if (aMVProcessed.Contains(aV)) { continue; } // const Bnd_Box& aBoxV=aMSB.FindFromKey(aV); const TColStd_ListOfInteger& aLI=aBSB.Compare(aBoxV); aNbVSD=aLI.Extent(); if (!aNbVSD) { myErrorStatus=3; // it must not be return; } // // Images TopTools_ListOfShape aLVSD; // aIt.Initialize(aLI); for (j=0; aIt.More(); aIt.Next(), ++j) { aIndex=aIt.Value(); const TopoDS_Shape& aVx=aMIS.FindFromKey(aIndex); if(!j) { aVF=aVx; } aLVSD.Append(aVx); aMVProcessed.Add(aVx); } myImages.Bind(aVF, aLVSD); } // Origins aItIm.Initialize(myImages); for (; aItIm.More(); aItIm.Next()) { const TopoDS_Shape& aV=aItIm.Key(); const TopTools_ListOfShape& aLVSD=aItIm.Value(); // aItS.Initialize(aLVSD); for (; aItS.More(); aItS.Next()) { const TopoDS_Shape& aVSD=aItS.Value(); if (!myOrigins.IsBound(aVSD)) { myOrigins.Bind(aVSD, aV); } } } }
//======================================================================= // function: MakeAloneVertices // purpose: //======================================================================= void NMTTools_PaveFiller::MakeAloneVertices() { Standard_Integer i, aNbFFs, nF1, nF2, j, aNbPnts, nFx, aNbV; Standard_Real aTolF1, aTolF2, aTolSum, aTolV; TColStd_ListIteratorOfListOfInteger aIt; TColStd_ListOfInteger aLI; TopoDS_Vertex aV; TopoDS_Compound aCompound; BRep_Builder aBB; TopTools_DataMapOfShapeListOfInteger aDMVFF, aDMVFF1; TopTools_DataMapIteratorOfDataMapOfShapeListOfInteger aItDMVFF; TopTools_DataMapOfShapeShape aDMVV; TopTools_DataMapOfIntegerShape aDMIV; TopTools_DataMapOfShapeInteger aDMVI; TopTools_DataMapIteratorOfDataMapOfShapeInteger aItDMVI; TopTools_DataMapIteratorOfDataMapOfIntegerShape aItDMIV; // aBB.MakeCompound(aCompound); // myAloneVertices.Clear(); // BOPTools_CArray1OfSSInterference& aFFs=myIP->SSInterferences(); // // 1. Collect alone vertices from FFs aNbV=0; aNbFFs=aFFs.Extent(); for (i=1; i<=aNbFFs; ++i) { BOPTools_SSInterference& aFFi=aFFs(i); aFFi.Indices(nF1, nF2); // const TopoDS_Face aF1=TopoDS::Face(myDS->Shape(nF1));//mpv const TopoDS_Face aF2=TopoDS::Face(myDS->Shape(nF2));//mpv // aTolF1=BRep_Tool::Tolerance(aF1); aTolF2=BRep_Tool::Tolerance(aF2); aTolSum=aTolF1+aTolF2; // aLI.Clear(); aLI.Append(nF1); aLI.Append(nF2); // const IntTools_SequenceOfPntOn2Faces& aSeqAlonePnts=aFFi.AlonePnts(); aNbPnts=aSeqAlonePnts.Length(); for (j=1; j<=aNbPnts; ++j) { const gp_Pnt& aP=aSeqAlonePnts(j).P1().Pnt(); BOPTools_Tools::MakeNewVertex(aP, aTolSum, aV); aDMVFF.Bind(aV, aLI); aBB.Add(aCompound, aV); ++aNbV; } } if (!aNbV) { return; } // // 2. Try to fuse alone vertices themselves; FuseVertices(aCompound, aDMVV); // // if some are fused, replace them by new ones aItDMVFF.Initialize(aDMVFF); for (; aItDMVFF.More(); aItDMVFF.Next()) { const TopoDS_Shape& aVx=aItDMVFF.Key(); const TColStd_ListOfInteger& aLIx=aItDMVFF.Value(); // if (!aDMVV.IsBound(aVx)) { aDMVFF1.Bind(aVx, aLIx); } else { const TopoDS_Shape& aVy=aDMVV.Find(aVx); if (aDMVFF1.IsBound(aVy)) { TColStd_ListOfInteger& aLIy=aDMVFF1.ChangeFind(aVy); aIt.Initialize(aLIx); for(; aIt.More(); aIt.Next()) { nFx=aIt.Value(); aLIy.Append(nFx); } } else { aDMVFF1.Bind(aVy, aLIx); } } } aDMVFF.Clear(); // // refine lists of faces in aDMVFF1; aItDMVFF.Initialize(aDMVFF1); for (; aItDMVFF.More(); aItDMVFF.Next()) { TColStd_MapOfInteger aMIy; TColStd_ListOfInteger aLIy; // const TopoDS_Shape& aVx=aItDMVFF.Key(); TColStd_ListOfInteger& aLIx=aDMVFF1.ChangeFind(aVx); aIt.Initialize(aLIx); for(; aIt.More(); aIt.Next()) { nFx=aIt.Value(); if (aMIy.Add(nFx)) { aLIy.Append(nFx); } } aLIx.Clear(); aLIx.Append(aLIy); } //================================== // // 3. Collect vertices from DS Standard_Integer aNbS, nV, nVSD, aNbVDS, i1, i2, aNbVSD; // aNbS=myDS->NumberOfShapesOfTheObject(); // old shapes for (i=1; i<=aNbS; ++i) { const TopoDS_Shape& aS=myDS->Shape(i); if (aS.ShapeType() != TopAbs_VERTEX){ continue; } // nVSD=FindSDVertex(i); nV=(nVSD) ? nVSD : i; const TopoDS_Shape& aVx=myDS->Shape(nV); if (!aDMVI.IsBound(aVx)) { aDMVI.Bind(aVx, nV); } } // new shapes i1=myDS->NumberOfSourceShapes()+1; i2=myDS->NumberOfInsertedShapes(); for (i=i1; i<=i2; ++i) { const TopoDS_Shape aS=myDS->Shape(i);//mpv if (aS.ShapeType() != TopAbs_VERTEX){ continue; } if (!aDMVI.IsBound(aS)) { aDMVI.Bind(aS, i); } } // // 4. Initialize BoundSortBox on aDMVI // Handle(Bnd_HArray1OfBox) aHAB; Bnd_BoundSortBox aBSB; // aNbVDS=aDMVI.Extent(); aHAB=new Bnd_HArray1OfBox(1, aNbVDS); // aItDMVI.Initialize(aDMVI); for (i=1; aItDMVI.More(); aItDMVI.Next(), ++i) { Bnd_Box aBox; // nV=aItDMVI.Value(); aV=TopoDS::Vertex(aItDMVI.Key()); aTolV=BRep_Tool::Tolerance(aV); aBox.SetGap(aTolV); BRepBndLib::Add(aV, aBox); aHAB->SetValue(i, aBox); // aDMIV.Bind(i, aV); } aBSB.Initialize(aHAB); // // 5. Compare aItDMVFF.Initialize(aDMVFF1); for (; aItDMVFF.More(); aItDMVFF.Next()) { Bnd_Box aBoxV; // const TColStd_ListOfInteger& aLIFF=aItDMVFF.Value(); aV=TopoDS::Vertex(aItDMVFF.Key()); // aTolV=BRep_Tool::Tolerance(aV); aBoxV.SetGap(aTolV); BRepBndLib::Add(aV, aBoxV); // const TColStd_ListOfInteger& aLIVSD=aBSB.Compare(aBoxV); aNbVSD=aLIVSD.Extent(); if (aNbVSD==0) { // add new vertex in DS and update map myAloneVertices BooleanOperations_AncestorsSeqAndSuccessorsSeq anASSeq; // myDS->InsertShapeAndAncestorsSuccessors(aV, anASSeq); nV=myDS->NumberOfInsertedShapes(); // aIt.Initialize(aLIFF); for (; aIt.More(); aIt.Next()) { nFx=aIt.Value(); if (myAloneVertices.Contains(nFx)) { TColStd_IndexedMapOfInteger& aMVx=myAloneVertices.ChangeFromKey(nFx); aMVx.Add(nV); } else { TColStd_IndexedMapOfInteger aMVx; aMVx.Add(nV); myAloneVertices.Add(nFx, aMVx); } } } } // qqf { Standard_Integer aNbF, aNbAV, nF, k; NMTTools_IndexedDataMapOfIndexedMapOfInteger aMAVF; // aNbF=myAloneVertices.Extent(); if (aNbF<2) { return; } // // 1. fill map Alone Vertex/Face -> aMAVF for (i=1; i<=aNbF; ++i) { nF=myAloneVertices.FindKey(i); const TColStd_IndexedMapOfInteger& aMAV=myAloneVertices(i); aNbAV=aMAV.Extent(); for(j=1; j<=aNbAV; ++j) { nV=aMAV(j); if (aMAVF.Contains(nV)) { TColStd_IndexedMapOfInteger& aMF=aMAVF.ChangeFromKey(nV); aMF.Add(nF); } else{ TColStd_IndexedMapOfInteger aMF; aMF.Add(nF); aMAVF.Add(nV, aMF); } } } // // 2 Obtain pairs of faces aNbAV=aMAVF.Extent(); for (i=1; i<=aNbAV; ++i) { const TColStd_IndexedMapOfInteger& aMF=aMAVF(i); aNbF=aMF.Extent(); for(j=1; j<aNbF; ++j) { nF1=aMF(j); for(k=j+1; k<=aNbF; ++k) { nF2=aMF(k); myIP->Add(nF1, nF2, Standard_True, NMTDS_TI_FF); } } } } // qqt }
App::DocumentObjectExecReturn *DrawViewSection::execute(void) { App::DocumentObject* link = Source.getValue(); App::DocumentObject* base = BaseView.getValue(); if (!link || !base) { Base::Console().Log("INFO - DVS::execute - No Source or Link - creation?\n"); return DrawView::execute(); } if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) return new App::DocumentObjectExecReturn("Source object is not a Part object"); if (!base->getTypeId().isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) return new App::DocumentObjectExecReturn("BaseView object is not a DrawViewPart object"); //Base::Console().Message("TRACE - DVS::execute() - %s/%s\n",getNameInDocument(),Label.getValue()); const Part::TopoShape &partTopo = static_cast<Part::Feature*>(link)->Shape.getShape(); if (partTopo.getShape().IsNull()) return new App::DocumentObjectExecReturn("Linked shape object is empty"); (void) DrawView::execute(); //make sure Scale is up to date gp_Pln pln = getSectionPlane(); gp_Dir gpNormal = pln.Axis().Direction(); Base::Vector3d orgPnt = SectionOrigin.getValue(); Base::BoundBox3d bb = partTopo.getBoundBox(); if(!isReallyInBox(orgPnt, bb)) { Base::Console().Warning("DVS: Section Plane doesn't intersect part in %s\n",getNameInDocument()); Base::Console().Warning("DVS: Using center of bounding box.\n"); orgPnt = bb.GetCenter(); SectionOrigin.setValue(orgPnt); } // Make the extrusion face double dMax = bb.CalcDiagonalLength(); BRepBuilderAPI_MakeFace mkFace(pln, -dMax,dMax,-dMax,dMax); TopoDS_Face aProjFace = mkFace.Face(); if(aProjFace.IsNull()) return new App::DocumentObjectExecReturn("DrawViewSection - Projected face is NULL"); gp_Vec extrudeDir = dMax * gp_Vec(gpNormal); TopoDS_Shape prism = BRepPrimAPI_MakePrism(aProjFace, extrudeDir, false, true).Shape(); // We need to copy the shape to not modify the BRepstructure BRepBuilderAPI_Copy BuilderCopy(partTopo.getShape()); TopoDS_Shape myShape = BuilderCopy.Shape(); BRepAlgoAPI_Cut mkCut(myShape, prism); if (!mkCut.IsDone()) return new App::DocumentObjectExecReturn("Section cut has failed"); TopoDS_Shape rawShape = mkCut.Shape(); Bnd_Box testBox; BRepBndLib::Add(rawShape, testBox); testBox.SetGap(0.0); if (testBox.IsVoid()) { //prism & input don't intersect. rawShape is garbage, don't bother. Base::Console().Log("INFO - DVS::execute - prism & input don't intersect\n"); return DrawView::execute(); } gp_Pnt inputCenter; try { inputCenter = TechDrawGeometry::findCentroid(rawShape, Direction.getValue()); TopoDS_Shape mirroredShape = TechDrawGeometry::mirrorShape(rawShape, inputCenter, Scale.getValue()); geometryObject = buildGeometryObject(mirroredShape,inputCenter); //this is original shape after cut by section prism #if MOD_TECHDRAW_HANDLE_FACES extractFaces(); #endif //#if MOD_TECHDRAW_HANDLE_FACES } catch (Standard_Failure) { Handle_Standard_Failure e1 = Standard_Failure::Caught(); Base::Console().Log("LOG - DVS::execute - base shape failed for %s - %s **\n",getNameInDocument(),e1->GetMessageString()); return new App::DocumentObjectExecReturn(e1->GetMessageString()); } try { TopoDS_Compound sectionCompound = findSectionPlaneIntersections(rawShape); TopoDS_Shape mirroredSection = TechDrawGeometry::mirrorShape(sectionCompound, inputCenter, Scale.getValue()); TopoDS_Compound newFaces; BRep_Builder builder; builder.MakeCompound(newFaces); TopExp_Explorer expl(mirroredSection, TopAbs_FACE); for (; expl.More(); expl.Next()) { const TopoDS_Face& face = TopoDS::Face(expl.Current()); TopoDS_Face pFace = projectFace(face, inputCenter, Direction.getValue()); if (!pFace.IsNull()) { builder.Add(newFaces,pFace); } } sectionFaces = newFaces; } catch (Standard_Failure) { Handle_Standard_Failure e2 = Standard_Failure::Caught(); Base::Console().Log("LOG - DVS::execute - failed building section faces for %s - %s **\n",getNameInDocument(),e2->GetMessageString()); return new App::DocumentObjectExecReturn(e2->GetMessageString()); } return App::DocumentObject::StdReturn; }
//! get the projected edges with all their new intersections. std::vector<TopoDS_Edge> DrawProjectSplit::getEdges(TechDrawGeometry::GeometryObject* geometryObject) { const std::vector<TechDrawGeometry::BaseGeom*>& goEdges = geometryObject->getVisibleFaceEdges(true,true); std::vector<TechDrawGeometry::BaseGeom*>::const_iterator itEdge = goEdges.begin(); std::vector<TopoDS_Edge> origEdges; for (;itEdge != goEdges.end(); itEdge++) { origEdges.push_back((*itEdge)->occEdge); } std::vector<TopoDS_Edge> faceEdges; std::vector<TopoDS_Edge> nonZero; for (auto& e:origEdges) { //drop any zero edges (shouldn't be any by now!!!) if (!DrawUtil::isZeroEdge(e)) { nonZero.push_back(e); } else { Base::Console().Message("INFO - DPS::getEdges found ZeroEdge!\n"); } } faceEdges = nonZero; origEdges = nonZero; //HLR algo does not provide all edge intersections for edge endpoints. //need to split long edges touched by Vertex of another edge std::vector<splitPoint> splits; std::vector<TopoDS_Edge>::iterator itOuter = origEdges.begin(); int iOuter = 0; for (; itOuter != origEdges.end(); ++itOuter, iOuter++) { TopoDS_Vertex v1 = TopExp::FirstVertex((*itOuter)); TopoDS_Vertex v2 = TopExp::LastVertex((*itOuter)); Bnd_Box sOuter; BRepBndLib::Add(*itOuter, sOuter); sOuter.SetGap(0.1); if (sOuter.IsVoid()) { Base::Console().Message("DPS::Extract Faces - outer Bnd_Box is void\n"); continue; } if (DrawUtil::isZeroEdge(*itOuter)) { Base::Console().Message("DPS::extractFaces - outerEdge: %d is ZeroEdge\n",iOuter); //this is not finding ZeroEdges continue; //skip zero length edges. shouldn't happen ;) } int iInner = 0; std::vector<TopoDS_Edge>::iterator itInner = faceEdges.begin(); for (; itInner != faceEdges.end(); ++itInner,iInner++) { if (iInner == iOuter) { continue; } if (DrawUtil::isZeroEdge((*itInner))) { continue; //skip zero length edges. shouldn't happen ;) } Bnd_Box sInner; BRepBndLib::Add(*itInner, sInner); sInner.SetGap(0.1); if (sInner.IsVoid()) { Base::Console().Log("INFO - DPS::Extract Faces - inner Bnd_Box is void\n"); continue; } if (sOuter.IsOut(sInner)) { //bboxes of edges don't intersect, don't bother continue; } double param = -1; if (isOnEdge((*itInner),v1,param,false)) { gp_Pnt pnt1 = BRep_Tool::Pnt(v1); splitPoint s1; s1.i = iInner; s1.v = Base::Vector3d(pnt1.X(),pnt1.Y(),pnt1.Z()); s1.param = param; splits.push_back(s1); } if (isOnEdge((*itInner),v2,param,false)) { gp_Pnt pnt2 = BRep_Tool::Pnt(v2); splitPoint s2; s2.i = iInner; s2.v = Base::Vector3d(pnt2.X(),pnt2.Y(),pnt2.Z()); s2.param = param; splits.push_back(s2); } } //inner loop } //outer loop std::vector<splitPoint> sorted = sortSplits(splits,true); auto last = std::unique(sorted.begin(), sorted.end(), DrawProjectSplit::splitEqual); //duplicates to back sorted.erase(last, sorted.end()); //remove dupls std::vector<TopoDS_Edge> newEdges = splitEdges(faceEdges,sorted); if (newEdges.empty()) { Base::Console().Log("LOG - DPS::extractFaces - no newEdges\n"); } newEdges = removeDuplicateEdges(newEdges); return newEdges; }
//! make faces from the existing edge geometry void DrawViewPart::extractFaces() { geometryObject->clearFaceGeom(); const std::vector<TechDrawGeometry::BaseGeom*>& goEdges = geometryObject->getVisibleFaceEdges(SmoothVisible.getValue(),SeamVisible.getValue()); std::vector<TechDrawGeometry::BaseGeom*>::const_iterator itEdge = goEdges.begin(); std::vector<TopoDS_Edge> origEdges; for (;itEdge != goEdges.end(); itEdge++) { origEdges.push_back((*itEdge)->occEdge); } std::vector<TopoDS_Edge> faceEdges; std::vector<TopoDS_Edge> nonZero; for (auto& e:origEdges) { //drop any zero edges (shouldn't be any by now!!!) if (!DrawUtil::isZeroEdge(e)) { nonZero.push_back(e); } else { Base::Console().Message("INFO - DVP::extractFaces for %s found ZeroEdge!\n",getNameInDocument()); } } faceEdges = nonZero; origEdges = nonZero; //HLR algo does not provide all edge intersections for edge endpoints. //need to split long edges touched by Vertex of another edge std::vector<splitPoint> splits; std::vector<TopoDS_Edge>::iterator itOuter = origEdges.begin(); int iOuter = 0; for (; itOuter != origEdges.end(); ++itOuter, iOuter++) { TopoDS_Vertex v1 = TopExp::FirstVertex((*itOuter)); TopoDS_Vertex v2 = TopExp::LastVertex((*itOuter)); Bnd_Box sOuter; BRepBndLib::Add(*itOuter, sOuter); sOuter.SetGap(0.1); if (sOuter.IsVoid()) { Base::Console().Message("DVP::Extract Faces - outer Bnd_Box is void for %s\n",getNameInDocument()); continue; } if (DrawUtil::isZeroEdge(*itOuter)) { Base::Console().Message("DVP::extractFaces - outerEdge: %d is ZeroEdge\n",iOuter); //this is not finding ZeroEdges continue; //skip zero length edges. shouldn't happen ;) } int iInner = 0; std::vector<TopoDS_Edge>::iterator itInner = faceEdges.begin(); for (; itInner != faceEdges.end(); ++itInner,iInner++) { if (iInner == iOuter) { continue; } if (DrawUtil::isZeroEdge((*itInner))) { continue; //skip zero length edges. shouldn't happen ;) } Bnd_Box sInner; BRepBndLib::Add(*itInner, sInner); sInner.SetGap(0.1); if (sInner.IsVoid()) { Base::Console().Log("INFO - DVP::Extract Faces - inner Bnd_Box is void for %s\n",getNameInDocument()); continue; } if (sOuter.IsOut(sInner)) { //bboxes of edges don't intersect, don't bother continue; } double param = -1; if (DrawProjectSplit::isOnEdge((*itInner),v1,param,false)) { gp_Pnt pnt1 = BRep_Tool::Pnt(v1); splitPoint s1; s1.i = iInner; s1.v = Base::Vector3d(pnt1.X(),pnt1.Y(),pnt1.Z()); s1.param = param; splits.push_back(s1); } if (DrawProjectSplit::isOnEdge((*itInner),v2,param,false)) { gp_Pnt pnt2 = BRep_Tool::Pnt(v2); splitPoint s2; s2.i = iInner; s2.v = Base::Vector3d(pnt2.X(),pnt2.Y(),pnt2.Z()); s2.param = param; splits.push_back(s2); } } //inner loop } //outer loop std::vector<splitPoint> sorted = DrawProjectSplit::sortSplits(splits,true); auto last = std::unique(sorted.begin(), sorted.end(), DrawProjectSplit::splitEqual); //duplicates to back sorted.erase(last, sorted.end()); //remove dupl splits std::vector<TopoDS_Edge> newEdges = DrawProjectSplit::splitEdges(faceEdges,sorted); if (newEdges.empty()) { Base::Console().Log("LOG - DVP::extractFaces - no newEdges\n"); return; } newEdges = DrawProjectSplit::removeDuplicateEdges(newEdges); //find all the wires in the pile of faceEdges EdgeWalker ew; ew.loadEdges(newEdges); bool success = ew.perform(); if (!success) { Base::Console().Warning("DVP::extractFaces - input is not planar graph. No face detection\n"); return; } std::vector<TopoDS_Wire> fw = ew.getResultNoDups(); std::vector<TopoDS_Wire> sortedWires = ew.sortStrip(fw,true); std::vector<TopoDS_Wire>::iterator itWire = sortedWires.begin(); for (; itWire != sortedWires.end(); itWire++) { //version 1: 1 wire/face - no voids in face TechDrawGeometry::Face* f = new TechDrawGeometry::Face(); const TopoDS_Wire& wire = (*itWire); TechDrawGeometry::Wire* w = new TechDrawGeometry::Wire(wire); f->wires.push_back(w); geometryObject->addFaceGeom(f); } }
App::DocumentObjectExecReturn *DrawViewDetail::execute(void) { if (!keepUpdated()) { return App::DocumentObject::StdReturn; } App::DocumentObject* baseObj = BaseView.getValue(); if (!baseObj) { Base::Console().Log("INFO - DVD::execute - No BaseView - creation?\n"); return DrawView::execute(); } DrawViewPart* dvp = nullptr; if (!baseObj->getTypeId().isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) { return new App::DocumentObjectExecReturn("BaseView object is not a DrawViewPart object"); } else { dvp = static_cast<DrawViewPart*>(baseObj); } TopoDS_Shape shape = dvp->getSourceShapeFused(); if (shape.IsNull()) { return new App::DocumentObjectExecReturn("DVD - Linked shape object is invalid"); } Base::Vector3d anchor = AnchorPoint.getValue(); //this is a 2D point (in unrotated coords) Base::Vector3d dirDetail = dvp->Direction.getValue(); double shapeRotate = dvp->Rotation.getValue(); //degrees CW? if (dvp->isDerivedFrom(TechDraw::DrawProjGroupItem::getClassTypeId())) { DrawProjGroupItem* dpgi= static_cast<TechDraw::DrawProjGroupItem*>(dvp); shapeRotate += dpgi->getRotateAngle() * 180.0/M_PI; // to degrees from radians } double radius = getFudgeRadius(); double scale = getScale(); BRepBuilderAPI_Copy BuilderCopy(shape); TopoDS_Shape myShape = BuilderCopy.Shape(); //rotate the copied shape to match orientation of BaseView and center it on origin gp_Pnt gpCenter = TechDrawGeometry::findCentroid(myShape, //centre of unrotated shape dirDetail); Base::Vector3d shapeCenter = Base::Vector3d(gpCenter.X(),gpCenter.Y(),gpCenter.Z()); gp_Ax2 viewAxis = getViewAxis(shapeCenter, dirDetail, false); myShape = TechDrawGeometry::rotateShape(myShape, //rotate to match Base shape viewAxis, -shapeRotate); myShape = TechDrawGeometry::moveShape(myShape, //centre on origin -shapeCenter); // shapeCenter = Base::Vector3d(0.0,0.0,0.0); gpCenter = TechDrawGeometry::findCentroid(myShape, dirDetail); shapeCenter = Base::Vector3d(gpCenter.X(),gpCenter.Y(),gpCenter.Z()); Bnd_Box bbxSource; bbxSource.SetGap(0.0); BRepBndLib::Add(myShape, bbxSource); double diag = sqrt(bbxSource.SquareExtent()); Base::Vector3d extentFar,extentNear; extentFar = shapeCenter + dirDetail * diag; extentNear = shapeCenter + dirDetail * diag * -1.0; anchor = Base::Vector3d(anchor.x,anchor.y, 0.0); viewAxis = getViewAxis(shapeCenter, dirDetail, false); //change view axis to (0,0,0) Base::Vector3d offsetCenter3D = DrawUtil::toR3(viewAxis, anchor); //displacement in R3 Base::Vector3d stdZ(0.0,0.0,1.0); if (DrawUtil::checkParallel(dirDetail,stdZ)) { extentNear = extentNear + offsetCenter3D; } else { extentNear = extentNear - offsetCenter3D; } gp_Dir cylDir(dirDetail.x,dirDetail.y,dirDetail.z); gp_Pnt cylPoint(extentNear.x,extentNear.y,extentNear.z); gp_Ax2 cylAxis(cylPoint,cylDir); BRepPrimAPI_MakeCylinder mkCyl(cylAxis, radius, (extentFar-extentNear).Length()); TopoDS_Shell sh = mkCyl.Cylinder().Shell(); BRepBuilderAPI_MakeSolid mkSol(sh); TopoDS_Solid tool = mkSol.Solid(); BRepAlgoAPI_Common mkCommon(myShape,tool); if (!mkCommon.IsDone()) { Base::Console().Log("DVD::execute - mkCommon not done\n"); return new App::DocumentObjectExecReturn("DVD::execute - mkCommon not done"); } if (mkCommon.Shape().IsNull()) { Base::Console().Log("DVD::execute - mkCommon.Shape is Null\n"); return new App::DocumentObjectExecReturn("DVD::execute - mkCommon.Shape is Null"); } //Did we get a solid? TopExp_Explorer xp; xp.Init(mkCommon.Shape(),TopAbs_SOLID); if (!(xp.More() == Standard_True)) { Base::Console().Message("DVD::execute - mkCommon.Shape is not a solid!\n"); } TopoDS_Shape detail = mkCommon.Shape(); Bnd_Box testBox; testBox.SetGap(0.0); BRepBndLib::Add(detail, testBox); if (testBox.IsVoid()) { Base::Console().Message("DrawViewDetail - detail area contains no geometry\n"); return new App::DocumentObjectExecReturn("DVDetail - detail area contains no geometry"); } //for debugging show compound instead of common // BRep_Builder builder; // TopoDS_Compound Comp; // builder.MakeCompound(Comp); // builder.Add(Comp, tool); // builder.Add(Comp, myShape); gp_Pnt inputCenter; try { inputCenter = TechDrawGeometry::findCentroid(tool, Direction.getValue()); TopoDS_Shape mirroredShape = TechDrawGeometry::mirrorShape(detail, inputCenter, scale); viewAxis = getViewAxis(Base::Vector3d(inputCenter.X(),inputCenter.Y(),inputCenter.Z()),Direction.getValue()); if (!DrawUtil::fpCompare(Rotation.getValue(),0.0)) { mirroredShape = TechDrawGeometry::rotateShape(mirroredShape, viewAxis, Rotation.getValue()); //degrees cw? } geometryObject = buildGeometryObject(mirroredShape,viewAxis); geometryObject->pruneVertexGeom(Base::Vector3d(0.0,0.0,0.0),Radius.getValue() * scale); //remove vertices beyond clipradius #if MOD_TECHDRAW_HANDLE_FACES if (handleFaces()) { try { extractFaces(); } catch (Standard_Failure& e4) { Base::Console().Log("LOG - DVD::execute - extractFaces failed for %s - %s **\n",getNameInDocument(),e4.GetMessageString()); return new App::DocumentObjectExecReturn(e4.GetMessageString()); } } #endif //#if MOD_TECHDRAW_HANDLE_FACES } catch (Standard_Failure& e1) { Base::Console().Log("LOG - DVD::execute - base shape failed for %s - %s **\n",getNameInDocument(),e1.GetMessageString()); return new App::DocumentObjectExecReturn(e1.GetMessageString()); } requestPaint(); dvp->requestPaint(); return App::DocumentObject::StdReturn; }
std::vector<TopoDS_Wire> EdgeWalker::sortStrip(std::vector<TopoDS_Wire> fw, bool includeBiggest) { std::vector<TopoDS_Wire> sortedWires = sortWiresBySize(fw,false); //biggest 1st if (!sortedWires.size()) { Base::Console().Log("INFO - DVP::extractFaces - no sorted Wires!\n"); return sortedWires; // might happen in the middle of changes? } //find the largest wire (OuterWire of graph) using bbox Bnd_Box bigBox; if (sortedWires.size() && !sortedWires.front().IsNull()) { BRepBndLib::Add(sortedWires.front(), bigBox); bigBox.SetGap(0.0); } std::vector<std::size_t> toBeChecked; std::vector<TopoDS_Wire>::iterator it = sortedWires.begin() + 1; for (; it != sortedWires.end(); it++) { if (!(*it).IsNull()) { Bnd_Box littleBox; BRepBndLib::Add((*it), littleBox); littleBox.SetGap(0.0); if (bigBox.SquareExtent() > littleBox.SquareExtent()) { break; } else { auto position = std::distance( sortedWires.begin(), it ); //get an index from iterator toBeChecked.push_back(position); } } } //unfortuneately, faces can have same bbox, but not be same size. need to weed out biggest if (toBeChecked.size() == 0) { //nobody had as big a bbox as first element of sortedWires if (!includeBiggest) { sortedWires.erase(sortedWires.begin()); } } else if (toBeChecked.size() > 0) { BRepBuilderAPI_MakeFace mkFace(sortedWires.front()); const TopoDS_Face& face = mkFace.Face(); GProp_GProps props; BRepGProp::SurfaceProperties(face, props); double bigArea = props.Mass(); unsigned int bigIndex = 0; for (unsigned int idx = 0; idx < toBeChecked.size(); idx++) { int iCheck = toBeChecked.at(idx); BRepBuilderAPI_MakeFace mkFace2(sortedWires.at(iCheck)); const TopoDS_Face& face2 = mkFace2.Face(); BRepGProp::SurfaceProperties(face2, props); double area = props.Mass(); if (area > bigArea) { bigArea = area; bigIndex = iCheck; } } if (bigIndex == 0) { //first wire is the biggest if (!includeBiggest) { sortedWires.erase(sortedWires.begin()); } } else { //first wire is not the biggest TopoDS_Wire bigWire = *(sortedWires.begin() + bigIndex); sortedWires.erase(sortedWires.begin() + bigIndex); if (includeBiggest) { sortedWires.insert(sortedWires.begin(),bigWire); //doesn't happen often } } } return sortedWires; }
void ViewProviderPartExt::updateVisual(const TopoDS_Shape& inputShape) { // Clear selection Gui::SoSelectionElementAction action(Gui::SoSelectionElementAction::None); action.apply(this->faceset); action.apply(this->lineset); action.apply(this->nodeset); TopoDS_Shape cShape(inputShape); if (cShape.IsNull()) { coords ->point .setNum(0); norm ->vector .setNum(0); faceset ->coordIndex .setNum(0); faceset ->partIndex .setNum(0); lineset ->coordIndex .setNum(0); VisualTouched = false; return; } // time measurement and book keeping Base::TimeInfo start_time; int nbrTriangles=0,nbrNodes=0,nbrNorms=0,nbrFaces=0,nbrEdges=0,nbrLines=0; std::set<int> faceEdges; try { // calculating the deflection value Bnd_Box bounds; BRepBndLib::Add(cShape, bounds); bounds.SetGap(0.0); Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue(); // create or use the mesh on the data structure BRepMesh_IncrementalMesh myMesh(cShape,deflection); // We must reset the location here because the transformation data // are set in the placement property TopLoc_Location aLoc; cShape.Location(aLoc); // count triangles and nodes in the mesh TopExp_Explorer Ex; for (Ex.Init(cShape,TopAbs_FACE);Ex.More();Ex.Next()) { Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc); // Note: we must also count empty faces if (!mesh.IsNull()) { nbrTriangles += mesh->NbTriangles(); nbrNodes += mesh->NbNodes(); nbrNorms += mesh->NbNodes(); } TopExp_Explorer xp; for (xp.Init(Ex.Current(),TopAbs_EDGE);xp.More();xp.Next()) faceEdges.insert(xp.Current().HashCode(INT_MAX)); nbrFaces++; } // get an indexed map of edges TopTools_IndexedMapOfShape M; TopExp::MapShapes(cShape, TopAbs_EDGE, M); std::set<int> edgeIdxSet; std::vector<int32_t> indxVector; std::vector<int32_t> edgeVector; // count and index the edges for (int i=1; i <= M.Extent(); i++) { edgeIdxSet.insert(i); nbrEdges++; const TopoDS_Edge& aEdge = TopoDS::Edge(M(i)); TopLoc_Location aLoc; // handling of the free edge that are not associated to a face // Note: The assumption that if for an edge BRep_Tool::Polygon3D // returns a valid object is wrong. This e.g. happens for ruled // surfaces which gets created by two edges or wires. // So, we have to store the hashes of the edges associated to a face. // If the hash of a given edge is not in this list we know it's really // a free edge. int hash = aEdge.HashCode(INT_MAX); if (faceEdges.find(hash) == faceEdges.end()) { Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(aEdge, aLoc); if (!aPoly.IsNull()) { int nbNodesInEdge = aPoly->NbNodes(); nbrNodes += nbNodesInEdge; } } } // reserve some memory indxVector.reserve(nbrEdges*8); // handling of the vertices TopTools_IndexedMapOfShape V; TopExp::MapShapes(cShape, TopAbs_VERTEX, V); nbrNodes += V.Extent(); // create memory for the nodes and indexes coords ->point .setNum(nbrNodes); norm ->vector .setNum(nbrNorms); faceset ->coordIndex .setNum(nbrTriangles*4); faceset ->partIndex .setNum(nbrFaces); // get the raw memory for fast fill up SbVec3f* verts = coords ->point .startEditing(); SbVec3f* norms = norm ->vector .startEditing(); int32_t* index = faceset ->coordIndex .startEditing(); int32_t* parts = faceset ->partIndex .startEditing(); // preset the normal vector with null vector for (int i=0;i < nbrNorms;i++) norms[i]= SbVec3f(0.0,0.0,0.0); int ii = 0,FaceNodeOffset=0,FaceTriaOffset=0; for (Ex.Init(cShape, TopAbs_FACE); Ex.More(); Ex.Next(),ii++) { TopLoc_Location aLoc; const TopoDS_Face &actFace = TopoDS::Face(Ex.Current()); // get the mesh of the shape Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace,aLoc); if (mesh.IsNull()) continue; // getting the transformation of the shape/face gp_Trsf myTransf; Standard_Boolean identity = true; if (!aLoc.IsIdentity()) { identity = false; myTransf = aLoc.Transformation(); } // getting size of node and triangle array of this face int nbNodesInFace = mesh->NbNodes(); int nbTriInFace = mesh->NbTriangles(); // check orientation TopAbs_Orientation orient = actFace.Orientation(); // cycling through the poly mesh const Poly_Array1OfTriangle& Triangles = mesh->Triangles(); const TColgp_Array1OfPnt& Nodes = mesh->Nodes(); for (int g=1;g<=nbTriInFace;g++) { // Get the triangle Standard_Integer N1,N2,N3; Triangles(g).Get(N1,N2,N3); // change orientation of the triangle if the face is reversed if ( orient != TopAbs_FORWARD ) { Standard_Integer tmp = N1; N1 = N2; N2 = tmp; } // get the 3 points of this triangle gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3)); // transform the vertices to the place of the face if (!identity) { V1.Transform(myTransf); V2.Transform(myTransf); V3.Transform(myTransf); } // calculating per vertex normals // Calculate triangle normal gp_Vec v1(V1.X(),V1.Y(),V1.Z()),v2(V2.X(),V2.Y(),V2.Z()),v3(V3.X(),V3.Y(),V3.Z()); gp_Vec Normal = (v2-v1)^(v3-v1); // add the triangle normal to the vertex normal for all points of this triangle norms[FaceNodeOffset+N1-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); norms[FaceNodeOffset+N2-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); norms[FaceNodeOffset+N3-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); // set the vertices verts[FaceNodeOffset+N1-1].setValue((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z())); verts[FaceNodeOffset+N2-1].setValue((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z())); verts[FaceNodeOffset+N3-1].setValue((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z())); // set the index vector with the 3 point indexes and the end delimiter index[FaceTriaOffset*4+4*(g-1)] = FaceNodeOffset+N1-1; index[FaceTriaOffset*4+4*(g-1)+1] = FaceNodeOffset+N2-1; index[FaceTriaOffset*4+4*(g-1)+2] = FaceNodeOffset+N3-1; index[FaceTriaOffset*4+4*(g-1)+3] = SO_END_FACE_INDEX; } parts[ii] = nbTriInFace; // new part // handling the edges lying on this face TopExp_Explorer Exp; for(Exp.Init(actFace,TopAbs_EDGE);Exp.More();Exp.Next()) { const TopoDS_Edge &actEdge = TopoDS::Edge(Exp.Current()); // get the overall index of this edge int idx = M.FindIndex(actEdge); edgeVector.push_back((int32_t)idx-1); // already processed this index ? if (edgeIdxSet.find(idx)!=edgeIdxSet.end()) { // this holds the indices of the edge's triangulation to the current polygon Handle(Poly_PolygonOnTriangulation) aPoly = BRep_Tool::PolygonOnTriangulation(actEdge, mesh, aLoc); if (aPoly.IsNull()) continue; // polygon does not exist // getting the indexes of the edge polygon const TColStd_Array1OfInteger& indices = aPoly->Nodes(); for (Standard_Integer i=indices.Lower();i <= indices.Upper();i++) { int inx = indices(i); indxVector.push_back(FaceNodeOffset+inx-1); // usually the coordinates for this edge are already set by the // triangles of the face this edge belongs to. However, there are // rare cases where some points are only referenced by the polygon // but not by any triangle. Thus, we must apply the coordinates to // make sure that everything is properly set. gp_Pnt p(Nodes(inx)); if (!identity) p.Transform(myTransf); verts[FaceNodeOffset+inx-1].setValue((float)(p.X()),(float)(p.Y()),(float)(p.Z())); } indxVector.push_back(-1); // remove the handled edge index from the set edgeIdxSet.erase(idx); } } edgeVector.push_back(-1); // counting up the per Face offsets FaceNodeOffset += nbNodesInFace; FaceTriaOffset += nbTriInFace; } // handling of the free edges for (int i=1; i <= M.Extent(); i++) { const TopoDS_Edge& aEdge = TopoDS::Edge(M(i)); Standard_Boolean identity = true; gp_Trsf myTransf; TopLoc_Location aLoc; // handling of the free edge that are not associated to a face int hash = aEdge.HashCode(INT_MAX); if (faceEdges.find(hash) == faceEdges.end()) { Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(aEdge, aLoc); if (!aPoly.IsNull()) { if (!aLoc.IsIdentity()) { identity = false; myTransf = aLoc.Transformation(); } const TColgp_Array1OfPnt& aNodes = aPoly->Nodes(); int nbNodesInEdge = aPoly->NbNodes(); gp_Pnt pnt; for (Standard_Integer j=1;j <= nbNodesInEdge;j++) { pnt = aNodes(j); if (!identity) pnt.Transform(myTransf); verts[FaceNodeOffset+j-1].setValue((float)(pnt.X()),(float)(pnt.Y()),(float)(pnt.Z())); indxVector.push_back(FaceNodeOffset+j-1); } indxVector.push_back(-1); FaceNodeOffset += nbNodesInEdge; } } } nodeset->startIndex.setValue(FaceNodeOffset); for (int i=0; i<V.Extent(); i++) { const TopoDS_Vertex& aVertex = TopoDS::Vertex(V(i+1)); gp_Pnt pnt = BRep_Tool::Pnt(aVertex); verts[FaceNodeOffset+i].setValue((float)(pnt.X()),(float)(pnt.Y()),(float)(pnt.Z())); } // normalize all normals for (int i = 0; i< nbrNorms ;i++) norms[i].normalize(); // preset the index vector size nbrLines = indxVector.size(); lineset ->coordIndex .setNum(nbrLines); int32_t* lines = lineset ->coordIndex .startEditing(); int l=0; for (std::vector<int32_t>::const_iterator it=indxVector.begin();it!=indxVector.end();++it,l++) lines[l] = *it; // end the editing of the nodes coords ->point .finishEditing(); norm ->vector .finishEditing(); faceset ->coordIndex .finishEditing(); faceset ->partIndex .finishEditing(); lineset ->coordIndex .finishEditing(); } catch (...) { Base::Console().Error("Cannot compute Inventor representation for the shape of %s.\n",pcObject->getNameInDocument()); } // printing some informations Base::Console().Log("ViewProvider update time: %f s\n",Base::TimeInfo::diffTimeF(start_time,Base::TimeInfo())); Base::Console().Log("Shape tria info: Faces:%d Edges:%d Nodes:%d Triangles:%d IdxVec:%d\n",nbrFaces,nbrEdges,nbrNodes,nbrTriangles,nbrLines); VisualTouched = false; }