/// 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); }
bool CTiglAbstractGeometricComponent::GetIsOn(const gp_Pnt& pnt) { const TopoDS_Shape& segmentShape = GetLoft()->Shape(); // fast check with bounding box Bnd_Box boundingBox; BRepBndLib::Add(segmentShape, boundingBox); Standard_Real xmin, xmax, ymin, ymax, zmin, zmax; boundingBox.Get(xmin, ymin, zmin, xmax, ymax, zmax); if (pnt.X() < xmin || pnt.X() > xmax || pnt.Y() < ymin || pnt.Y() > ymax || pnt.Z() < zmin || pnt.Z() > zmax) { return false; } double tolerance = 0.03; // 3cm BRepClass3d_SolidClassifier classifier; classifier.Load(segmentShape); classifier.Perform(pnt, tolerance); if ((classifier.State() == TopAbs_IN) || (classifier.State() == TopAbs_ON)) { return true; } else { return false; } }
//! 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); }
// Returns the coordinates of the bounding box of the shape void GetShapeExtension(const TopoDS_Shape& shape, double& minx, double& maxx, double& miny, double& maxy, double& minz, double& maxz) { Bnd_Box boundingBox; BRepBndLib::Add(shape, boundingBox); boundingBox.Get(minx, miny, minz, maxx, maxy, maxz); }
SBoundingBox3d OCCEdge::bounds() const { Bnd_Box b; BRepBndLib::Add(c, b); double xmin, ymin, zmin, xmax, ymax, zmax; b.Get(xmin, ymin, zmin, xmax, ymax, zmax); SBoundingBox3d bbox(xmin, ymin, zmin, xmax, ymax, zmax); return bbox; }
//------------------------------------------------------------------------- // Purpose : Get the bounding box of the object. // // Special Notes : // //------------------------------------------------------------------------- CubitBox OCCSurface::bounding_box() const { TopoDS_Face face = *myTopoDSFace; BRepAdaptor_Surface asurface(face); Bnd_Box aBox; BndLib_AddSurface::Add(asurface, Precision::Approximation(), aBox); double min[3], max[3]; aBox.Get( min[0], min[1], min[2], max[0], max[1], max[2]); return CubitBox(min, max); }
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; }
//======================================================================= //function : CheckTriangulation //purpose : //======================================================================= bool GEOMUtils::CheckTriangulation (const TopoDS_Shape& aShape) { bool isTriangulation = true; TopExp_Explorer exp (aShape, TopAbs_FACE); if (exp.More()) { TopLoc_Location aTopLoc; Handle(Poly_Triangulation) aTRF; aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc); if (aTRF.IsNull()) { isTriangulation = false; } } else // no faces, try edges { TopExp_Explorer expe (aShape, TopAbs_EDGE); if (!expe.More()) { return false; } TopLoc_Location aLoc; Handle(Poly_Polygon3D) aPE = BRep_Tool::Polygon3D(TopoDS::Edge(expe.Current()), aLoc); if (aPE.IsNull()) { isTriangulation = false; } } if (!isTriangulation) { // calculate deflection Standard_Real aDeviationCoefficient = 0.001; Bnd_Box B; BRepBndLib::Add(aShape, B); Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin; Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4; Standard_Real aHLRAngle = 0.349066; BRepMesh_IncrementalMesh Inc (aShape, aDeflection, Standard_False, aHLRAngle); } return true; }
OCCMesh *OCCFace::createMesh(double factor, double angle, bool qualityNormals = true) { OCCMesh *mesh = new OCCMesh(); try { Bnd_Box aBox; BRepBndLib::Add(this->getShape(), aBox); Standard_Real aXmin, aYmin, aZmin; Standard_Real aXmax, aYmax, aZmax; aBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); Standard_Real maxd = fabs(aXmax - aXmin); maxd = std::max(maxd, fabs(aYmax - aYmin)); maxd = std::max(maxd, fabs(aZmax - aZmin)); BRepMesh_FastDiscret MSH(factor*maxd, angle, aBox, Standard_False, Standard_False, Standard_True, Standard_True); MSH.Perform(this->getShape()); BRepMesh_IncrementalMesh(this->getShape(),factor*maxd); if (this->getShape().ShapeType() != TopAbs_FACE) { TopExp_Explorer exFace; for (exFace.Init(this->getShape(), TopAbs_FACE); exFace.More(); exFace.Next()) { const TopoDS_Face& faceref = static_cast<const TopoDS_Face &>(exFace.Current()); mesh->extractFaceMesh(faceref, qualityNormals); } } else { mesh->extractFaceMesh(this->getFace(), qualityNormals); } } catch(Standard_Failure &err) { Handle_Standard_Failure e = Standard_Failure::Caught(); const Standard_CString msg = e->GetMessageString(); if (msg != NULL && strlen(msg) > 1) { setErrorMessage(msg); } else { setErrorMessage("Failed to create mesh"); } return NULL; } return mesh; }
//---------------------------------------------------------------- // Function: update_bounding_box // Description: calculate for bounding box of this OCCBody // // Author: janehu //---------------------------------------------------------------- void OCCBody::update_bounding_box() { Bnd_Box box; TopoDS_Shape shape; for (int i = 0; i < myLumps.size(); i++) { OCCLump *lump = CAST_TO(myLumps.get_and_step(), OCCLump); shape = *lump->get_TopoDS_Solid(); BRepBndLib::Add(shape, box); } for(int i = 0; i < mySheetSurfaces.size(); i++) { OCCSurface* surface = mySheetSurfaces.get_and_step(); shape = *surface->get_TopoDS_Face(); BRepBndLib::Add(shape, box); } for(int i = 0; i <myShells.size() ; i++) { OCCShell* occ_shell = myShells.get_and_step(); shape = *occ_shell->get_TopoDS_Shell(); BRepBndLib::Add(shape, box); } //calculate the bounding box if(myLumps.size() + mySheetSurfaces.size() + myShells.size() == 0) { if(!myTopoDSShape) return; TopoDS_Shape shape = *myTopoDSShape; BRepBndLib::Add(shape, box); } double min[3], max[3]; //get values box.Get(min[0], min[1], min[2], max[0], max[1], max[2]); //update boundingbox. boundingbox.reset(min, max); }
void SetupResultBoundingBox::go(ResultEntry *entry) { entry->boxSep = new SoSeparator(); entry->viewProvider->getRoot()->addChild(entry->boxSep); entry->boxSwitch = new SoSwitch(); entry->boxSep->addChild(entry->boxSwitch); SoGroup *group = new SoGroup(); entry->boxSwitch->addChild(group); entry->boxSwitch->whichChild.setValue(SO_SWITCH_NONE); SoDrawStyle *dStyle = new SoDrawStyle(); dStyle->style.setValue(SoDrawStyle::LINES); dStyle->linePattern.setValue(0xc0c0); group->addChild(dStyle); SoMaterial *material = new SoMaterial(); material->diffuseColor.setValue(255.0, 255.0, 255.0); material->ambientColor.setValue(255.0, 255.0, 255.0); group->addChild(material); Bnd_Box boundingBox; BRepBndLib::Add(entry->shape, boundingBox); Standard_Real xmin, ymin, zmin, xmax, ymax, zmax; boundingBox.Get(xmin, ymin, zmin, xmax, ymax, zmax); double xCenter, yCenter, zCenter; xCenter = (xmax - xmin)/2 + xmin; yCenter = (ymax - ymin)/2 + ymin; zCenter = (zmax - zmin)/2 + zmin; SbVec3f boundCenter(xCenter, yCenter, zCenter); Standard_Real x, y, z; entry->shape.Location().Transformation().TranslationPart().Coord(x, y, z); boundCenter -= SbVec3f(x, y, z); SoTransform *position = new SoTransform(); position->translation.setValue(boundCenter); group->addChild(position); SoCube *cube = new SoCube(); cube->width.setValue(xmax - xmin); cube->height.setValue(ymax - ymin); cube->depth.setValue(zmax - zmin); group->addChild(cube); }
void PartGui::goSetupResultBoundingBox(ResultEntry *entry) { //empty compound throws bounding box error. Mantis #0001426 try { Bnd_Box boundingBox; BRepBndLib::Add(entry->shape, boundingBox); Standard_Real xmin, ymin, zmin, xmax, ymax, zmax; boundingBox.Get(xmin, ymin, zmin, xmax, ymax, zmax); SbVec3f boundCenter((xmax - xmin)/2 + xmin, (ymax - ymin)/2 + ymin, (zmax - zmin)/2 + zmin); entry->boxSep = new SoSeparator(); entry->viewProviderRoot->addChild(entry->boxSep); entry->boxSwitch = new SoSwitch(); entry->boxSep->addChild(entry->boxSwitch); SoGroup *group = new SoGroup(); entry->boxSwitch->addChild(group); entry->boxSwitch->whichChild.setValue(SO_SWITCH_NONE); SoDrawStyle *dStyle = new SoDrawStyle(); dStyle->style.setValue(SoDrawStyle::LINES); dStyle->linePattern.setValue(0xc0c0); group->addChild(dStyle); SoMaterial *material = new SoMaterial(); material->diffuseColor.setValue(255.0, 255.0, 255.0); material->ambientColor.setValue(255.0, 255.0, 255.0); group->addChild(material); SoResetTransform *reset = new SoResetTransform(); group->addChild(reset); SoTransform *position = new SoTransform(); position->translation.setValue(boundCenter); group->addChild(position); SoCube *cube = new SoCube(); cube->width.setValue(xmax - xmin); cube->height.setValue(ymax - ymin); cube->depth.setValue(zmax - zmin); group->addChild(cube); } catch (const Standard_Failure &){} }
void VisualSceneOCCGeometry :: BuildScene (int zoomall) { if (occgeometry -> changed == OCCGEOMETRYVISUALIZATIONFULLCHANGE) { occgeometry -> BuildVisualizationMesh (vispar.occdeflection); center = occgeometry -> Center(); rad = occgeometry -> GetBoundingBox().Diam() / 2; if (vispar.occzoomtohighlightedentity) { bool hilite = false; bool hiliteonepoint = false; Bnd_Box bb; for (int i = 1; i <= occgeometry->fmap.Extent(); i++) if (occgeometry->fvispar[i-1].IsHighlighted()) { hilite = true; BRepBndLib::Add (occgeometry->fmap(i), bb); } for (int i = 1; i <= occgeometry->emap.Extent(); i++) if (occgeometry->evispar[i-1].IsHighlighted()) { hilite = true; BRepBndLib::Add (occgeometry->emap(i), bb); } for (int i = 1; i <= occgeometry->vmap.Extent(); i++) if (occgeometry->vvispar[i-1].IsHighlighted()) { hiliteonepoint = true; BRepBndLib::Add (occgeometry->vmap(i), bb); } if (hilite || hiliteonepoint) { double x1,y1,z1,x2,y2,z2; bb.Get (x1,y1,z1,x2,y2,z2); Point<3> p1 = Point<3> (x1,y1,z1); Point<3> p2 = Point<3> (x2,y2,z2); Box<3> boundingbox(p1,p2); center = boundingbox.Center(); if (hiliteonepoint) rad = occgeometry -> GetBoundingBox().Diam() / 100; else rad = boundingbox.Diam() / 2; } } CalcTransformationMatrices(); } // Clear lists for (int i = 1; i <= linelists.Size(); i++) glDeleteLists (linelists.Elem(i), 1); linelists.SetSize(0); for (int i = 1; i <= trilists.Size(); i++) glDeleteLists (trilists.Elem(i), 1); trilists.SetSize(0); // Total wireframe linelists.Append (glGenLists (1)); glNewList (linelists.Last(), GL_COMPILE); for (int i = 1; i <= occgeometry->emap.Extent(); i++) { TopoDS_Edge edge = TopoDS::Edge(occgeometry->emap(i)); if (BRep_Tool::Degenerated(edge)) continue; if (occgeometry->evispar[i-1].IsHighlighted()) continue; Handle(Poly_PolygonOnTriangulation) aEdgePoly; Handle(Poly_Triangulation) T; TopLoc_Location aEdgeLoc; BRep_Tool::PolygonOnTriangulation(edge, aEdgePoly, T, aEdgeLoc); if(aEdgePoly.IsNull()) { (*testout) << "visualizing edge " << occgeometry->emap.FindIndex (edge) << " without using the occ visualization triangulation" << endl; double s0, s1; Handle(Geom_Curve) c = BRep_Tool::Curve(edge, s0, s1); glBegin (GL_LINE_STRIP); for (int i = 0; i<=50; i++) { gp_Pnt p = c->Value (s0 + i*(s1-s0)/50.0); glVertex3f (p.X(),p.Y(),p.Z()); } glEnd (); continue; } int nbnodes = aEdgePoly -> NbNodes(); glBegin (GL_LINE_STRIP); for (int j = 1; j <= nbnodes; j++) { gp_Pnt p = (T -> Nodes())(aEdgePoly->Nodes()(j)).Transformed(aEdgeLoc); glVertex3f (p.X(), p.Y(), p.Z()); } glEnd (); } glEndList (); // Highlighted edge list linelists.Append (glGenLists (1)); glNewList (linelists.Last(), GL_COMPILE); for (int i = 1; i <= occgeometry->emap.Extent(); i++) if (occgeometry->evispar[i-1].IsHighlighted()) { TopoDS_Edge edge = TopoDS::Edge(occgeometry->emap(i)); if (BRep_Tool::Degenerated(edge)) continue; Handle(Poly_PolygonOnTriangulation) aEdgePoly; Handle(Poly_Triangulation) T; TopLoc_Location aEdgeLoc; BRep_Tool::PolygonOnTriangulation(edge, aEdgePoly, T, aEdgeLoc); if(aEdgePoly.IsNull()) { (*testout) << "visualizing edge " << occgeometry->emap.FindIndex (edge) << " without using the occ visualization triangulation" << endl; double s0, s1; Handle(Geom_Curve) c = BRep_Tool::Curve(edge, s0, s1); glBegin (GL_LINE_STRIP); for (int i = 0; i<=50; i++) { gp_Pnt p = c->Value (s0 + i*(s1-s0)/50.0); glVertex3f (p.X(),p.Y(),p.Z()); } glEnd (); continue; } int nbnodes = aEdgePoly -> NbNodes(); glBegin (GL_LINE_STRIP); for (int j = 1; j <= nbnodes; j++) { gp_Pnt p = (T -> Nodes())(aEdgePoly->Nodes()(j)).Transformed(aEdgeLoc); glVertex3f (p.X(), p.Y(), p.Z()); } glEnd (); } glEndList (); // display faces trilists.Append (glGenLists (1)); glNewList (trilists.Last(), GL_COMPILE); for (int i = 1; i <= occgeometry->fmap.Extent(); i++) { if (!occgeometry->fvispar[i-1].IsVisible()) continue; glLoadName (i); float mat_col[4]; mat_col[3] = 1; TopoDS_Face face = TopoDS::Face(occgeometry->fmap(i)); if (!occgeometry->fvispar[i-1].IsHighlighted()) { // Philippose - 30/01/2009 // OpenCascade XDE Support Quantity_Color face_colour; // Philippose - 23/02/2009 // Check to see if colours have been extracted first!! // Forum bug-fox (Jean-Yves - 23/02/2009) if(!(occgeometry->face_colours.IsNull()) && (occgeometry->face_colours->GetColor(face,XCAFDoc_ColorSurf,face_colour))) { mat_col[0] = face_colour.Red(); mat_col[1] = face_colour.Green(); mat_col[2] = face_colour.Blue(); } else { mat_col[0] = 0.0; mat_col[1] = 1.0; mat_col[2] = 0.0; } } else { mat_col[0] = 0.8; mat_col[1] = 0.2; mat_col[2] = 0.2; } glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); TopLoc_Location loc; Handle(Geom_Surface) surf = BRep_Tool::Surface (face); BRepAdaptor_Surface sf(face, Standard_False); BRepLProp_SLProps prop(sf, 1, 1e-5); Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc); if (triangulation.IsNull()) { cout << "cannot visualize face " << i << endl; occgeometry->fvispar[i-1].SetNotDrawable(); continue; } gp_Pnt2d uv; gp_Pnt pnt; gp_Vec n; glBegin (GL_TRIANGLES); int ntriangles = triangulation -> NbTriangles(); for (int j = 1; j <= ntriangles; j++) { Poly_Triangle triangle = (triangulation -> Triangles())(j); gp_Pnt p[3]; for (int k = 1; k <= 3; k++) p[k-1] = (triangulation -> Nodes())(triangle(k)).Transformed(loc); for (int k = 1; k <= 3; k++) { uv = (triangulation -> UVNodes())(triangle(k)); prop.SetParameters (uv.X(), uv.Y()); // surf->D0 (uv.X(), uv.Y(), pnt); if (prop.IsNormalDefined()) n = prop.Normal(); else { (*testout) << "Visualization of face " << i << ": Normal vector not defined" << endl; // n = gp_Vec (0,0,0); gp_Vec a(p[0],p[1]); gp_Vec b(p[0],p[2]); n = b^a; } if (face.Orientation() == TopAbs_REVERSED) n *= -1; glNormal3f (n.X(), n.Y(), n.Z()); glVertex3f (p[k-1].X(), p[k-1].Y(), p[k-1].Z()); } } glEnd (); } glEndList (); }
//======================================================================= //function : Execute //purpose : //======================================================================= Standard_Integer GEOMImpl_MeasureDriver::Execute(TFunction_Logbook& log) const { if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); GEOMImpl_IMeasure aCI (aFunction); Standard_Integer aType = aFunction->GetType(); TopoDS_Shape aShape; if (aType == CDG_MEASURE) { Handle(GEOM_Function) aRefBase = aCI.GetBase(); TopoDS_Shape aShapeBase = aRefBase->GetValue(); if (aShapeBase.IsNull()) { Standard_NullObject::Raise("Shape for centre of mass calculation is null"); } gp_Ax3 aPos = GEOMImpl_IMeasureOperations::GetPosition(aShapeBase); gp_Pnt aCenterMass = aPos.Location(); aShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape(); } else if (aType == VERTEX_BY_INDEX) { Handle(GEOM_Function) aRefBase = aCI.GetBase(); TopoDS_Shape aShapeBase = aRefBase->GetValue(); if (aShapeBase.IsNull()) { Standard_NullObject::Raise("Shape for centre of mass calculation is null"); } int index = aCI.GetIndex(); gp_Pnt aVertex; if (aShapeBase.ShapeType() == TopAbs_VERTEX) { if ( index != 1 ) Standard_NullObject::Raise("Vertex index is out of range"); else aVertex = BRep_Tool::Pnt(TopoDS::Vertex(aShapeBase)); } else if (aShapeBase.ShapeType() == TopAbs_EDGE) { TopoDS_Vertex aV1, aV2; TopoDS_Edge anEdgeE = TopoDS::Edge(aShapeBase); TopExp::Vertices(anEdgeE, aV1, aV2); gp_Pnt aP1 = BRep_Tool::Pnt(aV1); gp_Pnt aP2 = BRep_Tool::Pnt(aV2); if (index < 0 || index > 1) Standard_NullObject::Raise("Vertex index is out of range"); if ( ( anEdgeE.Orientation() == TopAbs_FORWARD && index == 0 ) || ( anEdgeE.Orientation() == TopAbs_REVERSED && index == 1 ) ) aVertex = aP1; else aVertex = aP2; } else if (aShapeBase.ShapeType() == TopAbs_WIRE) { TopTools_IndexedMapOfShape anEdgeShapes; TopTools_IndexedMapOfShape aVertexShapes; TopoDS_Vertex aV1, aV2; TopoDS_Wire aWire = TopoDS::Wire(aShapeBase); TopExp_Explorer exp (aWire, TopAbs_EDGE); for (; exp.More(); exp.Next()) { anEdgeShapes.Add(exp.Current()); TopoDS_Edge E = TopoDS::Edge(exp.Current()); TopExp::Vertices(E, aV1, aV2); if ( aVertexShapes.Extent() == 0) aVertexShapes.Add(aV1); if ( !aV1.IsSame( aVertexShapes(aVertexShapes.Extent()) ) ) aVertexShapes.Add(aV1); if ( !aV2.IsSame( aVertexShapes(aVertexShapes.Extent()) ) ) aVertexShapes.Add(aV2); } if (index < 0 || index > aVertexShapes.Extent()) Standard_NullObject::Raise("Vertex index is out of range"); if (aWire.Orientation() == TopAbs_FORWARD) aVertex = BRep_Tool::Pnt(TopoDS::Vertex(aVertexShapes(index+1))); else aVertex = BRep_Tool::Pnt(TopoDS::Vertex(aVertexShapes(aVertexShapes.Extent() - index))); } else { Standard_NullObject::Raise("Shape for vertex calculation is not an edge or wire"); } aShape = BRepBuilderAPI_MakeVertex(aVertex).Shape(); } else if (aType == VECTOR_FACE_NORMALE) { // Face Handle(GEOM_Function) aRefBase = aCI.GetBase(); TopoDS_Shape aShapeBase = aRefBase->GetValue(); if (aShapeBase.IsNull()) { Standard_NullObject::Raise("Face for normale calculation is null"); } if (aShapeBase.ShapeType() != TopAbs_FACE) { Standard_NullObject::Raise("Shape for normale calculation is not a face"); } TopoDS_Face aFace = TopoDS::Face(aShapeBase); // Point gp_Pnt p1 (0,0,0); Handle(GEOM_Function) aPntFunc = aCI.GetPoint(); if (!aPntFunc.IsNull()) { TopoDS_Shape anOptPnt = aPntFunc->GetValue(); if (anOptPnt.IsNull()) Standard_NullObject::Raise("Invalid shape given for point argument"); p1 = BRep_Tool::Pnt(TopoDS::Vertex(anOptPnt)); } else { gp_Ax3 aPos = GEOMImpl_IMeasureOperations::GetPosition(aFace); p1 = aPos.Location(); } // Point parameters on surface Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace); Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf); gp_Pnt2d pUV = aSurfAna->ValueOfUV(p1, Precision::Confusion()); // Normal direction gp_Vec Vec1,Vec2; BRepAdaptor_Surface SF (aFace); SF.D1(pUV.X(), pUV.Y(), p1, Vec1, Vec2); if (Vec1.Magnitude() < Precision::Confusion()) { gp_Vec tmpV; gp_Pnt tmpP; SF.D1(pUV.X(), pUV.Y()-0.1, tmpP, Vec1, tmpV); } else if (Vec2.Magnitude() < Precision::Confusion()) { gp_Vec tmpV; gp_Pnt tmpP; SF.D1(pUV.X()-0.1, pUV.Y(), tmpP, tmpV, Vec2); } gp_Vec V = Vec1.Crossed(Vec2); Standard_Real mod = V.Magnitude(); if (mod < Precision::Confusion()) Standard_NullObject::Raise("Normal vector of a face has null magnitude"); // Set length of normal vector to average radius of curvature Standard_Real radius = 0.0; GeomLProp_SLProps aProperties (aSurf, pUV.X(), pUV.Y(), 2, Precision::Confusion()); if (aProperties.IsCurvatureDefined()) { Standard_Real radius1 = Abs(aProperties.MinCurvature()); Standard_Real radius2 = Abs(aProperties.MaxCurvature()); if (Abs(radius1) > Precision::Confusion()) { radius = 1.0 / radius1; if (Abs(radius2) > Precision::Confusion()) { radius = (radius + 1.0 / radius2) / 2.0; } } else { if (Abs(radius2) > Precision::Confusion()) { radius = 1.0 / radius2; } } } // Set length of normal vector to average dimension of the face // (only if average radius of curvature is not appropriate) if (radius < Precision::Confusion()) { Bnd_Box B; Standard_Real Xmin, Xmax, Ymin, Ymax, Zmin, Zmax; BRepBndLib::Add(aFace, B); B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax); radius = ((Xmax - Xmin) + (Ymax - Ymin) + (Zmax - Zmin)) / 3.0; } if (radius < Precision::Confusion()) radius = 1.0; V *= radius / mod; // consider the face orientation if (aFace.Orientation() == TopAbs_REVERSED || aFace.Orientation() == TopAbs_INTERNAL) { V = - V; } // Edge gp_Pnt p2 = p1.Translated(V); BRepBuilderAPI_MakeEdge aBuilder (p1, p2); if (!aBuilder.IsDone()) Standard_NullObject::Raise("Vector construction failed"); aShape = aBuilder.Shape(); } else { } if (aShape.IsNull()) return 0; aFunction->SetValue(aShape); log.SetTouched(Label()); return 1; }
bool RoomLayoutPillarController::PreRender3D() { auto& imp_ = *ImpUPtr_; plane3df plan(0,0,0,0,1,0); auto line = GetRenderContextSPtr()->Smgr_->getSceneCollisionManager()->getRayFromScreenCoordinates(imp_.CursorIPos_); plan.getIntersectionWithLine(line.start, line.getVector(), imp_.CurrentPos_); imp_.CurrentPos_.Y = 0; gp_Pnt cursorPnt(imp_.CurrentPos_.X, imp_.CurrentPos_.Y, imp_.CurrentPos_.Z); switch (imp_.State_) { case EPilarState::EPS_SWEEPING: { if ( GetPickingODL().expired() ) { break; } auto activePilar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock()); activePilar->SetSweeping(true); if ( imp_.CtrllHolding_ ) { imp_.State_ = EPilarState::EPS_MODIFY_INIT; break; } if ( imp_.LMousePressDown_ ) { auto box = activePilar->GetBaseBndBox(); auto pos = activePilar->GetTranslation(); Standard_Real xMin,xMax,yMin,yMax,zMin,zMax; box.Get(xMin, yMin, zMin, xMax, yMax, zMax); imp_.EventInfo_ = SEventPillarInfo(); imp_.EventInfo_->XLength_ = static_cast<float>(xMax-xMin); imp_.EventInfo_->YLength_ = static_cast<float>(yMax-yMin); imp_.EventInfo_->ZLength_ = static_cast<float>(zMax-zMin); imp_.EventInfo_->OffsetHeight_ = activePilar->GetOffsetHeight(); imp_.SavePos_ = imp_.CurrentPos_; imp_.State_ = EPilarState::EPS_MOUSEHOLDING; } } break; case EPilarState::EPS_MODIFY_INIT: { auto activePilar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock()); activePilar->SetSweeping(true); if ( !imp_.CtrllHolding_ ) { GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_NORMAL); imp_.State_ = EPilarState::EPS_SWEEPING; imp_.CtrllHolding_ = false; break; } auto box = activePilar->GetBaseBndBox(); Standard_Real xMin,xMax,yMin,yMax,zMin,zMax; box.Get(xMin, yMin, zMin, xMax, yMax, zMax); auto modifyAlign = 100; Bnd_Box smallBox,bigBox; smallBox.Update(xMin+modifyAlign < 0 ? xMin+modifyAlign : 0, yMin+modifyAlign < 0 ? yMin+modifyAlign : 0, zMin+modifyAlign < 0 ? zMin+modifyAlign : 0, xMax-modifyAlign > 0 ? xMax-modifyAlign : 0, yMax-modifyAlign > 0 ? yMax-modifyAlign : 0, zMax-modifyAlign > 0 ? zMax-modifyAlign : 0); bigBox.Update(xMin-modifyAlign, yMin-modifyAlign, zMin-modifyAlign, xMax+modifyAlign, yMax+modifyAlign, zMax+modifyAlign); auto relationCursorPnt = cursorPnt.Transformed(activePilar->GetAbsoluteTransform().Inverted()); relationCursorPnt.SetY(0); if ( Standard_True == bigBox.IsOut(relationCursorPnt) ) { GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_NORMAL); imp_.State_ = EPilarState::EPS_SWEEPING; imp_.CtrllHolding_ = false; break; } if ( Standard_False == smallBox.IsOut(relationCursorPnt) ) { GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_NORMAL); break; } gp_Dir cursorDir = gp_Vec(gp::Origin(), relationCursorPnt); { auto rad = gp::DX().AngleWithRef(cursorDir, gp::DY()); rad = rad < 0 ? M_PI * 2 + rad : rad; auto mod = std::fmod(rad, M_PI_2); if ( mod < M_PI_4 ) { rad -= mod; } else { rad = rad - mod + M_PI_2; } cursorDir = gp::DX().Rotated(gp::OY(), rad); mod = std::fmod(rad, M_PI); if ( mod < Precision::Angular() ) { GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_SIZEWE); } else { GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_SIZENS); } } if ( imp_.LMousePressDown_ ) { auto edge = BRepBuilderAPI_MakeEdge(gp_Lin(gp::Origin().Transformed(activePilar->GetAbsoluteTransform()), cursorDir.Transformed(activePilar->GetAbsoluteTransform()))).Edge(); BRepAdaptor_Curve moveBC(edge); GeomAPI_ProjectPointOnCurve ppc(relationCursorPnt.Transformed(activePilar->GetAbsoluteTransform()), moveBC.Curve().Curve()); imp_.ModifyEdge_ = moveBC; imp_.ModifyPar_ = ppc.LowerDistanceParameter(); imp_.State_ = EPilarState::EPS_MODIFY; break; } } break; case EPilarState::EPS_MODIFY: { auto activePilar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock()); activePilar->SetPicking(true); if ( imp_.LMouseLeftUp_ ) { activePilar->UpdateMesh(); imp_.State_ = EPilarState::EPS_SWEEPING; break; } GeomAPI_ProjectPointOnCurve ppcCur(cursorPnt, imp_.ModifyEdge_.Curve().Curve()); auto curPar = ppcCur.LowerDistanceParameter(); if ( std::abs(curPar - imp_.ModifyPar_) < Precision::Confusion() ) { break; } //偏移的起始点、终点(绝对) gp_Pnt fromPnt,toPnt; imp_.ModifyEdge_.D0(imp_.ModifyPar_, fromPnt); imp_.ModifyEdge_.D0(curPar, toPnt); gp_Vec moveOffset(fromPnt, toPnt); auto relationMoveOffset = moveOffset.Transformed(activePilar->GetAbsoluteTransform().Inverted()); auto modifyDir = imp_.ModifyEdge_.Line().Direction().Transformed(activePilar->GetAbsoluteTransform().Inverted()); auto modifyOffset = relationMoveOffset; { modifyOffset.SetX(modifyOffset.X() * modifyDir.X()); modifyOffset.SetY(modifyOffset.Y() * modifyDir.Y()); modifyOffset.SetZ(modifyOffset.Z() * modifyDir.Z()); } auto curPillarSize = activePilar->GetSize(); if ( Standard_False == imp_.ModifyEdge_.Line().Direction().IsEqual(gp_Dir(moveOffset), Precision::Angular()) ) {//防止大小缩成0 auto testSize = curPillarSize + modifyOffset.XYZ(); auto minSize = 100; auto alignSize = testSize - gp_XYZ(minSize,minSize,minSize); if ( alignSize.X() < Precision::Confusion() || alignSize.Y() < Precision::Confusion() || alignSize.Z() < Precision::Confusion() ) { break; } } Bnd_Box pillarBox; auto pillarBoxSize = curPillarSize + modifyOffset.XYZ(); gp_Trsf pillarTranslation,pillarRotation,pillarTransformation; { pillarBox.Update(-pillarBoxSize.X()/2, -pillarBoxSize.Y()/2, -pillarBoxSize.Z()/2, pillarBoxSize.X()/2, pillarBoxSize.Y()/2, pillarBoxSize.Z()/2); auto translation = activePilar->GetTranslation() + relationMoveOffset.XYZ()/2; pillarTranslation.SetTranslationPart(translation); pillarRotation.SetRotation(activePilar->GetRotation()); } pillarTransformation = pillarTranslation * pillarRotation; auto offsetHeight = activePilar->GetOffsetHeight(); //新的位置 gp_Pnt newPnt = gp::Origin().Transformed(pillarTransformation); //吸附距离 static auto alignDis = 200.0; //当前的吸附物体 auto alignODLs = activePilar->GetAlignList(); alignODLs.erase(std::remove_if(alignODLs.begin(), alignODLs.end(), [&pillarBox,&pillarTransformation](const BaseODLSPtr& alignODL) { if ( !alignODL ) { return true; } return alignODL->GetBaseBndBox().Distance(pillarBox.Transformed(alignODL->GetAbsoluteTransform().Inverted() * pillarTransformation)) > alignDis; }), alignODLs.end()); activePilar->SetAlignList(BaseODLList()); std::multimap<double,BaseODLSPtr> disMap; for ( auto& curODL : RootODL_.lock()->GetChildrenList() ) { if ( EODLT_PILLAR != curODL->GetType() && EODLT_WALL != curODL->GetType() ) { continue; } if ( std::find(alignODLs.begin(), alignODLs.end(), curODL) != alignODLs.end() ) { continue; } if ( EODLT_PILLAR == curODL->GetType() && curODL == activePilar ) { continue; } auto dis = curODL->GetBaseBndBox().Distance(pillarBox.Transformed(curODL->GetAbsoluteTransform().Inverted() * pillarTransformation)); if ( dis > alignDis ) { continue; } disMap.emplace(dis, curODL); } for ( auto& curODL : disMap ) { alignODLs.push_back(curODL.second); } for ( auto& curODL : alignODLs ) { auto alignTransformation = curODL->GetAbsoluteTransform(); //调整柱box的旋转 auto activeRotationPillarBox = pillarBox; { gp_Trsf tfsODL; tfsODL.SetRotation(alignTransformation.GetRotation()); activeRotationPillarBox = activeRotationPillarBox.Transformed(tfsODL.Inverted() * pillarRotation); } Bnd_Box movingBox,alignODLBox; { auto curBox = curODL->GetBaseBndBox(); Standard_Real xAlignMin,yAlignMin,zAlignMin,xAlignMax,yAlignMax,zAlignMax; curBox.Get(xAlignMin, yAlignMin, zAlignMin, xAlignMax, yAlignMax, zAlignMax); Standard_Real xPillarMin,yPillarMin,zPillarMin,xPillarMax,yPillarMax,zPillarMax; activeRotationPillarBox.Get(xPillarMin, yPillarMin, zPillarMin, xPillarMax, yPillarMax, zPillarMax); movingBox.Update(xAlignMin+xPillarMin, yAlignMin+yPillarMin, zAlignMin+zPillarMin, xAlignMax+xPillarMax, yAlignMax+yPillarMax, zAlignMax+zPillarMax); alignODLBox.Update(xAlignMin+xPillarMin-alignDis, yAlignMin+yPillarMin-alignDis, zAlignMin+zPillarMin-alignDis, xAlignMax+xPillarMax+alignDis, yAlignMax+yPillarMax+alignDis, zAlignMax+zPillarMax+alignDis); } auto inODLPnt = newPnt.Transformed(curODL->GetAbsoluteTransform().Inverted()); if ( Standard_True == alignODLBox.IsOut(inODLPnt) ) { continue; } //当前被停靠物体的box shape Standard_Real xMin,yMin,zMin,xMax,yMax,zMax; movingBox.Get(xMin, yMin, zMin, xMax, yMax, zMax); auto alignBoxShape = BRepPrimAPI_MakeBox(gp_Pnt(xMin, yMin, zMin), gp_Pnt(xMax, yMax, zMax)).Shape(); TopExp_Explorer exp(alignBoxShape, TopAbs_SHELL); BRepExtrema_DistShapeShape dss(imp_.ModifyEdge_.Edge().Moved(curODL->GetAbsoluteTransform().Inverted()), exp.Current()); auto needContinue = false; std::map<double, gp_Pnt> tmp; for ( auto index=1; index<=dss.NbSolution(); ++index ) { if ( dss.SupportTypeShape2(index) == BRepExtrema_IsOnEdge ) { activePilar->AddAlign(curODL); needContinue = true; break; } auto pntOnEdge = dss.PointOnShape1(index); auto pntOnBox = dss.PointOnShape2(index); if ( pntOnEdge.Distance(pntOnBox) > Precision::Confusion() ) { continue; } tmp.emplace(pntOnEdge.Distance(inODLPnt), pntOnEdge); } if ( needContinue ) { continue; } auto foundPnt = tmp.begin()->second.Transformed(curODL->GetAbsoluteTransform()); if ( foundPnt.Distance(newPnt) < 1) { activePilar->AddAlign(curODL); continue; } else { newPnt = foundPnt; break; } } auto finalOffset = gp_Vec(pillarTranslation.TranslationPart(), newPnt); auto finalRelationOffset = finalOffset.Transformed(pillarTransformation.Inverted()); auto finalModifyOffset = finalRelationOffset; { finalModifyOffset.SetX(finalModifyOffset.X()*modifyDir.X()); finalModifyOffset.SetY(finalModifyOffset.Y()*modifyDir.Y()); finalModifyOffset.SetZ(finalModifyOffset.Z()*modifyDir.Z()); } auto finalSize = pillarBoxSize + finalModifyOffset.XYZ(); auto finalTranslation = pillarTranslation.TranslationPart() + finalRelationOffset.XYZ()/2; activePilar->SetSize(finalSize); activePilar->SetTranslation(finalTranslation); { vector3df newPos(static_cast<float>(finalTranslation.X()), static_cast<float>(finalTranslation.Y()), static_cast<float>(finalTranslation.Z())); activePilar->GetDataSceneNode()->setPosition(newPos); } activePilar->Update2DMesh(); imp_.ModifyPar_ = curPar; } break; case EPilarState::EPS_MOUSEHOLDING: { auto activePillar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock()); activePillar->SetPicking(true); if ( imp_.SavePos_.getDistanceFromSQ(imp_.CurrentPos_) > 100 * 100 ) { imp_.State_ = EPilarState::EPS_MOVING; imp_.Valid_ = true; } else if ( imp_.LMouseLeftUp_ ) { imp_.PropertyCallBack_ = boost::none; imp_.State_ = EPilarState::EPS_PROPERTY; auto pointer = reinterpret_cast<int>(static_cast<void*>(&(*imp_.EventInfo_))); ::PostMessage((HWND)GetRenderContextSPtr()->GetHandle(), WM_IRR_DLG_MSG, WM_USER_ROOMLAYOUT_PILLAR_PROPERTY, pointer); } } break; case EPilarState::EPS_PROPERTY: { if ( !imp_.PropertyCallBack_ ) { break; } auto activePillar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock()); switch (*(imp_.PropertyCallBack_)) { case EUT_ROOMLAYOUT_PILLAR_NONE: { imp_.State_ = EPilarState::EPS_SWEEPING; } break; case EUT_ROOMLAYOUT_PILLAR_UPDATE: { activePillar->SetSize(imp_.EventInfo_->XLength_, imp_.EventInfo_->YLength_, imp_.EventInfo_->ZLength_); activePillar->SetOffsetHeight(imp_.EventInfo_->OffsetHeight_); { auto curTrans = activePillar->GetTranslation(); curTrans.SetY(imp_.EventInfo_->YLength_/2 + imp_.EventInfo_->OffsetHeight_); activePillar->SetTranslation(curTrans); auto curPos = activePillar->GetDataSceneNode()->getPosition(); curPos.Y = static_cast<float>(imp_.EventInfo_->YLength_/2 + imp_.EventInfo_->OffsetHeight_); activePillar->GetDataSceneNode()->setPosition(curPos); } activePillar->UpdateMesh(); imp_.State_ = EPilarState::EPS_SWEEPING; } break; case EUT_ROOMLAYOUT_PILLAR_MOVE: { imp_.State_ = EPilarState::EPS_MOVING; } break; case EUT_ROOMLAYOUT_PILLAR_DELETE: { activePillar->RemoveFromParent(); imp_.State_ = EPilarState::EPS_SWEEPING; } break; default: assert(0); break; } } break; case EPilarState::EPS_CREATING_INIT: { assert(imp_.EventInfo_); auto newPilar = PillarODL::Create<PillarODL>(GetRenderContextSPtr()); newPilar->SetSize(imp_.EventInfo_->XLength_, imp_.EventInfo_->YLength_, imp_.EventInfo_->ZLength_); newPilar->SetOffsetHeight(imp_.EventInfo_->OffsetHeight_); newPilar->UpdateMesh(); RootODL_.lock()->AddChild(newPilar); auto newPos = imp_.CurrentPos_; newPos.Y = imp_.EventInfo_->YLength_/2; newPilar->SetTranslation(gp_XYZ(newPos.X, newPos.Y, newPos.Z)); newPilar->GetDataSceneNode()->setPosition(newPos); SetPickingODL(newPilar); imp_.State_ = EPilarState::EPS_MOVING; } break; case EPilarState::EPS_MOVING: { auto activePilar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock()); activePilar->SetPicking(true); activePilar->SetVaildPosition(imp_.Valid_); if ( imp_.LMouseLeftUp_ ) { if ( imp_.Valid_ ) { ImpUPtr_->Valid_ = false; ImpUPtr_->EventInfo_ = boost::none; imp_.State_ = EPilarState::EPS_SWEEPING; break; } } if ( imp_.EscapePressDown_ ) { activePilar->RemoveFromParent(); imp_.State_ = EPilarState::EPS_SWEEPING; break; } //当前柱的Box auto activeTransitionBox = activePilar->GetBaseBndBox(); { gp_Trsf tfs; tfs.SetTranslationPart(activePilar->GetTranslation()); activeTransitionBox = activeTransitionBox.Transformed(tfs); } activePilar->SetRotation(gp_Quaternion(gp::DZ(), gp::DZ())); activePilar->GetDataSceneNode()->setRotation(vector3df(0)); auto size = activePilar->GetSize(); auto offset = activePilar->GetOffsetHeight(); //新的位置 auto newPos = imp_.CurrentPos_; newPos.Y = static_cast<float>(size.Y()/2) + offset; gp_Pnt newPnt(newPos.X, newPos.Y, newPos.Z); //吸附距离 static auto alignDis = 200.0; //当前的吸附物体 auto alignODLs = activePilar->GetAlignList(); alignODLs.erase(std::remove_if(alignODLs.begin(), alignODLs.end(), [&activePilar, &activeTransitionBox](const BaseODLSPtr& alignODL) { if ( !alignODL ) { return true; } return alignODL->GetBaseBndBox().Distance(activeTransitionBox.Transformed(alignODL->GetAbsoluteTransform().Inverted())) > alignDis; }), alignODLs.end()); activePilar->SetAlignList(BaseODLList()); std::multimap<double,BaseODLSPtr> disMap; for ( auto& curODL : RootODL_.lock()->GetChildrenList() ) { if ( EODLT_PILLAR != curODL->GetType() && EODLT_WALL != curODL->GetType() ) { continue; } if ( std::find(alignODLs.begin(), alignODLs.end(), curODL) != alignODLs.end() ) { continue; } if ( EODLT_PILLAR == curODL->GetType() && curODL == activePilar ) { continue; } auto dis = curODL->GetBaseBndBox().Distance(activeTransitionBox.Transformed(curODL->GetAbsoluteTransform().Inverted())); if ( dis > alignDis ) { continue; } disMap.emplace(dis, curODL); } for ( auto& curODL : disMap ) { alignODLs.push_back(curODL.second); } //锁定旋转 auto lockRotation = false; //锁定位置 auto lockPosition = false; //移动方向 TopoDS_Edge movingEdge; for ( auto& curODL : alignODLs ) { auto alignTransformation = curODL->GetAbsoluteTransform(); //如果锁定了旋转,则调整柱的box auto activeRotationPillarBox = activePilar->GetBaseBndBox(); if ( lockRotation ) { gp_Trsf tfsODL, tfsPillar; tfsODL.SetRotation(alignTransformation.GetRotation()); tfsPillar.SetRotation(activePilar->GetRotation()); activeRotationPillarBox = activeRotationPillarBox.Transformed(tfsODL.Inverted() * tfsPillar); } Bnd_Box movingBox; { auto curBox = curODL->GetBaseBndBox(); Standard_Real xAlignMin,yAlignMin,zAlignMin,xAlignMax,yAlignMax,zAlignMax; curBox.Get(xAlignMin, yAlignMin, zAlignMin, xAlignMax, yAlignMax, zAlignMax); Standard_Real xPillarMin,yPillarMin,zPillarMin,xPillarMax,yPillarMax,zPillarMax; activeRotationPillarBox.Get(xPillarMin, yPillarMin, zPillarMin, xPillarMax, yPillarMax, zPillarMax); movingBox.Update(xAlignMin+xPillarMin, yAlignMin+yPillarMin, zAlignMin+zPillarMin, xAlignMax+xPillarMax, yAlignMax+yPillarMax, zAlignMax+zPillarMax); } auto inODLPnt = newPnt.Transformed(curODL->GetAbsoluteTransform().Inverted()); //当位置锁定了以后,只需要判断是不是相交 if ( lockPosition ) { if ( Standard_True == movingBox.IsOut(inODLPnt) ) { continue; } Bnd_Box pntBox; pntBox.Add(inODLPnt); if ( pntBox.Distance(movingBox) < Precision::Confusion() ) { continue; } imp_.Valid_ = false; break; } Bnd_Box alignODLBox; { auto curBox = curODL->GetBaseBndBox(); Standard_Real xAlignMin,yAlignMin,zAlignMin,xAlignMax,yAlignMax,zAlignMax; curBox.Get(xAlignMin, yAlignMin, zAlignMin, xAlignMax, yAlignMax, zAlignMax); Standard_Real xPillarMin,yPillarMin,zPillarMin,xPillarMax,yPillarMax,zPillarMax; activeRotationPillarBox.Get(xPillarMin, yPillarMin, zPillarMin, xPillarMax, yPillarMax, zPillarMax); alignODLBox.Update(xAlignMin+xPillarMin-alignDis, yAlignMin+yPillarMin-alignDis, zAlignMin+zPillarMin-alignDis, xAlignMax+xPillarMax+alignDis, yAlignMax+yPillarMax+alignDis, zAlignMax+zPillarMax+alignDis); } if ( Standard_True == alignODLBox.IsOut(inODLPnt) ) { continue; } //当前被停靠物体的box shape Standard_Real xMin,yMin,zMin,xMax,yMax,zMax; movingBox.Get(xMin, yMin, zMin, xMax, yMax, zMax); auto alignBoxShape = BRepPrimAPI_MakeBox(gp_Pnt(xMin, yMin, zMin), gp_Pnt(xMax, yMax, zMax)).Shape(); TopExp_Explorer exp(alignBoxShape, TopAbs_SHELL); if ( !lockRotation ) {//找到第一个被停靠物体 BRepExtrema_DistShapeShape dss(BRepBuilderAPI_MakeVertex(inODLPnt).Shape(), exp.Current()); assert(0 != dss.NbSolution()); inODLPnt = dss.PointOnShape2(1); newPnt = inODLPnt.Transformed(curODL->GetAbsoluteTransform()).XYZ(); auto rot = curODL->GetAbsoluteTransform().GetRotation(); Standard_Real rX,rY,rZ; rot.GetEulerAngles(gp_Extrinsic_XYZ, rX, rY, rZ); vector3df rotation(static_cast<float>(irr::core::radToDeg(rX)), static_cast<float>(irr::core::radToDeg(rY)), static_cast<float>(irr::core::radToDeg(rZ))); activePilar->GetDataSceneNode()->setRotation(rotation); activePilar->SetRotation(rot); gp_Dir movingDir; if ( std::abs(std::abs(inODLPnt.X()) - xMax) < Precision::Confusion() ) { movingDir = gp::DZ(); } else { movingDir = gp::DX(); } auto curMovingEdge = BRepBuilderAPI_MakeEdge(gp_Lin(inODLPnt, movingDir)).Edge(); movingEdge = TopoDS::Edge(curMovingEdge.Moved(curODL->GetAbsoluteTransform())); activePilar->AddAlign(curODL); imp_.Valid_ = true; lockRotation = true; } else {//第二个被停靠物体 BRepExtrema_DistShapeShape dss(movingEdge.Moved(curODL->GetAbsoluteTransform().Inverted()), exp.Current()); auto foundSecond = false; std::map<double, gp_Pnt> tmp; for ( auto index=1; index<=dss.NbSolution(); ++index ) { auto pntOnEdge = dss.PointOnShape1(index); auto pntOnBox = dss.PointOnShape2(index); if ( pntOnEdge.Distance(pntOnBox) > Precision::Confusion() ) { continue; } tmp.emplace(pntOnEdge.Distance(inODLPnt), pntOnEdge); foundSecond = true; } if ( !foundSecond ) { imp_.Valid_ = false; break; } newPnt = tmp.begin()->second.Transformed(curODL->GetAbsoluteTransform()); activePilar->AddAlign(curODL); lockPosition = true; } } if ( activePilar->GetAlignList().empty() ) { imp_.Valid_ = true; } newPos.X = static_cast<float>(newPnt.X()); newPos.Y = static_cast<float>(newPnt.Y()); newPos.Z = static_cast<float>(newPnt.Z()); activePilar->GetDataSceneNode()->setPosition(newPos); activePilar->SetTranslation(newPnt.XYZ()); for ( auto& curAlign : activePilar->GetAlignList() ) { curAlign->SetSweeping(true); } } break; default: break; } imp_.LMousePressDown_ = false; imp_.LMouseLeftUp_ = false; imp_.EscapePressDown_ = false; return false; }
void NETGENPlugin_Mesher::PrepareOCCgeometry(netgen::OCCGeometry& occgeo, const TopoDS_Shape& shape, SMESH_Mesh& mesh, list< SMESH_subMesh* > * meshedSM) { BRepTools::Clean (shape); try { #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 OCC_CATCH_SIGNALS; #endif BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh (shape, 0.01, true); } catch (Standard_Failure) { } Bnd_Box bb; BRepBndLib::Add (shape, bb); double x1,y1,z1,x2,y2,z2; bb.Get (x1,y1,z1,x2,y2,z2); MESSAGE("shape bounding box:\n" << "(" << x1 << " " << y1 << " " << z1 << ") " << "(" << x2 << " " << y2 << " " << z2 << ")"); netgen::Point<3> p1 = netgen::Point<3> (x1,y1,z1); netgen::Point<3> p2 = netgen::Point<3> (x2,y2,z2); occgeo.boundingbox = netgen::Box<3> (p1,p2); occgeo.shape = shape; occgeo.changed = 1; //occgeo.BuildFMap(); // fill maps of shapes of occgeo with not yet meshed subshapes // get root submeshes list< SMESH_subMesh* > rootSM; if ( SMESH_subMesh* sm = mesh.GetSubMeshContaining( shape )) { rootSM.push_back( sm ); } else { for ( TopoDS_Iterator it( shape ); it.More(); it.Next() ) rootSM.push_back( mesh.GetSubMesh( it.Value() )); } // add subshapes of empty submeshes list< SMESH_subMesh* >::iterator rootIt = rootSM.begin(), rootEnd = rootSM.end(); for ( ; rootIt != rootEnd; ++rootIt ) { SMESH_subMesh * root = *rootIt; SMESH_subMeshIteratorPtr smIt = root->getDependsOnIterator(/*includeSelf=*/true, /*complexShapeFirst=*/true); // to find a right orientation of subshapes (PAL20462) TopTools_IndexedMapOfShape subShapes; TopExp::MapShapes(root->GetSubShape(), subShapes); while ( smIt->more() ) { SMESH_subMesh* sm = smIt->next(); if ( !meshedSM || sm->IsEmpty() ) { TopoDS_Shape shape = sm->GetSubShape(); if ( shape.ShapeType() != TopAbs_VERTEX ) shape = subShapes( subShapes.FindIndex( shape ));// - shape->index->oriented shape switch ( shape.ShapeType() ) { case TopAbs_FACE : occgeo.fmap.Add( shape ); break; case TopAbs_EDGE : occgeo.emap.Add( shape ); break; case TopAbs_VERTEX: occgeo.vmap.Add( shape ); break; case TopAbs_SOLID :occgeo.somap.Add( shape ); break; default:; } } // collect submeshes of meshed shapes else if (meshedSM) { meshedSM->push_back( sm ); } } } occgeo.facemeshstatus.SetSize (occgeo.fmap.Extent()); occgeo.facemeshstatus = 0; }
//======================================================================= //function : PreciseBoundingBox //purpose : //======================================================================= Standard_Boolean GEOMUtils::PreciseBoundingBox (const TopoDS_Shape &theShape, Bnd_Box &theBox) { if ( theBox.IsVoid() ) BRepBndLib::Add( theShape, theBox ); if ( theBox.IsVoid() ) return Standard_False; Standard_Real aBound[6]; theBox.Get(aBound[0], aBound[2], aBound[4], aBound[1], aBound[3], aBound[5]); Standard_Integer i; const gp_Pnt aMid(0.5*(aBound[1] + aBound[0]), // XMid 0.5*(aBound[3] + aBound[2]), // YMid 0.5*(aBound[5] + aBound[4])); // ZMid const gp_XYZ aSize(aBound[1] - aBound[0], // DX aBound[3] - aBound[2], // DY aBound[5] - aBound[4]); // DZ const gp_Pnt aPnt[6] = { gp_Pnt(aBound[0] - (aBound[1] - aBound[0]), aMid.Y(), aMid.Z()), // XMin gp_Pnt(aBound[1] + (aBound[1] - aBound[0]), aMid.Y(), aMid.Z()), // XMax gp_Pnt(aMid.X(), aBound[2] - (aBound[3] - aBound[2]), aMid.Z()), // YMin gp_Pnt(aMid.X(), aBound[3] + (aBound[3] - aBound[2]), aMid.Z()), // YMax gp_Pnt(aMid.X(), aMid.Y(), aBound[4] - (aBound[5] - aBound[4])), // ZMin gp_Pnt(aMid.X(), aMid.Y(), aBound[5] + (aBound[5] - aBound[4])) // ZMax }; const gp_Dir aDir[3] = { gp::DX(), gp::DY(), gp::DZ() }; const Standard_Real aPlnSize[3] = { 0.5*Max(aSize.Y(), aSize.Z()), // XMin, XMax planes 0.5*Max(aSize.X(), aSize.Z()), // YMin, YMax planes 0.5*Max(aSize.X(), aSize.Y()) // ZMin, ZMax planes }; gp_Pnt aPMin[2]; for (i = 0; i < 6; i++) { const Standard_Integer iHalf = i/2; const gp_Pln aPln(aPnt[i], aDir[iHalf]); BRepBuilderAPI_MakeFace aMkFace(aPln, -aPlnSize[iHalf], aPlnSize[iHalf], -aPlnSize[iHalf], aPlnSize[iHalf]); if (!aMkFace.IsDone()) { return Standard_False; } TopoDS_Shape aFace = aMkFace.Shape(); // Get minimal distance between planar face and shape. Standard_Real aMinDist = GEOMUtils::GetMinDistance(aFace, theShape, aPMin[0], aPMin[1]); if (aMinDist < 0.) { return Standard_False; } aBound[i] = aPMin[1].Coord(iHalf + 1); } // Update Bounding box with the new values. theBox.SetVoid(); theBox.Update(aBound[0], aBound[2], aBound[4], aBound[1], aBound[3], aBound[5]); return Standard_True; }
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()); } } }
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; }