Py::Object TopoShapeFacePy::getCenterOfMass(void) const { GProp_GProps props; BRepGProp::SurfaceProperties(getTopoShapePtr()->getShape(), props); gp_Pnt c = props.CentreOfMass(); return Py::Vector(Base::Vector3d(c.X(),c.Y(),c.Z())); }
Py::Object TopoShapeEdgePy::getCenterOfMass(void) const { GProp_GProps props; BRepGProp::LinearProperties(getTopoShapePtr()->_Shape, props); gp_Pnt c = props.CentreOfMass(); return Py::Vector(Base::Vector3d(c.X(),c.Y(),c.Z())); }
Py::Object TopoShapeSolidPy::getMass(void) const { GProp_GProps props; BRepGProp::VolumeProperties(getTopoShapePtr()->_Shape, props); double c = props.Mass(); return Py::Float(c); }
double ProfileBased::getReversedAngle(const Base::Vector3d &b, const Base::Vector3d &v) { try { Part::Feature* obj = getVerifiedObject(); TopoDS_Shape sketchshape = getVerifiedFace(); // get centre of gravity of the sketch face GProp_GProps props; BRepGProp::SurfaceProperties(sketchshape, props); gp_Pnt cog = props.CentreOfMass(); Base::Vector3d p_cog(cog.X(), cog.Y(), cog.Z()); // get direction to cog from its projection on the revolve axis Base::Vector3d perp_dir = p_cog - p_cog.Perpendicular(b, v); // get cross product of projection direction with revolve axis direction Base::Vector3d cross = v % perp_dir; // get sketch vector pointing away from support material Base::Placement SketchPos = obj->Placement.getValue(); Base::Rotation SketchOrientation = SketchPos.getRotation(); Base::Vector3d SketchNormal(0,0,1); SketchOrientation.multVec(SketchNormal,SketchNormal); return SketchNormal * cross; } catch (...) { return Reversed.getValue() ? 1 : 0; } }
Py::Object TopoShapeFacePy::getMass(void) const { GProp_GProps props; BRepGProp::SurfaceProperties(getTopoShapePtr()->getShape(), props); double c = props.Mass(); return Py::Float(c); }
Py::Dict TopoShapeFacePy::getPrincipalProperties(void) const { GProp_GProps props; BRepGProp::SurfaceProperties(getTopoShapePtr()->getShape(), props); GProp_PrincipalProps pprops = props.PrincipalProperties(); Py::Dict dict; dict.setItem("SymmetryAxis", Py::Boolean(pprops.HasSymmetryAxis() ? true : false)); dict.setItem("SymmetryPoint", Py::Boolean(pprops.HasSymmetryPoint() ? true : false)); Standard_Real lx,ly,lz; pprops.Moments(lx,ly,lz); Py::Tuple tuple(3); tuple.setItem(0, Py::Float(lx)); tuple.setItem(1, Py::Float(ly)); tuple.setItem(2, Py::Float(lz)); dict.setItem("Moments",tuple); dict.setItem("FirstAxisOfInertia",Py::Vector(Base::convertTo <Base::Vector3d>(pprops.FirstAxisOfInertia()))); dict.setItem("SecondAxisOfInertia",Py::Vector(Base::convertTo <Base::Vector3d>(pprops.SecondAxisOfInertia()))); dict.setItem("ThirdAxisOfInertia",Py::Vector(Base::convertTo <Base::Vector3d>(pprops.ThirdAxisOfInertia()))); Standard_Real Rxx,Ryy,Rzz; pprops.RadiusOfGyration(Rxx,Ryy,Rzz); Py::Tuple rog(3); rog.setItem(0, Py::Float(Rxx)); rog.setItem(1, Py::Float(Ryy)); rog.setItem(2, Py::Float(Rzz)); dict.setItem("RadiusOfGyration",rog); return dict; }
//======================================================================= //function : ShapeToDouble //purpose : used by CompareShapes::operator() //======================================================================= std::pair<double, double> GEOMUtils::ShapeToDouble (const TopoDS_Shape& S, bool isOldSorting) { // Computing of CentreOfMass gp_Pnt GPoint; double Len; if (S.ShapeType() == TopAbs_VERTEX) { GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S)); Len = (double)S.Orientation(); } else { GProp_GProps GPr; // BEGIN: fix for Mantis issue 0020842 if (isOldSorting) { BRepGProp::LinearProperties(S, GPr); } else { if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) { BRepGProp::LinearProperties(S, GPr); } else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) { BRepGProp::SurfaceProperties(S, GPr); } else { BRepGProp::VolumeProperties(S, GPr); } } // END: fix for Mantis issue 0020842 GPoint = GPr.CentreOfMass(); Len = GPr.Mass(); } double dMidXYZ = GPoint.X() * 999.0 + GPoint.Y() * 99.0 + GPoint.Z() * 0.9; return std::make_pair(dMidXYZ, Len); }
//------------------------------------------------------------------------- // Purpose : Returns the center of the Surface mass // //------------------------------------------------------------------------- CubitVector OCCSurface::center_point() { GProp_GProps myProps; BRepGProp::SurfaceProperties(*myTopoDSFace, myProps); gp_Pnt pt = myProps.CentreOfMass(); CubitVector v(pt.X(),pt.Y(), pt.Z()); return v; }
void CShape::CalculateVolumeAndCentre() { GProp_GProps System; BRepGProp::VolumeProperties(m_shape, System); m_volume = System.Mass(); m_centre_of_mass = System.CentreOfMass(); m_volume_found = true; }
// Returns the surface area of this fuselage double CCPACSFuselage::GetSurfaceArea(void) { const TopoDS_Shape& fusedSegments = GetLoft()->Shape(); // Calculate surface area GProp_GProps System; BRepGProp::SurfaceProperties(fusedSegments, System); double myArea = System.Mass(); return myArea; }
// Returns the volume of this fuselage double CCPACSFuselage::GetVolume(void) { const TopoDS_Shape& fusedSegments = GetLoft()->Shape(); // Calculate volume GProp_GProps System; BRepGProp::VolumeProperties(fusedSegments, System); double myVolume = System.Mass(); return myVolume; }
OCCStruct3d OCCFace::centreOfMass() { OCCStruct3d ret; GProp_GProps prop; BRepGProp::SurfaceProperties(this->getShape(), prop); gp_Pnt cg = prop.CentreOfMass(); ret.x = cg.X(); ret.y = cg.Y(); ret.z = cg.Z(); return ret; }
//======================================================================= //function : GetPosition //purpose : //======================================================================= gp_Ax3 GEOMUtils::GetPosition (const TopoDS_Shape& theShape) { gp_Ax3 aResult; if (theShape.IsNull()) return aResult; // Axes aResult.Transform(theShape.Location().Transformation()); if (theShape.ShapeType() == TopAbs_FACE) { Handle(Geom_Surface) aGS = BRep_Tool::Surface(TopoDS::Face(theShape)); if (!aGS.IsNull() && aGS->IsKind(STANDARD_TYPE(Geom_Plane))) { Handle(Geom_Plane) aGPlane = Handle(Geom_Plane)::DownCast(aGS); gp_Pln aPln = aGPlane->Pln(); aResult = aPln.Position(); // In case of reverse orinetation of the face invert the plane normal // (the face's normal does not mathc the plane's normal in this case) if(theShape.Orientation() == TopAbs_REVERSED) { gp_Dir Vx = aResult.XDirection(); gp_Dir N = aResult.Direction().Mirrored(Vx); gp_Pnt P = aResult.Location(); aResult = gp_Ax3(P, N, Vx); } } } // Origin gp_Pnt aPnt; TopAbs_ShapeEnum aShType = theShape.ShapeType(); if (aShType == TopAbs_VERTEX) { aPnt = BRep_Tool::Pnt(TopoDS::Vertex(theShape)); } else { if (aShType == TopAbs_COMPOUND) { aShType = GetTypeOfSimplePart(theShape); } GProp_GProps aSystem; if (aShType == TopAbs_EDGE || aShType == TopAbs_WIRE) BRepGProp::LinearProperties(theShape, aSystem); else if (aShType == TopAbs_FACE || aShType == TopAbs_SHELL) BRepGProp::SurfaceProperties(theShape, aSystem); else BRepGProp::VolumeProperties(theShape, aSystem); aPnt = aSystem.CentreOfMass(); } aResult.SetLocation(aPnt); return aResult; }
Py::Object TopoShapeFacePy::getStaticMoments(void) const { GProp_GProps props; BRepGProp::SurfaceProperties(getTopoShapePtr()->getShape(), props); Standard_Real lx,ly,lz; props.StaticMoments(lx,ly,lz); Py::Tuple tuple(3); tuple.setItem(0, Py::Float(lx)); tuple.setItem(1, Py::Float(ly)); tuple.setItem(2, Py::Float(lz)); return tuple; }
DVec OCCFace::inertia() { DVec ret; GProp_GProps prop; BRepGProp::SurfaceProperties(this->getShape(), prop); gp_Mat mat = prop.MatrixOfInertia(); ret.push_back(mat(1,1)); // Ixx ret.push_back(mat(2,2)); // Iyy ret.push_back(mat(3,3)); // Izz ret.push_back(mat(1,2)); // Ixy ret.push_back(mat(1,3)); // Ixz ret.push_back(mat(2,3)); // Iyz return ret; }
Py::Object TopoShapeFacePy::getMatrixOfInertia(void) const { GProp_GProps props; BRepGProp::SurfaceProperties(getTopoShapePtr()->getShape(), props); gp_Mat m = props.MatrixOfInertia(); Base::Matrix4D mat; for (int i=0; i<3; i++) { for (int j=0; j<3; j++) { mat[i][j] = m(i+1,j+1); } } return Py::Matrix(mat); }
TEST(BRepGPropTestSuite, testComputeBoxVolume) { // create a box, mixing integers and floats BRepPrimAPI_MakeBox my_box(10.,10.,10.); my_box.Build(); ASSERT_TRUE(my_box.IsDone()); // compute shape properties GProp_GProps prop; // a 10*10*10 cube should have a volume of 1000 BRepGProp::VolumeProperties(my_box.Shape(), prop); ASSERT_GT(prop.Mass(),1000.-Precision::Confusion()); ASSERT_LT(prop.Mass(),1001.+Precision::Confusion()); }
TEST(BRepGPropTestSuite, testComputeBoxSurface) { // create a box, mixing integers and floats BRepPrimAPI_MakeBox my_box(10.,10.,10.); my_box.Build(); ASSERT_TRUE(my_box.IsDone()); // compute shape properties GProp_GProps prop; // the surface should be 6 faces*10*10=600 BRepGProp::SurfaceProperties(my_box.Shape(), prop); ASSERT_GT(prop.Mass(),600.-Precision::Confusion()); ASSERT_LT(prop.Mass(),600.+Precision::Confusion()); }
TEST(BRepGPropTestSuite, testComputeSphereVolume) { // create a box, mixing integers and floats BRepPrimAPI_MakeSphere sphere(20.); sphere.Build(); ASSERT_TRUE(sphere.IsDone()); // compute shape properties GProp_GProps prop; // a sphere with a radius of 20 should have a volume of // V = 4/3*pi*20*20*20 = 33510.321638291127 BRepGProp::VolumeProperties(sphere.Shape(), prop); ASSERT_GT(prop.Mass(),33510.321638291127-Precision::Confusion()); ASSERT_LT(prop.Mass(),33510.321638291127+Precision::Confusion()); }
int main(int argc, char **argv){ TopoDS_Shape shape; BRep_Builder builder; GProp_GProps prop; if (argc < 2) { std::cerr << "Usage: computeSurface file.brep" << std::endl; exit(1); } BRepTools::Read(shape, argv[1], builder); BRepGProp::SurfaceProperties(shape, prop); std::cout << "Total surface of all shapes: " << prop.Mass() << std::endl; return 0; }
bool DrawUtil::isZeroEdge(TopoDS_Edge e) { TopoDS_Vertex vStart = TopExp::FirstVertex(e); TopoDS_Vertex vEnd = TopExp::LastVertex(e); bool result = isSamePoint(vStart,vEnd); if (result) { //closed edge will have same V's but non-zero length GProp_GProps props; BRepGProp::LinearProperties(e, props); double len = props.Mass(); if (len > Precision::Confusion()) { result = false; } } return result; }
const std::list<gp_Trsf> Scaled::getTransformations(const std::vector<App::DocumentObject*> originals) { double factor = Factor.getValue(); if (factor < Precision::Confusion()) throw Base::Exception("Scaling factor too small"); int occurrences = Occurrences.getValue(); if (occurrences < 2) throw Base::Exception("At least two occurrences required"); double f = (factor - 1.0) / double(occurrences - 1); // Find centre of gravity of first original // FIXME: This method will NOT give the expected result for more than one original! Part::Feature* originalFeature = static_cast<Part::Feature*>(originals.front()); TopoDS_Shape original; if (originalFeature->getTypeId().isDerivedFrom(PartDesign::Additive::getClassTypeId())) { PartDesign::Additive* addFeature = static_cast<PartDesign::Additive*>(originalFeature); original = addFeature->AddShape.getShape()._Shape; } else if (originalFeature->getTypeId().isDerivedFrom(PartDesign::Subtractive::getClassTypeId())) { PartDesign::Subtractive* subFeature = static_cast<PartDesign::Subtractive*>(originalFeature); original = subFeature->SubShape.getShape()._Shape; } GProp_GProps props; BRepGProp::VolumeProperties(original,props); gp_Pnt cog = props.CentreOfMass(); // 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.SetScale(cog, 1.0 + double(i) * f); transformations.push_back(trans); } return transformations; }
Base::Vector3d Measurement::massCenter() const { int numRefs = References3D.getSize(); if(!numRefs || measureType == Invalid) throw Base::Exception("Measurement - massCenter - Invalid References3D Provided"); const std::vector<App::DocumentObject*> &objects = References3D.getValues(); const std::vector<std::string> &subElements = References3D.getSubValues(); GProp_GProps gprops = GProp_GProps(); if(measureType == Volumes) { // Iterate through edges and calculate each length std::vector<App::DocumentObject*>::const_iterator obj = objects.begin(); std::vector<std::string>::const_iterator subEl = subElements.begin(); for (;obj != objects.end(); ++obj, ++subEl) { //const Part::Feature *refObj = static_cast<const Part::Feature*>((*obj)); //const Part::TopoShape& refShape = refObj->Shape.getShape(); // Compute inertia properties GProp_GProps props = GProp_GProps(); BRepGProp::VolumeProperties(getShape((*obj), ""), props); gprops.Add(props); // Get inertia properties } //double mass = gprops.Mass(); gp_Pnt cog = gprops.CentreOfMass(); return Base::Vector3d(cog.X(), cog.Y(), cog.Z()); } else { throw Base::Exception("Measurement - massCenter - Invalid References3D Provided"); } }
//------------------------------------------------------------------------- // Purpose : Find centroid and volume for lumps and shells // // Special Notes : // // Author : Jane Hu // // Creation Date : 11/30/07 //------------------------------------------------------------------------- CubitStatus OCCBody::mass_properties( CubitVector& centroid, double& volume ) { if( myShells.size() == 0 && myLumps.size() == 0) return CUBIT_FAILURE; GProp_GProps myProps; TopoDS_Shape* pshape = myTopoDSShape; if(!pshape || pshape->IsNull())//single lump or shell or surface { DLIList<Lump*> lumps = this->lumps(); if (lumps.size() > 0) pshape = CAST_TO(lumps.get(), OCCLump)->get_TopoDS_Solid(); } if(!pshape || pshape->IsNull()) return CUBIT_FAILURE; BRepGProp::VolumeProperties(*pshape, myProps); volume = myProps.Mass(); gp_Pnt pt = myProps.CentreOfMass(); centroid.set(pt.X(), pt.Y(), pt.Z()); return CUBIT_SUCCESS; }
PyObject* TopoShapeSolidPy::getRadiusOfGyration(PyObject *args) { PyObject *p,*d; if (!PyArg_ParseTuple(args, "O!O!",&Base::VectorPy::Type,&p ,&Base::VectorPy::Type,&d)) return 0; Base::Vector3d pnt = Py::Vector(p,false).toVector(); Base::Vector3d dir = Py::Vector(d,false).toVector(); try { GProp_GProps props; BRepGProp::VolumeProperties(getTopoShapePtr()->getShape(), props); double r = props.RadiusOfGyration(gp_Ax1(Base::convertTo<gp_Pnt>(pnt), Base::convertTo<gp_Dir>(dir))); return PyFloat_FromDouble(r); } catch (Standard_Failure& e) { PyErr_SetString(PartExceptionOCCError, e.GetMessageString()); return 0; } }
bool Revolution::suggestReversed(void) { try { updateAxis(); Part::Part2DObject* sketch = getVerifiedSketch(); std::vector<TopoDS_Wire> wires = getSketchWires(); TopoDS_Shape sketchshape = makeFace(wires); Base::Vector3d b = Base.getValue(); Base::Vector3d v = Axis.getValue(); // get centre of gravity of the sketch face GProp_GProps props; BRepGProp::SurfaceProperties(sketchshape, props); gp_Pnt cog = props.CentreOfMass(); Base::Vector3d p_cog(cog.X(), cog.Y(), cog.Z()); // get direction to cog from its projection on the revolve axis Base::Vector3d perp_dir = p_cog - p_cog.Perpendicular(b, v); // get cross product of projection direction with revolve axis direction Base::Vector3d cross = v % perp_dir; // get sketch vector pointing away from support material Base::Placement SketchPos = sketch->Placement.getValue(); Base::Rotation SketchOrientation = SketchPos.getRotation(); Base::Vector3d SketchNormal(0,0,1); SketchOrientation.multVec(SketchNormal,SketchNormal); // simply convert double to float Base::Vector3d norm(SketchNormal.x, SketchNormal.y, SketchNormal.z); // return true if the angle between norm and cross is obtuse return norm * cross < 0.f; } catch (...) { return Reversed.getValue(); } }
//======================================================================= //function : PointProperties //purpose : //======================================================================= void PointProperties(const TopoDS_Shape& aS, GProp_GProps& aGProps) { Standard_Integer i, aNbS; Standard_Real aDensity; gp_Pnt aPX; TopTools_IndexedMapOfShape aMS; // aDensity=1.; // TopExp::MapShapes(aS, TopAbs_VERTEX, aMS); aNbS=aMS.Extent(); for (i=1; i<=aNbS; ++i) { GEOMAlgo_GProps aGPropsX; // const TopoDS_Vertex& aVX=*((TopoDS_Vertex*)&aMS(i)); aPX=BRep_Tool::Pnt(aVX); aGPropsX.SetMass(1.); aGPropsX.SetCG(aPX); aGProps.Add(aGPropsX, aDensity); } }
bool ChCascadeDoc::GetVolumeProperties(const TopoDS_Shape& mshape, ///< pass the shape here const double density, ///< pass the density here ChVector<>& center_position, ///< get the position center, respect to shape pos. ChVector<>& inertiaXX, ///< get the inertia diagonal terms ChVector<>& inertiaXY, ///< get the inertia extradiagonal terms double& volume, ///< get the volume double& mass ///< get the mass ) { if (mshape.IsNull()) return false; GProp_GProps mprops; GProp_GProps vprops; BRepGProp::VolumeProperties(mshape,mprops); BRepGProp::VolumeProperties(mshape,vprops); mprops.Add(mprops, density); mass = mprops.Mass(); volume = vprops.Mass(); gp_Pnt G = mprops.CentreOfMass (); gp_Mat I = mprops.MatrixOfInertia(); center_position.x = G.X(); center_position.y = G.Y(); center_position.z = G.Z(); inertiaXX.x = I(1,1); inertiaXX.y = I(2,2); inertiaXX.z = I(3,3); inertiaXY.x = I(1,2); inertiaXY.y = I(1,3); inertiaXY.z = I(2,3); return true; }
//======================================================================= //function : Execute //purpose : //======================================================================= Standard_Integer GEOMImpl_RotateDriver::Execute(TFunction_Logbook& log) const { if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); if (aFunction.IsNull()) return 0; GEOMImpl_IRotate RI(aFunction); gp_Trsf aTrsf; gp_Pnt aCP, aP1, aP2; Standard_Integer aType = aFunction->GetType(); Handle(GEOM_Function) anOriginalFunction = RI.GetOriginal(); if (anOriginalFunction.IsNull()) return 0; TopoDS_Shape aShape, anOriginal = anOriginalFunction->GetValue(); if (anOriginal.IsNull()) return 0; if (aType == ROTATE || aType == ROTATE_COPY) { Handle(GEOM_Function) anAxis = RI.GetAxis(); if (anAxis.IsNull()) return 0; TopoDS_Shape A = anAxis->GetValue(); if (A.IsNull() || A.ShapeType() != TopAbs_EDGE) return 0; TopoDS_Edge anEdge = TopoDS::Edge(A); gp_Pnt aP1 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge)); gp_Pnt aP2 = BRep_Tool::Pnt(TopExp::LastVertex(anEdge)); gp_Dir aDir(gp_Vec(aP1, aP2)); gp_Ax1 anAx1(aP1, aDir); Standard_Real anAngle = RI.GetAngle(); if (fabs(anAngle) < Precision::Angular()) anAngle += 2*PI; // NPAL19665,19769 aTrsf.SetRotation(anAx1, anAngle); //NPAL18620: performance problem: multiple locations are accumulated // in shape and need a great time to process //BRepBuilderAPI_Transform aTransformation(anOriginal, aTrsf, Standard_False); //aShape = aTransformation.Shape(); TopLoc_Location aLocOrig = anOriginal.Location(); gp_Trsf aTrsfOrig = aLocOrig.Transformation(); //TopLoc_Location aLocRes (aTrsf * aTrsfOrig); // gp_Trsf::Multiply() has a bug aTrsfOrig.PreMultiply(aTrsf); TopLoc_Location aLocRes (aTrsfOrig); aShape = anOriginal.Located(aLocRes); } else if (aType == ROTATE_THREE_POINTS || aType == ROTATE_THREE_POINTS_COPY) { Handle(GEOM_Function) aCentPoint = RI.GetCentPoint(); Handle(GEOM_Function) aPoint1 = RI.GetPoint1(); Handle(GEOM_Function) aPoint2 = RI.GetPoint2(); if(aCentPoint.IsNull() || aPoint1.IsNull() || aPoint2.IsNull()) return 0; TopoDS_Shape aCV = aCentPoint->GetValue(); TopoDS_Shape aV1 = aPoint1->GetValue(); TopoDS_Shape aV2 = aPoint2->GetValue(); if(aCV.IsNull() || aCV.ShapeType() != TopAbs_VERTEX) return 0; if(aV1.IsNull() || aV1.ShapeType() != TopAbs_VERTEX) return 0; if(aV2.IsNull() || aV2.ShapeType() != TopAbs_VERTEX) return 0; aCP = BRep_Tool::Pnt(TopoDS::Vertex(aCV)); aP1 = BRep_Tool::Pnt(TopoDS::Vertex(aV1)); aP2 = BRep_Tool::Pnt(TopoDS::Vertex(aV2)); gp_Vec aVec1 (aCP, aP1); gp_Vec aVec2 (aCP, aP2); gp_Dir aDir (aVec1 ^ aVec2); gp_Ax1 anAx1 (aCP, aDir); Standard_Real anAngle = aVec1.Angle(aVec2); if (fabs(anAngle) < Precision::Angular()) anAngle += 2*PI; // NPAL19665 aTrsf.SetRotation(anAx1, anAngle); //NPAL18620: performance problem: multiple locations are accumulated // in shape and need a great time to process //BRepBuilderAPI_Transform aTransformation(anOriginal, aTrsf, Standard_False); //aShape = aTransformation.Shape(); TopLoc_Location aLocOrig = anOriginal.Location(); gp_Trsf aTrsfOrig = aLocOrig.Transformation(); //TopLoc_Location aLocRes (aTrsf * aTrsfOrig); // gp_Trsf::Multiply() has a bug aTrsfOrig.PreMultiply(aTrsf); TopLoc_Location aLocRes (aTrsfOrig); aShape = anOriginal.Located(aLocRes); } else if (aType == ROTATE_1D) { //Get direction Handle(GEOM_Function) anAxis = RI.GetAxis(); if(anAxis.IsNull()) return 0; TopoDS_Shape A = anAxis->GetValue(); if(A.IsNull() || A.ShapeType() != TopAbs_EDGE) return 0; TopoDS_Edge anEdge = TopoDS::Edge(A); gp_Pnt aP1 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge)); gp_Pnt aP2 = BRep_Tool::Pnt(TopExp::LastVertex(anEdge)); gp_Dir D(gp_Vec(aP1, aP2)); gp_Ax1 AX1(aP1, D); Standard_Integer nbtimes = RI.GetNbIter1(); Standard_Real angle = 360.0/nbtimes; TopoDS_Compound aCompound; BRep_Builder B; B.MakeCompound( aCompound ); TopLoc_Location aLocOrig = anOriginal.Location(); gp_Trsf aTrsfOrig = aLocOrig.Transformation(); for (int i = 0; i < nbtimes; i++ ) { if (i == 0) { // NPAL19665 B.Add(aCompound, anOriginal); } else { aTrsf.SetRotation(AX1, i*angle/* * PI180 */); //TopLoc_Location aLocRes (aTrsf * aTrsfOrig); // gp_Trsf::Multiply() has a bug gp_Trsf aTrsfNew (aTrsfOrig); aTrsfNew.PreMultiply(aTrsf); TopLoc_Location aLocRes (aTrsfNew); B.Add(aCompound, anOriginal.Located(aLocRes)); } //NPAL18620: performance problem: multiple locations are accumulated // in shape and need a great time to process //BRepBuilderAPI_Transform aBRepTransformation(anOriginal, aTrsf, Standard_False); //B.Add(aCompound, aBRepTransformation.Shape()); } aShape = aCompound; } else if (aType == ROTATE_2D) { //Get direction Handle(GEOM_Function) anAxis = RI.GetAxis(); if(anAxis.IsNull()) return 0; TopoDS_Shape A = anAxis->GetValue(); if(A.IsNull() || A.ShapeType() != TopAbs_EDGE) return 0; TopoDS_Edge anEdge = TopoDS::Edge(A); gp_Pnt aP1 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge)); gp_Pnt aP2 = BRep_Tool::Pnt(TopExp::LastVertex(anEdge)); gp_Dir D(gp_Vec(aP1, aP2)); gp_Ax1 AX1(aP1, D); gp_Trsf aTrsf1; gp_Trsf aTrsf2; gp_Trsf aTrsf3; gp_XYZ aDir2 = RI.GetDir2(); // can be set by previous execution if (aDir2.Modulus() < gp::Resolution()) { // Calculate direction as vector from the axis to the shape's center gp_Pnt P1; GProp_GProps System; if (anOriginal.ShapeType() == TopAbs_VERTEX) { P1 = BRep_Tool::Pnt(TopoDS::Vertex( anOriginal )); } else if ( anOriginal.ShapeType() == TopAbs_EDGE || anOriginal.ShapeType() == TopAbs_WIRE ) { BRepGProp::LinearProperties(anOriginal, System); P1 = System.CentreOfMass(); } else if ( anOriginal.ShapeType() == TopAbs_FACE || anOriginal.ShapeType() == TopAbs_SHELL ) { BRepGProp::SurfaceProperties(anOriginal, System); P1 = System.CentreOfMass(); } else { BRepGProp::VolumeProperties(anOriginal, System); P1 = System.CentreOfMass(); } Handle(Geom_Line) Line = new Geom_Line(AX1); GeomAPI_ProjectPointOnCurve aPrjTool( P1, Line ); gp_Pnt P2 = aPrjTool.NearestPoint(); if ( P1.IsEqual(P2, Precision::Confusion() ) ) return 0; aDir2 = gp_XYZ(P1.X()-P2.X(), P1.Y()-P2.Y(), P1.Z()-P2.Z()); // Attention: this abnormal action is done for good working of // TransformLikeOther(), used by RestoreSubShapes functionality RI.SetDir2(aDir2); } gp_Vec Vec (aDir2); Vec.Normalize(); gp_Vec elevVec(D); elevVec.Normalize(); Standard_Integer nbtimes2 = RI.GetNbIter2(); Standard_Integer nbtimes1 = RI.GetNbIter1(); Standard_Real step = RI.GetStep(); Standard_Real elevationstep = RI.GetElevationStep(); Standard_Real ang = RI.GetAngle(); TopLoc_Location aLocOrig = anOriginal.Location(); gp_Trsf aTrsfOrig = aLocOrig.Transformation(); gp_Vec aVec; TopoDS_Compound aCompound; BRep_Builder B; B.MakeCompound( aCompound ); Standard_Real DX, DY, DZ; for (int i = 0; i < nbtimes2; i++ ) { if (i != 0) { DX = i * step * Vec.X(); DY = i * step * Vec.Y(); DZ = i * step * Vec.Z(); aVec.SetCoord( DX, DY, DZ ); aTrsf1.SetTranslation(aVec); } for (int j = 0; j < nbtimes1; j++ ) { if (j == 0) { // NPAL19665 TopLoc_Location aLocRes (aTrsf1 * aTrsfOrig); B.Add(aCompound, anOriginal.Located(aLocRes)); } else { DX = j * elevationstep * elevVec.X(); DY = j * elevationstep * elevVec.Y(); DZ = j * elevationstep * elevVec.Z(); aVec.SetCoord( DX, DY, DZ ); aTrsf3.SetTranslation(aVec); aTrsf2.SetRotation(AX1, j*ang /* * PI180 */ ); //TopLoc_Location aLocRes (aTrsf2 * aTrsf1 * aTrsfOrig); // gp_Trsf::Multiply() has a bug gp_Trsf aTrsfNew (aTrsfOrig); aTrsfNew.PreMultiply(aTrsf1); aTrsfNew.PreMultiply(aTrsf2); aTrsfNew.PreMultiply(aTrsf3); TopLoc_Location aLocRes (aTrsfNew); B.Add(aCompound, anOriginal.Located(aLocRes)); } //NPAL18620: performance problem: multiple locations are accumulated // in shape and need a great time to process //BRepBuilderAPI_Transform aBRepTrsf1 (anOriginal, aTrsf1, Standard_False); //BRepBuilderAPI_Transform aBRepTrsf2 (aBRepTrsf1.Shape(), aTrsf2, Standard_False); //B.Add(aCompound, aBRepTrsf2.Shape()); } } aShape = aCompound; } else return 0; if (aShape.IsNull()) return 0; aFunction->SetValue(aShape); log.SetTouched(Label()); return 1; }
bool Constraint::getPoints(std::vector<Base::Vector3d> &points, std::vector<Base::Vector3d> &normals, int * scale) const { std::vector<App::DocumentObject*> Objects = References.getValues(); std::vector<std::string> SubElements = References.getSubValues(); // Extract geometry from References TopoDS_Shape sh; for (std::size_t i = 0; i < Objects.size(); i++) { App::DocumentObject* obj = Objects[i]; Part::Feature* feat = static_cast<Part::Feature*>(obj); const Part::TopoShape& toposhape = feat->Shape.getShape(); if (toposhape.isNull()) return false; sh = toposhape.getSubShape(SubElements[i].c_str()); if (sh.ShapeType() == TopAbs_VERTEX) { const TopoDS_Vertex& vertex = TopoDS::Vertex(sh); gp_Pnt p = BRep_Tool::Pnt(vertex); points.push_back(Base::Vector3d(p.X(), p.Y(), p.Z())); normals.push_back(NormalDirection.getValue()); //OvG: Scale by whole object mass in case of a vertex GProp_GProps props; BRepGProp::VolumeProperties(toposhape.getShape(), props); double lx = props.Mass(); *scale = this->calcDrawScaleFactor(sqrt(lx)*0.5); //OvG: setup draw scale for constraint } else if (sh.ShapeType() == TopAbs_EDGE) { BRepAdaptor_Curve curve(TopoDS::Edge(sh)); double fp = curve.FirstParameter(); double lp = curve.LastParameter(); GProp_GProps props; BRepGProp::LinearProperties(TopoDS::Edge(sh), props); double l = props.Mass(); // Create points with 10 units distance, but at least one at the beginning and end of the edge int steps; if (l >= 30) //OvG: Increase 10 units distance proportionately to l for larger objects. { *scale = this->calcDrawScaleFactor(l); //OvG: setup draw scale for constraint steps = (int)round(l / (10*( *scale))); steps = steps<3?3:steps; } else if (l >= 20) { steps = (int)round(l / 10); *scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint } else { steps = 1; *scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint } steps = steps>CONSTRAINTSTEPLIMIT?CONSTRAINTSTEPLIMIT:steps; //OvG: Place upper limit on number of steps double step = (lp - fp) / steps; for (int i = 0; i < steps + 1; i++) { gp_Pnt p = curve.Value(i * step); points.push_back(Base::Vector3d(p.X(), p.Y(), p.Z())); normals.push_back(NormalDirection.getValue()); } } else if (sh.ShapeType() == TopAbs_FACE) { TopoDS_Face face = TopoDS::Face(sh); // Surface boundaries BRepAdaptor_Surface surface(face); double ufp = surface.FirstUParameter(); double ulp = surface.LastUParameter(); double vfp = surface.FirstVParameter(); double vlp = surface.LastVParameter(); double l; double lv, lu; // Surface normals BRepGProp_Face props(face); gp_Vec normal; gp_Pnt center; // Get an estimate for the number of arrows by finding the average length of curves Handle(Adaptor3d_HSurface) hsurf; hsurf = new BRepAdaptor_HSurface(surface); Adaptor3d_IsoCurve isoc(hsurf); try { isoc.Load(GeomAbs_IsoU, ufp); l = GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion()); } catch (const Standard_Failure&) { gp_Pnt p1 = hsurf->Value(ufp, vfp); gp_Pnt p2 = hsurf->Value(ufp, vlp); l = p1.Distance(p2); } try { isoc.Load(GeomAbs_IsoU, ulp); lv = (l + GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion()))/2.0; } catch (const Standard_Failure&) { gp_Pnt p1 = hsurf->Value(ulp, vfp); gp_Pnt p2 = hsurf->Value(ulp, vlp); lv = (l + p1.Distance(p2))/2.0; } try { isoc.Load(GeomAbs_IsoV, vfp); l = GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion()); } catch (const Standard_Failure&) { gp_Pnt p1 = hsurf->Value(ufp, vfp); gp_Pnt p2 = hsurf->Value(ulp, vfp); l = p1.Distance(p2); } try { isoc.Load(GeomAbs_IsoV, vlp); lu = (l + GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion()))/2.0; } catch (const Standard_Failure&) { gp_Pnt p1 = hsurf->Value(ufp, vlp); gp_Pnt p2 = hsurf->Value(ulp, vlp); lu = (l + p1.Distance(p2))/2.0; } int stepsv; if (lv >= 30) //OvG: Increase 10 units distance proportionately to lv for larger objects. { *scale = this->calcDrawScaleFactor(lv,lu); //OvG: setup draw scale for constraint stepsv = (int)round(lv / (10*( *scale))); stepsv = stepsv<3?3:stepsv; } else if (lv >= 20.0) { stepsv = (int)round(lv / 10); *scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint } else { stepsv = 2; // Minimum of three arrows to ensure (as much as possible) that at least one is displayed *scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint } stepsv = stepsv>CONSTRAINTSTEPLIMIT?CONSTRAINTSTEPLIMIT:stepsv; //OvG: Place upper limit on number of steps int stepsu; if (lu >= 30) //OvG: Increase 10 units distance proportionately to lu for larger objects. { *scale = this->calcDrawScaleFactor(lv,lu); //OvG: setup draw scale for constraint stepsu = (int)round(lu / (10*( *scale))); stepsu = stepsu<3?3:stepsu; } else if (lu >= 20.0) { stepsu = (int)round(lu / 10); *scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint } else { stepsu = 2; *scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint } stepsu = stepsu>CONSTRAINTSTEPLIMIT?CONSTRAINTSTEPLIMIT:stepsu; //OvG: Place upper limit on number of steps double stepv = (vlp - vfp) / stepsv; double stepu = (ulp - ufp) / stepsu; // Create points and normals for (int i = 0; i < stepsv + 1; i++) { for (int j = 0; j < stepsu + 1; j++) { double v = vfp + i * stepv; double u = ufp + j * stepu; gp_Pnt p = surface.Value(u, v); BRepClass_FaceClassifier classifier(face, p, Precision::Confusion()); if (classifier.State() != TopAbs_OUT) { points.push_back(Base::Vector3d(p.X(), p.Y(), p.Z())); props.Normal(u, v,center,normal); normal.Normalize(); normals.push_back(Base::Vector3d(normal.X(), normal.Y(), normal.Z())); } } } } } return true; }