//======================================================================= //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); }
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())); }
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; } }
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; }
//------------------------------------------------------------------------- // 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; }
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; }
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; }
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; }
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: 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; }
const std::list<gp_Trsf> MultiTransform::getTransformations(const std::vector<App::DocumentObject*> originals) { std::vector<App::DocumentObject*> transFeatures = Transformations.getValues(); // 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::FeatureAddSub::getClassTypeId())) { PartDesign::FeatureAddSub* addFeature = static_cast<PartDesign::FeatureAddSub*>(originalFeature); if(addFeature->getAddSubType() == FeatureAddSub::Additive) original = addFeature->AddSubShape.getShape()._Shape; else original = addFeature->AddSubShape.getShape()._Shape; } GProp_GProps props; BRepGProp::VolumeProperties(original,props); gp_Pnt cog = props.CentreOfMass(); std::list<gp_Trsf> result; std::list<gp_Pnt> cogs; std::vector<App::DocumentObject*>::const_iterator f; for (f = transFeatures.begin(); f != transFeatures.end(); ++f) { if (!((*f)->getTypeId().isDerivedFrom(PartDesign::Transformed::getClassTypeId()))) throw Base::Exception("Transformation features must be subclasses of Transformed"); PartDesign::Transformed* transFeature = static_cast<PartDesign::Transformed*>(*f); std::list<gp_Trsf> newTransformations = transFeature->getTransformations(originals); if (result.empty()) { // First transformation Feature result = newTransformations; for (std::list<gp_Trsf>::const_iterator nt = newTransformations.begin(); nt != newTransformations.end(); ++nt) { cogs.push_back(cog.Transformed(*nt)); } } else { // Retain a copy of the first set of transformations for iterator ot // We can't iterate through result if we are also adding elements with push_back()! std::list<gp_Trsf> oldTransformations; result.swap(oldTransformations); // empty result to receive new transformations std::list<gp_Pnt> oldCogs; cogs.swap(oldCogs); // empty cogs to receive new cogs if ((*f)->getTypeId() == PartDesign::Scaled::getClassTypeId()) { // Diagonal method // Multiply every element in the old transformations' slices with the corresponding // element in the newTransformations. Example: // a11 a12 a13 a14 b1 a11*b1 a12*b1 a13*b1 a14*b1 // a21 a22 a23 a24 diag b2 = a21*b2 a22*b2 a23*b2 a24*b1 // a31 a23 a33 a34 b3 a31*b3 a23*b3 a33*b3 a34*b1 // In other words, the length of the result vector is equal to the length of the // oldTransformations vector if (oldTransformations.size() % newTransformations.size() != 0) throw Base::Exception("Number of occurrences must be a divisor of previous number of occurrences"); unsigned sliceLength = oldTransformations.size() / newTransformations.size(); std::list<gp_Trsf>::const_iterator ot = oldTransformations.begin(); std::list<gp_Pnt>::const_iterator oc = oldCogs.begin(); for (std::list<gp_Trsf>::const_iterator nt = newTransformations.begin(); nt != newTransformations.end(); ++nt) { for (unsigned s = 0; s < sliceLength; s++) { gp_Trsf trans; double factor = nt->ScaleFactor(); // extract scale factor if (factor > Precision::Confusion()) { trans.SetScale(*oc, factor); // recreate the scaled transformation to use the correct COG trans = trans * (*ot); cogs.push_back(*oc); // Scaling does not affect the COG } else { trans = (*nt) * (*ot); cogs.push_back(oc->Transformed(*nt)); } result.push_back(trans); ++ot; ++oc; } } } else { // Multiplication method: Combine the new transformations with the old ones. // All old transformations are multiplied with all new ones, so that the length of the // result vector is the length of the old and new transformations multiplied. // a11 a12 b1 a11*b1 a12*b1 a11*b2 a12*b2 a11*b3 a12*b3 // a21 a22 mul b2 = a21*b1 a22*b1 a21*b2 a22*b2 a21*b3 a22*b3 // b3 for (std::list<gp_Trsf>::const_iterator nt = newTransformations.begin(); nt != newTransformations.end(); ++nt) { std::list<gp_Pnt>::const_iterator oc = oldCogs.begin(); for (std::list<gp_Trsf>::const_iterator ot = oldTransformations.begin(); ot != oldTransformations.end(); ++ot) { result.push_back((*nt) * (*ot)); cogs.push_back(oc->Transformed(*nt)); ++oc; } } } // What about the Additive method: Take the last (set of) transformations and use them as // "originals" for the next transformationFeature, so that something similar to a sweep // for transformations could be put together? } } return result; }
//======================================================================= //function : SortShapes //purpose : //======================================================================= void GEOMUtils::SortShapes (TopTools_ListOfShape& SL, const Standard_Boolean isOldSorting) { #ifdef STD_SORT_ALGO std::vector<TopoDS_Shape> aShapesVec; aShapesVec.reserve(SL.Extent()); TopTools_ListIteratorOfListOfShape it (SL); for (; it.More(); it.Next()) { aShapesVec.push_back(it.Value()); } SL.Clear(); CompareShapes shComp (isOldSorting); std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp); //std::sort(aShapesVec.begin(), aShapesVec.end(), shComp); std::vector<TopoDS_Shape>::const_iterator anIter = aShapesVec.begin(); for (; anIter != aShapesVec.end(); ++anIter) { SL.Append(*anIter); } #else // old implementation Standard_Integer MaxShapes = SL.Extent(); TopTools_Array1OfShape aShapes (1,MaxShapes); TColStd_Array1OfInteger OrderInd(1,MaxShapes); TColStd_Array1OfReal MidXYZ (1,MaxShapes); //X,Y,Z; TColStd_Array1OfReal Length (1,MaxShapes); //X,Y,Z; // Computing of CentreOfMass Standard_Integer Index; GProp_GProps GPr; gp_Pnt GPoint; TopTools_ListIteratorOfListOfShape it(SL); for (Index=1; it.More(); Index++) { TopoDS_Shape S = it.Value(); SL.Remove( it ); // == it.Next() aShapes(Index) = S; OrderInd.SetValue (Index, Index); if (S.ShapeType() == TopAbs_VERTEX) { GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S )); Length.SetValue( Index, (Standard_Real) S.Orientation()); } else { // 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(); Length.SetValue(Index, GPr.Mass()); } MidXYZ.SetValue(Index, GPoint.X()*999.0 + GPoint.Y()*99.0 + GPoint.Z()*0.9); //cout << Index << " L: " << Length(Index) << "CG: " << MidXYZ(Index) << endl; } // Sorting Standard_Integer aTemp; Standard_Boolean exchange, Sort = Standard_True; Standard_Real tol = Precision::Confusion(); while (Sort) { Sort = Standard_False; for (Index=1; Index < MaxShapes; Index++) { exchange = Standard_False; Standard_Real dMidXYZ = MidXYZ(OrderInd(Index)) - MidXYZ(OrderInd(Index+1)); Standard_Real dLength = Length(OrderInd(Index)) - Length(OrderInd(Index+1)); if ( dMidXYZ >= tol ) { // cout << "MidXYZ: " << MidXYZ(OrderInd(Index))<< " > " <<MidXYZ(OrderInd(Index+1)) // << " d: " << dMidXYZ << endl; exchange = Standard_True; } else if ( Abs(dMidXYZ) < tol && dLength >= tol ) { // cout << "Length: " << Length(OrderInd(Index))<< " > " <<Length(OrderInd(Index+1)) // << " d: " << dLength << endl; exchange = Standard_True; } else if ( Abs(dMidXYZ) < tol && Abs(dLength) < tol && aShapes(OrderInd(Index)).ShapeType() <= TopAbs_FACE) { // PAL17233 // equal values possible on shapes such as two halves of a sphere and // a membrane inside the sphere Bnd_Box box1,box2; BRepBndLib::Add( aShapes( OrderInd(Index) ), box1 ); if ( box1.IsVoid() ) continue; BRepBndLib::Add( aShapes( OrderInd(Index+1) ), box2 ); Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent(); if ( dSquareExtent >= tol ) { // cout << "SquareExtent: " << box1.SquareExtent()<<" > "<<box2.SquareExtent() << endl; exchange = Standard_True; } else if ( Abs(dSquareExtent) < tol ) { Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2; box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); val1 = (aXmin+aXmax)*999 + (aYmin+aYmax)*99 + (aZmin+aZmax)*0.9; box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); val2 = (aXmin+aXmax)*999 + (aYmin+aYmax)*99 + (aZmin+aZmax)*0.9; //exchange = val1 > val2; if ((val1 - val2) >= tol) { exchange = Standard_True; } //cout << "box: " << val1<<" > "<<val2 << endl; } } if (exchange) { // cout << "exchange " << Index << " & " << Index+1 << endl; aTemp = OrderInd(Index); OrderInd(Index) = OrderInd(Index+1); OrderInd(Index+1) = aTemp; Sort = Standard_True; } } } for (Index=1; Index <= MaxShapes; Index++) SL.Append( aShapes( OrderInd(Index) )); #endif }
gp_Pnt GetCOG(TopoDS_Shape shape) { GProp_GProps System; BRepGProp::SurfaceProperties (shape, System); return System.CentreOfMass(); }
//======================================================================= //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; }
//---------------------------------------------------------------- // Function: TopoDS_Shape level function to update the core Body // for any Boolean operation of the body. // Author: Jane Hu //---------------------------------------------------------------- CubitStatus OCCBody::update_OCC_entity(TopoDS_Shape& old_shape, TopoDS_Shape& new_shape, BRepBuilderAPI_MakeShape *op, LocOpe_SplitShape* sp) { //set the Shells TopTools_IndexedMapOfShape M; TopExp::MapShapes(old_shape, TopAbs_SOLID, M); TopTools_IndexedMapOfShape M_new; TopExp::MapShapes(new_shape, TopAbs_SOLID, M_new); TopTools_ListOfShape shapes; TopoDS_Shape shape; CubitBoolean updated = CUBIT_FALSE; if(!old_shape.IsNull() && old_shape.ShapeType() == TopAbs_COMPOUND && !new_shape.IsNull() && new_shape.ShapeType() == TopAbs_COMPOUND && !old_shape.IsSame(new_shape)) { //By updating underling solids, shells etc., the old_shape will get changed. //trying to make sure the the number of each entity in the old and new //shapes are the same, which means that nothing is delete, that we can //update the map here. Otherwise, when deleting solids, it'll delete the //the old body and create new body. This is Ok for general boolean operation //except imprint when booleans are called, usually the original body are // supposed to be kept. updated = CUBIT_TRUE; OCCQueryEngine::instance()->update_OCC_map(old_shape, new_shape); } DLIList<int> new_solid_nums; DLIList<int> unfound_nums; for(int ii=1; ii<=M.Extent(); ii++) { TopoDS_Solid solid = TopoDS::Solid(M(ii)); TopTools_ListOfShape shapes; if(op) { shapes.Assign(op->Modified(solid)); if(shapes.Extent() == 0) shapes.Assign(op->Generated(solid)); } else if(sp) shapes.Assign(sp->DescendantShapes(solid)); if (shapes.Extent() == 1) shape = shapes.First(); else if(shapes.Extent() > 1) { //update all attributes first. TopTools_ListIteratorOfListOfShape it; it.Initialize(shapes); for(; it.More(); it.Next()) { shape = it.Value(); OCCQueryEngine::instance()->copy_attributes(solid, shape); } shape = shapes.First(); } else if(op->IsDeleted(solid)) { if (M_new.Extent()== 1 && ii == 1) shape = M_new(1); else if(M_new.Extent()== 1 && ii > 1) shape.Nullify(); else if(M_new.Extent() > 1) { GProp_GProps myProps; BRepGProp::VolumeProperties(solid, myProps); double bf_mass = myProps.Mass(); gp_Pnt old_center = myProps.CentreOfMass(); CubitBoolean found = CUBIT_FALSE; for(int l = 1; l <= M_new.Extent(); l++) { BRepGProp::VolumeProperties(M_new(l), myProps); double af_mass = myProps.Mass(); double dTol = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); if(fabs(bf_mass-af_mass) < dTol) //unchanged { gp_Pnt new_center = myProps.CentreOfMass(); if(new_center.IsEqual(old_center, dTol)) { found = CUBIT_TRUE; shape = M_new(l); new_solid_nums.append(l); break; } } } if(!found) { unfound_nums.append(ii); continue; } } else shape.Nullify(); } else { shape = solid; continue; } if(shapes.Extent() > 0 || (op && op->IsDeleted(solid))) OCCLump::update_OCC_entity(solid, shape, op, sp); } if( unfound_nums.size() == 1 ) { TopoDS_Solid solid = TopoDS::Solid(M(unfound_nums.get())); for(int kk = 1; kk <= M_new.Extent(); kk++) { if(!new_solid_nums.move_to(kk)) { shape = M_new(kk); break; } } OCCLump::update_OCC_entity(solid, shape, op, sp); } else if(unfound_nums.size() > 1) { shape.Nullify(); for(int kk = 1; kk <=unfound_nums.size(); kk++) { TopoDS_Solid solid = TopoDS::Solid(M(unfound_nums.get_and_step())); OCCLump::update_OCC_entity(solid, shape, op, sp); } } if(!old_shape.IsSame(new_shape) && !updated) OCCQueryEngine::instance()->update_OCC_map(old_shape, new_shape); return CUBIT_SUCCESS; }