//======================================================================= //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; }
// create the PCB (board only) model using the current outlines and drill holes bool PCBMODEL::CreatePCB() { if( m_hasPCB ) { if( m_pcb_label.IsNull() ) return false; return true; } if( m_curves.empty() || m_mincurve == m_curves.end() ) { m_hasPCB = true; std::ostringstream ostr; #ifdef __WXDEBUG__ ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; #endif /* __WXDEBUG */ ostr << " * no valid board outline\n"; wxLogMessage( "%s", ostr.str().c_str() ); return false; } m_hasPCB = true; // whether or not operations fail we note that CreatePCB has been invoked TopoDS_Shape board; OUTLINE oln; // loop to assemble (represents PCB outline and cutouts) oln.SetMinSqDistance( m_minDistance2 ); oln.AddSegment( *m_mincurve ); m_curves.erase( m_mincurve ); while( !m_curves.empty() ) { if( oln.IsClosed() ) { if( board.IsNull() ) { if( !oln.MakeShape( board, m_thickness ) ) { std::ostringstream ostr; #ifdef __WXDEBUG__ ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; #endif /* __WXDEBUG */ ostr << " * could not create board extrusion\n"; wxLogMessage( "%s", ostr.str().c_str() ); return false; } } else { TopoDS_Shape hole; if( oln.MakeShape( hole, m_thickness ) ) { m_cutouts.push_back( hole ); } else { std::ostringstream ostr; #ifdef __WXDEBUG__ ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; #endif /* __WXDEBUG */ ostr << " * could not create board cutout\n"; wxLogMessage( "%s", ostr.str().c_str() ); } } oln.Clear(); if( !m_curves.empty() ) { oln.AddSegment( m_curves.front() ); m_curves.pop_front(); } continue; } std::list< KICADCURVE >::iterator sC = m_curves.begin(); std::list< KICADCURVE >::iterator eC = m_curves.end(); while( sC != eC ) { if( oln.AddSegment( *sC ) ) { m_curves.erase( sC ); break; } ++sC; } if( sC == eC && !oln.m_curves.empty() ) { std::ostringstream ostr; #ifdef __WXDEBUG__ ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; #endif /* __WXDEBUG */ ostr << " * could not close outline (dropping outline data with " << oln.m_curves.size() << " segments)\n"; for( const auto& c : oln.m_curves ) ostr << " + " << c.Describe() << "\n"; wxLogMessage( "%s", ostr.str().c_str() ); oln.Clear(); if( !m_curves.empty() ) { oln.AddSegment( m_curves.front() ); m_curves.pop_front(); } } } if( oln.IsClosed() ) { if( board.IsNull() ) { if( !oln.MakeShape( board, m_thickness ) ) { std::ostringstream ostr; #ifdef __WXDEBUG__ ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; #endif /* __WXDEBUG */ ostr << " * could not create board extrusion\n"; wxLogMessage( "%s", ostr.str().c_str() ); return false; } } else { TopoDS_Shape hole; if( oln.MakeShape( hole, m_thickness ) ) { m_cutouts.push_back( hole ); } else { std::ostringstream ostr; #ifdef __WXDEBUG__ ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; #endif /* __WXDEBUG */ ostr << " * could not create board cutout\n"; wxLogMessage( "%s", ostr.str().c_str() ); } } } // subtract cutouts (if any) for( auto i : m_cutouts ) board = BRepAlgoAPI_Cut( board, i ); // push the board to the data structure m_pcb_label = m_assy->AddComponent( m_assy_label, board ); if( m_pcb_label.IsNull() ) return false; // color the PCB Handle(XCAFDoc_ColorTool) color = XCAFDoc_DocumentTool::ColorTool( m_doc->Main () ); Quantity_Color pcb_green( 0.06, 0.4, 0.06, Quantity_TOC_RGB ); color->SetColor( m_pcb_label, pcb_green, XCAFDoc_ColorSurf ); TopExp_Explorer topex; topex.Init( m_assy->GetShape( m_pcb_label ), TopAbs_SOLID ); while( topex.More() ) { color->SetColor( topex.Current(), pcb_green, XCAFDoc_ColorSurf ); topex.Next(); } #if ( defined OCC_VERSION_HEX ) && ( OCC_VERSION_HEX > 0x070101 ) m_assy->UpdateAssemblies(); #endif return true; }
App::DocumentObjectExecReturn *Pipe::execute(void) { std::vector<TopoDS_Wire> wires; try { wires = getProfileWires(); } catch (const Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } TopoDS_Shape sketchshape = getVerifiedFace(); if (sketchshape.IsNull()) return new App::DocumentObjectExecReturn("Pipe: No valid sketch or face as first section"); else { //TODO: currently we only allow planar faces. the reason for this is that with other faces in front, we could //not use the current simulate approach and build the start and end face from the wires. As the shell //beginns always at the spine and not the profile, the sketchshape cannot be used directly as front face. //We would need a method to translate the frontshape to match the shell starting position somehow... TopoDS_Face face = TopoDS::Face(sketchshape); BRepAdaptor_Surface adapt(face); if(adapt.GetType() != GeomAbs_Plane) return new App::DocumentObjectExecReturn("Pipe: Only planar faces supportet"); } // if the Base property has a valid shape, fuse the pipe into it TopoDS_Shape base; try { base = getBaseShape(); } catch (const Base::Exception&) { base = TopoDS_Shape(); } try { //setup the location this->positionByPrevious(); TopLoc_Location invObjLoc = this->getLocation().Inverted(); if(!base.IsNull()) base.Move(invObjLoc); //build the paths App::DocumentObject* spine = Spine.getValue(); if (!(spine && spine->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))) return new App::DocumentObjectExecReturn("No spine linked."); std::vector<std::string> subedge = Spine.getSubValues(); TopoDS_Shape path; const Part::TopoShape& shape = static_cast<Part::Feature*>(spine)->Shape.getValue(); buildPipePath(shape, subedge, path); path.Move(invObjLoc); TopoDS_Shape auxpath; if(Mode.getValue()==3) { App::DocumentObject* auxspine = AuxillerySpine.getValue(); if (!(auxspine && auxspine->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))) return new App::DocumentObjectExecReturn("No auxillery spine linked."); std::vector<std::string> auxsubedge = AuxillerySpine.getSubValues(); TopoDS_Shape path; const Part::TopoShape& auxshape = static_cast<Part::Feature*>(auxspine)->Shape.getValue(); buildPipePath(auxshape, auxsubedge, auxpath); auxpath.Move(invObjLoc); } //build up multisections auto multisections = Sections.getValues(); std::vector<std::vector<TopoDS_Wire>> wiresections; for(TopoDS_Wire& wire : wires) wiresections.push_back(std::vector<TopoDS_Wire>(1, wire)); //maybe we need a sacling law Handle(Law_Function) scalinglaw; //see if we shall use multiple sections if(Transformation.getValue() == 1) { //TODO: we need to order the sections to prevent occ from crahsing, as makepieshell connects //the sections in the order of adding for(App::DocumentObject* obj : multisections) { if(!obj->isDerivedFrom(Part::Feature::getClassTypeId())) return new App::DocumentObjectExecReturn("All sections need to be part features"); TopExp_Explorer ex; size_t i=0; for (ex.Init(static_cast<Part::Feature*>(obj)->Shape.getValue(), TopAbs_WIRE); ex.More(); ex.Next()) { wiresections[i].push_back(TopoDS::Wire(ex.Current())); if(i>=wiresections.size()) return new App::DocumentObjectExecReturn("Multisections need to have the same amount of inner wires as the base section"); ++i; } if(i<wiresections.size()) return new App::DocumentObjectExecReturn("Multisections need to have the same amount of inner wires as the base section"); } } /*//build the law functions instead else if(Transformation.getValue() == 2) { if(ScalingData.getValues().size()<1) return new App::DocumentObjectExecReturn("No valid data given for liinear scaling mode"); Handle(Law_Linear) lin = new Law_Linear(); lin->Set(0,1,1,ScalingData[0].x); scalinglaw = lin; } else if(Transformation.getValue() == 3) { if(ScalingData.getValues().size()<1) return new App::DocumentObjectExecReturn("No valid data given for S-shape scaling mode"); Handle(Law_S) s = new Law_S(); s->Set(0,1,ScalingData[0].y, 1, ScalingData[0].x, ScalingData[0].z); scalinglaw = s; }*/ //build all shells std::vector<TopoDS_Shape> shells; std::vector<TopoDS_Wire> frontwires, backwires; for(std::vector<TopoDS_Wire>& wires : wiresections) { BRepOffsetAPI_MakePipeShell mkPS(TopoDS::Wire(path)); setupAlgorithm(mkPS, auxpath); if(!scalinglaw) { for(TopoDS_Wire& wire : wires) { wire.Move(invObjLoc); mkPS.Add(wire); } } else { for(TopoDS_Wire& wire : wires) { wire.Move(invObjLoc); mkPS.SetLaw(wire, scalinglaw); } } if (!mkPS.IsReady()) return new App::DocumentObjectExecReturn("pipe could not be build"); //build the shell use simulate to get the top and bottom wires in an easy way shells.push_back(mkPS.Shape()); TopTools_ListOfShape sim; mkPS.Simulate(2, sim); frontwires.push_back(TopoDS::Wire(sim.First())); backwires.push_back(TopoDS::Wire(sim.Last())); } //build the top and bottom face, sew the shell and build the final solid TopoDS_Shape front = makeFace(frontwires); TopoDS_Shape back = makeFace(backwires); BRepBuilderAPI_Sewing sewer; sewer.SetTolerance(Precision::Confusion()); sewer.Add(front); sewer.Add(back); for(TopoDS_Shape& s : shells) sewer.Add(s); sewer.Perform(); //build the solid BRepBuilderAPI_MakeSolid mkSolid; mkSolid.Add(TopoDS::Shell(sewer.SewedShape())); if(!mkSolid.IsDone()) return new App::DocumentObjectExecReturn("Result is not a solid"); TopoDS_Shape result = mkSolid.Shape(); BRepClass3d_SolidClassifier SC(result); SC.PerformInfinitePoint(Precision::Confusion()); if ( SC.State() == TopAbs_IN) { result.Reverse(); } //result.Move(invObjLoc); AddSubShape.setValue(result); if(base.IsNull()) { Shape.setValue(result); return App::DocumentObject::StdReturn; } if(getAddSubType() == FeatureAddSub::Additive) { BRepAlgoAPI_Fuse mkFuse(base, result); if (!mkFuse.IsDone()) return new App::DocumentObjectExecReturn("Adding the pipe failed"); // we have to get the solids (fuse sometimes creates compounds) TopoDS_Shape boolOp = this->getSolid(mkFuse.Shape()); // lets check if the result is a solid if (boolOp.IsNull()) return new App::DocumentObjectExecReturn("Resulting shape is not a solid"); boolOp = refineShapeIfActive(boolOp); Shape.setValue(boolOp); } else if(getAddSubType() == FeatureAddSub::Subtractive) { BRepAlgoAPI_Cut mkCut(base, result); if (!mkCut.IsDone()) return new App::DocumentObjectExecReturn("Subtracting the pipe failed"); // we have to get the solids (fuse sometimes creates compounds) TopoDS_Shape boolOp = this->getSolid(mkCut.Shape()); // lets check if the result is a solid if (boolOp.IsNull()) return new App::DocumentObjectExecReturn("Resulting shape is not a solid"); boolOp = refineShapeIfActive(boolOp); Shape.setValue(boolOp); } return App::DocumentObject::StdReturn; return ProfileBased::execute(); } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); return new App::DocumentObjectExecReturn(e->GetMessageString()); } catch (...) { return new App::DocumentObjectExecReturn("A fatal error occurred when making the pipe"); } }
void PovTools::writeShape(std::ostream &out, const char *PartName, const TopoDS_Shape& Shape, float fMeshDeviation) { Base::Console().Log("Meshing with Deviation: %f\n",fMeshDeviation); TopExp_Explorer ex; BRepMesh_IncrementalMesh MESH(Shape,fMeshDeviation); // counting faces and start sequencer int l = 1; for (ex.Init(Shape, TopAbs_FACE); ex.More(); ex.Next(),l++) {} Base::SequencerLauncher seq("Writing file", l); // write the file out << "// Written by FreeCAD http://www.freecadweb.org/" << endl; l = 1; for (ex.Init(Shape, TopAbs_FACE); ex.More(); ex.Next(),l++) { // get the shape and mesh it const TopoDS_Face& aFace = TopoDS::Face(ex.Current()); // this block mesh the face and transfers it in a C array of vertices and face indexes Standard_Integer nbNodesInFace,nbTriInFace; gp_Vec* vertices=0; gp_Vec* vertexnormals=0; long* cons=0; transferToArray(aFace,&vertices,&vertexnormals,&cons,nbNodesInFace,nbTriInFace); if (!vertices) break; // writing per face header out << "// face number" << l << " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl << "#declare " << PartName << l << " = mesh2{" << endl << " vertex_vectors {" << endl << " " << nbNodesInFace << "," << endl; // writing vertices for (int i=0; i < nbNodesInFace; i++) { out << " <" << vertices[i].X() << "," << vertices[i].Z() << "," << vertices[i].Y() << ">," << endl; } out << " }" << endl // writing per vertex normals << " normal_vectors {" << endl << " " << nbNodesInFace << "," << endl; for (int j=0; j < nbNodesInFace; j++) { out << " <" << vertexnormals[j].X() << "," << vertexnormals[j].Z() << "," << vertexnormals[j].Y() << ">," << endl; } out << " }" << endl // writing triangle indices << " face_indices {" << endl << " " << nbTriInFace << "," << endl; for (int k=0; k < nbTriInFace; k++) { out << " <" << cons[3*k] << ","<< cons[3*k+2] << ","<< cons[3*k+1] << ">," << endl; } // end of face out << " }" << endl << "} // end of Face"<< l << endl << endl; delete [] vertexnormals; delete [] vertices; delete [] cons; seq.next(); } // end of face loop out << endl << endl << "// Declare all together +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl << "#declare " << PartName << " = union {" << endl; for (int i=1; i < l; i++) { out << "mesh2{ " << PartName << i << "}" << endl; } out << "}" << endl; }
App::DocumentObjectExecReturn *FeatureShape::execute(void) { TopoDS_Shape shape = Shape.getValue(); if (!shape.IsNull()) { if (shape.ShapeType() == TopAbs_WIRE) { Path::Toolpath result; bool first = true; Base::Placement last; TopExp_Explorer ExpEdges (shape,TopAbs_EDGE); while (ExpEdges.More()) { const TopoDS_Edge& edge = TopoDS::Edge(ExpEdges.Current()); TopExp_Explorer ExpVerts(edge,TopAbs_VERTEX); bool vfirst = true; while (ExpVerts.More()) { const TopoDS_Vertex& vert = TopoDS::Vertex(ExpVerts.Current()); gp_Pnt pnt = BRep_Tool::Pnt(vert); Base::Placement tpl; tpl.setPosition(Base::Vector3d(pnt.X(),pnt.Y(),pnt.Z())); if (first) { // add first point as a G0 move Path::Command cmd; std::ostringstream ctxt; ctxt << "G0 X" << tpl.getPosition().x << " Y" << tpl.getPosition().y << " Z" << tpl.getPosition().z; cmd.setFromGCode(ctxt.str()); result.addCommand(cmd); first = false; vfirst = false; } else { if (vfirst) vfirst = false; else { Path::Command cmd; cmd.setFromPlacement(tpl); // write arc data if needed BRepAdaptor_Curve adapt(edge); if (adapt.GetType() == GeomAbs_Circle) { gp_Circ circ = adapt.Circle(); gp_Pnt c = circ.Location(); bool clockwise = false; gp_Dir n = circ.Axis().Direction(); if (n.Z() < 0) clockwise = true; Base::Vector3d center = Base::Vector3d(c.X(),c.Y(),c.Z()); // center coords must be relative to last point center -= last.getPosition(); cmd.setCenter(center,clockwise); } result.addCommand(cmd); } } ExpVerts.Next(); last = tpl; } ExpEdges.Next(); } Path.setValue(result); } } return App::DocumentObject::StdReturn; }
const bool SketchBased::checkLineCrossesFace(const gp_Lin &line, const TopoDS_Face &face) { #if 1 BRepBuilderAPI_MakeEdge mkEdge(line); TopoDS_Wire wire = ShapeAnalysis::OuterWire(face); BRepExtrema_DistShapeShape distss(wire, mkEdge.Shape(), Precision::Confusion()); if (distss.IsDone()) { if (distss.Value() > Precision::Confusion()) return false; // build up map vertex->edge TopTools_IndexedDataMapOfShapeListOfShape vertex2Edge; TopExp::MapShapesAndAncestors(wire, TopAbs_VERTEX, TopAbs_EDGE, vertex2Edge); for (Standard_Integer i=1; i<= distss.NbSolution(); i++) { if (distss.PointOnShape1(i).Distance(distss.PointOnShape2(i)) > Precision::Confusion()) continue; BRepExtrema_SupportType type = distss.SupportTypeShape1(i); if (type == BRepExtrema_IsOnEdge) { TopoDS_Edge edge = TopoDS::Edge(distss.SupportOnShape1(i)); BRepAdaptor_Curve adapt(edge); // create a plane (pnt,dir) that goes through the intersection point and is built of // the vectors of the sketch normal and the rotation axis const gp_Dir& normal = BRepAdaptor_Surface(face).Plane().Axis().Direction(); gp_Dir dir = line.Direction().Crossed(normal); gp_Pnt pnt = distss.PointOnShape1(i); Standard_Real t; distss.ParOnEdgeS1(i, t); gp_Pnt p_eps1 = adapt.Value(std::max<double>(adapt.FirstParameter(), t-10*Precision::Confusion())); gp_Pnt p_eps2 = adapt.Value(std::min<double>(adapt.LastParameter(), t+10*Precision::Confusion())); // now check if we get a change in the sign of the distances Standard_Real dist_p_eps1_pnt = gp_Vec(p_eps1, pnt).Dot(gp_Vec(dir)); Standard_Real dist_p_eps2_pnt = gp_Vec(p_eps2, pnt).Dot(gp_Vec(dir)); // distance to the plane must be noticable if (fabs(dist_p_eps1_pnt) > 5*Precision::Confusion() && fabs(dist_p_eps2_pnt) > 5*Precision::Confusion()) { if (dist_p_eps1_pnt * dist_p_eps2_pnt < 0) return true; } } else if (type == BRepExtrema_IsVertex) { // for a vertex check the two adjacent edges if there is a change of sign TopoDS_Vertex vertex = TopoDS::Vertex(distss.SupportOnShape1(i)); const TopTools_ListOfShape& edges = vertex2Edge.FindFromKey(vertex); if (edges.Extent() == 2) { // create a plane (pnt,dir) that goes through the intersection point and is built of // the vectors of the sketch normal and the rotation axis BRepAdaptor_Surface adapt(face); const gp_Dir& normal = adapt.Plane().Axis().Direction(); gp_Dir dir = line.Direction().Crossed(normal); gp_Pnt pnt = distss.PointOnShape1(i); // from the first edge get a point next to the intersection point const TopoDS_Edge& edge1 = TopoDS::Edge(edges.First()); BRepAdaptor_Curve adapt1(edge1); Standard_Real dist1 = adapt1.Value(adapt1.FirstParameter()).SquareDistance(pnt); Standard_Real dist2 = adapt1.Value(adapt1.LastParameter()).SquareDistance(pnt); gp_Pnt p_eps1; if (dist1 < dist2) p_eps1 = adapt1.Value(adapt1.FirstParameter() + 2*Precision::Confusion()); else p_eps1 = adapt1.Value(adapt1.LastParameter() - 2*Precision::Confusion()); // from the second edge get a point next to the intersection point const TopoDS_Edge& edge2 = TopoDS::Edge(edges.Last()); BRepAdaptor_Curve adapt2(edge2); Standard_Real dist3 = adapt2.Value(adapt2.FirstParameter()).SquareDistance(pnt); Standard_Real dist4 = adapt2.Value(adapt2.LastParameter()).SquareDistance(pnt); gp_Pnt p_eps2; if (dist3 < dist4) p_eps2 = adapt2.Value(adapt2.FirstParameter() + 2*Precision::Confusion()); else p_eps2 = adapt2.Value(adapt2.LastParameter() - 2*Precision::Confusion()); // now check if we get a change in the sign of the distances Standard_Real dist_p_eps1_pnt = gp_Vec(p_eps1, pnt).Dot(gp_Vec(dir)); Standard_Real dist_p_eps2_pnt = gp_Vec(p_eps2, pnt).Dot(gp_Vec(dir)); // distance to the plane must be noticable if (fabs(dist_p_eps1_pnt) > Precision::Confusion() && fabs(dist_p_eps2_pnt) > Precision::Confusion()) { if (dist_p_eps1_pnt * dist_p_eps2_pnt < 0) return true; } } } } } return false; #else // This is not as easy as it looks, because a distance of zero might be OK if // the axis touches the sketchshape in in a linear edge or a vertex // Note: This algorithm does not catch cases where the sketchshape touches the // axis in two or more points // Note: And it only works on closed outer wires TopoDS_Wire outerWire = ShapeAnalysis::OuterWire(face); BRepBuilderAPI_MakeEdge mkEdge(line); if (!mkEdge.IsDone()) throw Base::Exception("Revolve: Unexpected OCE failure"); BRepAdaptor_Curve axis(TopoDS::Edge(mkEdge.Shape())); TopExp_Explorer ex; int intersections = 0; std::vector<gp_Pnt> intersectionpoints; // Note: We need to look at evey edge separately to catch coincident lines for (ex.Init(outerWire, TopAbs_EDGE); ex.More(); ex.Next()) { BRepAdaptor_Curve edge(TopoDS::Edge(ex.Current())); Extrema_ExtCC intersector(axis, edge); if (intersector.IsDone()) { for (int i = 1; i <= intersector.NbExt(); i++) { #if OCC_VERSION_HEX >= 0x060500 if (intersector.SquareDistance(i) < Precision::Confusion()) { #else if (intersector.Value(i) < Precision::Confusion()) { #endif if (intersector.IsParallel()) { // A line that is coincident with the axis produces three intersections // 1 with the line itself and 2 with the adjacent edges intersections -= 2; } else { Extrema_POnCurv p1, p2; intersector.Points(i, p1, p2); intersectionpoints.push_back(p1.Value()); intersections++; } } } } } // Note: We might check this inside the loop but then we have to rely on TopExp_Explorer // returning the wire's edges in adjacent order (because of the coincident line checking) if (intersections > 1) { // Check that we don't touch the sketchface just in two identical vertices if ((intersectionpoints.size() == 2) && (intersectionpoints[0].IsEqual(intersectionpoints[1], Precision::Confusion()))) return false; else return true; } return false; #endif } void SketchBased::remapSupportShape(const TopoDS_Shape& newShape) { TopTools_IndexedMapOfShape faceMap; TopExp::MapShapes(newShape, TopAbs_FACE, faceMap); // here we must reset the placement otherwise the geometric matching doesn't work Part::TopoShape shape = this->Shape.getValue(); shape._Shape.Location(TopLoc_Location()); std::vector<App::DocumentObject*> refs = this->getInList(); for (std::vector<App::DocumentObject*>::iterator it = refs.begin(); it != refs.end(); ++it) { std::vector<App::Property*> props; (*it)->getPropertyList(props); for (std::vector<App::Property*>::iterator jt = props.begin(); jt != props.end(); ++jt) { if (!(*jt)->isDerivedFrom(App::PropertyLinkSub::getClassTypeId())) continue; App::PropertyLinkSub* link = static_cast<App::PropertyLinkSub*>(*jt); if (link->getValue() != this) continue; std::vector<std::string> subValues = link->getSubValues(); std::vector<std::string> newSubValues; for (std::vector<std::string>::iterator it = subValues.begin(); it != subValues.end(); ++it) { std::string shapetype; if (it->size() > 4 && it->substr(0,4) == "Face") { shapetype = "Face"; } else if (it->size() > 4 && it->substr(0,4) == "Edge") { shapetype = "Edge"; } else if (it->size() > 6 && it->substr(0,6) == "Vertex") { shapetype = "Vertex"; } else { newSubValues.push_back(*it); continue; } bool success = false; TopoDS_Shape element; try { element = shape.getSubShape(it->c_str()); } catch (Standard_Failure) { // This shape doesn't even exist, so no chance to do some tests newSubValues.push_back(*it); continue; } try { // as very first test check if old face and new face are parallel planes TopoDS_Shape newElement = Part::TopoShape(newShape).getSubShape(it->c_str()); if (isParallelPlane(element, newElement)) { newSubValues.push_back(*it); success = true; } } catch (Standard_Failure) { } // try an exact matching if (!success) { for (int i=1; i<faceMap.Extent(); i++) { if (isQuasiEqual(element, faceMap.FindKey(i))) { std::stringstream str; str << shapetype << i; newSubValues.push_back(str.str()); success = true; break; } } } // if an exact matching fails then try to compare only the geometries if (!success) { for (int i=1; i<faceMap.Extent(); i++) { if (isEqualGeometry(element, faceMap.FindKey(i))) { std::stringstream str; str << shapetype << i; newSubValues.push_back(str.str()); success = true; break; } } } // the new shape couldn't be found so keep the old sub-name if (!success) newSubValues.push_back(*it); } link->setValue(this, newSubValues); } } }
//======================================================================= // function: Perform // purpose: //======================================================================= void GEOMAlgo_WireSplitter::Perform() { myErrorStatus=2; myNothingToDo=Standard_True; Standard_Integer index, i, aNb, aCntIn, aCntOut; Standard_Boolean anIsIn; Standard_Real anAngle; BOP_ListOfEdgeInfo emptyInfo; TopTools_ListIteratorOfListOfShape anItList; // // 1.Filling mySmartMap mySmartMap.Clear(); anItList.Initialize(myEdges); for (; anItList.More(); anItList.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge(anItList.Value()); // if (!BOPTools_Tools2D::HasCurveOnSurface (anEdge, myFace)) { continue; } // TopExp_Explorer anExpVerts (anEdge, TopAbs_VERTEX); for (; anExpVerts.More(); anExpVerts.Next()) { const TopoDS_Shape& aVertex= anExpVerts.Current(); index = mySmartMap.FindIndex(aVertex); if (!index) { index=mySmartMap.Add(aVertex, emptyInfo); } BOP_ListOfEdgeInfo& aListOfEInfo=mySmartMap(index); BOP_EdgeInfo aEInfo; aEInfo.SetEdge(anEdge); TopAbs_Orientation anOr=aVertex.Orientation(); if (anOr==TopAbs_FORWARD) { aEInfo.SetInFlag(Standard_False); } else if (anOr==TopAbs_REVERSED) { aEInfo.SetInFlag(Standard_True); } aListOfEInfo.Append(aEInfo); } } // aNb=mySmartMap.Extent(); // // 2. myNothingToDo myNothingToDo=Standard_True; for (i=1; i<=aNb; i++) { aCntIn=0; aCntOut=0; const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i); BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo); for (; anIt.More(); anIt.Next()) { const BOP_EdgeInfo& anEdgeInfo=anIt.Value(); anIsIn=anEdgeInfo.IsIn(); if (anIsIn) { aCntIn++; } else { aCntOut++; } } if (aCntIn!=1 || aCntOut!=1) { myNothingToDo=Standard_False; break; } } // // Each vertex has one edge In and one - Out. Good. But it is not enought // to consider that nothing to do with this. We must check edges on TShape // coinsidence. If there are such edges there is something to do with. // if (myNothingToDo) { Standard_Integer aNbE, aNbMapEE; TopTools_IndexedDataMapOfShapeListOfShape aMapEE; aNbE=myEdges.Extent(); anItList.Initialize(myEdges); for (; anItList.More(); anItList.Next()) { const TopoDS_Shape& aE = anItList.Value(); if (!aMapEE.Contains(aE)) { TopTools_ListOfShape aLEx; aLEx.Append(aE); aMapEE.Add(aE, aLEx); } else { TopTools_ListOfShape& aLEx=aMapEE.ChangeFromKey(aE); aLEx.Append(aE); } } Standard_Boolean bFlag; bFlag=Standard_True; aNbMapEE=aMapEE.Extent(); for (i=1; i<=aNbMapEE; i++) { const TopTools_ListOfShape& aLEx=aMapEE(i); aNbE=aLEx.Extent(); if (aNbE==1) { // usual case continue; } else if (aNbE==2){ const TopoDS_Shape& aE1=aLEx.First(); const TopoDS_Shape& aE2=aLEx.Last(); if (aE1.IsSame(aE2)) { bFlag=Standard_False; break; } } else { bFlag=Standard_False; break; } } myNothingToDo=myNothingToDo && bFlag; } // // if (myNothingToDo) { myErrorStatus=0; return; } // // 3. Angles in mySmartMap BRepAdaptor_Surface aBAS(myFace); const GeomAdaptor_Surface& aGAS=aBAS.Surface(); for (i=1; i<=aNb; i++) { const TopoDS_Vertex& aV=TopoDS::Vertex (mySmartMap.FindKey(i)); const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i); BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo); for (; anIt.More(); anIt.Next()) { BOP_EdgeInfo& anEdgeInfo=anIt.Value(); const TopoDS_Edge& aE=anEdgeInfo.Edge(); // TopoDS_Vertex aVV=aV; // anIsIn=anEdgeInfo.IsIn(); if (anIsIn) { // aVV.Orientation(TopAbs_REVERSED); anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_True); } // else { // OUT // aVV.Orientation(TopAbs_FORWARD); anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_False); } anEdgeInfo.SetAngle(anAngle); } } // // 4. Do // Standard_Boolean anIsOut, anIsNotPassed; TopTools_SequenceOfShape aLS, aVertVa; TColgp_SequenceOfPnt2d aCoordVa; BOP_ListIteratorOfListOfEdgeInfo anIt; for (i=1; i<=aNb; i++) { const TopoDS_Vertex aVa=TopoDS::Vertex (mySmartMap.FindKey(i)); const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap(i); anIt.Initialize(aLEInfo); for (; anIt.More(); anIt.Next()) { BOP_EdgeInfo& anEdgeInfo=anIt.Value(); const TopoDS_Edge& aEOuta=anEdgeInfo.Edge(); anIsOut=!anEdgeInfo.IsIn(); anIsNotPassed=!anEdgeInfo.Passed(); if (anIsOut && anIsNotPassed) { // aLS.Clear(); aVertVa.Clear(); aCoordVa.Clear(); // Path(aGAS, myFace, aVa, aEOuta, anEdgeInfo, aLS, aVertVa, aCoordVa, myShapes, mySmartMap); } } } // { Standard_Integer aNbV, aNbE; TopoDS_Vertex aV1, aV2; BOPTColStd_ListOfListOfShape aShapes; BOPTColStd_ListIteratorOfListOfListOfShape anItW(myShapes); for (; anItW.More(); anItW.Next()) { TopTools_IndexedMapOfShape aMV, aME; const TopTools_ListOfShape& aLE=anItW.Value(); TopTools_ListIteratorOfListOfShape anItE(aLE); for (; anItE.More(); anItE.Next()) { const TopoDS_Edge& aE=TopoDS::Edge(anItE.Value()); aME.Add(aE); TopExp::Vertices(aE, aV1, aV2); aMV.Add(aV1); aMV.Add(aV2); } aNbV=aMV.Extent(); aNbE=aME.Extent(); if (aNbV<=aNbE) { aShapes.Append(aLE); } } // myShapes.Clear(); anItW.Initialize(aShapes); for (; anItW.More(); anItW.Next()) { const TopTools_ListOfShape& aLE=anItW.Value(); myShapes.Append(aLE); } } // myErrorStatus=0; }
void SketchBased::getUpToFace(TopoDS_Face& upToFace, const TopoDS_Shape& support, const TopoDS_Face& supportface, const TopoDS_Shape& sketchshape, const std::string& method, const gp_Dir& dir) { if ((method == "UpToLast") || (method == "UpToFirst")) { // Check for valid support object if (support.IsNull()) throw Base::Exception("SketchBased: Up to face: No support in Sketch!"); std::vector<Part::cutFaces> cfaces = Part::findAllFacesCutBy(support, sketchshape, dir); if (cfaces.empty()) throw Base::Exception("SketchBased: Up to face: No faces found in this direction"); // Find nearest/furthest face std::vector<Part::cutFaces>::const_iterator it, it_near, it_far; it_near = it_far = cfaces.begin(); for (it = cfaces.begin(); it != cfaces.end(); it++) if (it->distsq > it_far->distsq) it_far = it; else if (it->distsq < it_near->distsq) it_near = it; upToFace = (method == "UpToLast" ? it_far->face : it_near->face); } // Remove the limits of the upToFace so that the extrusion works even if sketchshape is larger // than the upToFace bool remove_limits = false; TopExp_Explorer Ex; for (Ex.Init(sketchshape,TopAbs_FACE); Ex.More(); Ex.Next()) { // Get outermost wire of sketch face TopoDS_Face sketchface = TopoDS::Face(Ex.Current()); TopoDS_Wire outerWire = ShapeAnalysis::OuterWire(sketchface); if (!checkWireInsideFace(outerWire, upToFace, dir)) { remove_limits = true; break; } } if (remove_limits) { // Note: Using an unlimited face every time gives unnecessary failures for concave faces TopLoc_Location loc = upToFace.Location(); BRepAdaptor_Surface adapt(upToFace, Standard_False); BRepBuilderAPI_MakeFace mkFace(adapt.Surface().Surface() #if OCC_VERSION_HEX >= 0x060502 , Precision::Confusion() #endif ); if (!mkFace.IsDone()) throw Base::Exception("SketchBased: Up To Face: Failed to create unlimited face"); upToFace = TopoDS::Face(mkFace.Shape()); upToFace.Location(loc); } // Check that the upToFace does not intersect the sketch face and // is not parallel to the extrusion direction (for simplicity, supportface is used instead of sketchshape) BRepAdaptor_Surface adapt1(TopoDS::Face(supportface)); BRepAdaptor_Surface adapt2(TopoDS::Face(upToFace)); if (adapt2.GetType() == GeomAbs_Plane) { if (adapt1.Plane().Axis().IsNormal(adapt2.Plane().Axis(), Precision::Confusion())) throw Base::Exception("SketchBased: Up to face: Must not be parallel to extrusion direction!"); } // We must measure from sketchshape, not supportface, here BRepExtrema_DistShapeShape distSS(sketchshape, upToFace); if (distSS.Value() < Precision::Confusion()) throw Base::Exception("SketchBased: Up to face: Must not intersect sketch!"); }
int OCCFace::boolean(OCCSolid *tool, BoolOpType op) { try { TopoDS_Shape shape; switch (op) { case BOOL_CUT: { BRepAlgoAPI_Cut CU (this->getShape(), tool->getShape()); if (!CU.IsDone()) Standard_ConstructionError::Raise("operation failed"); shape = CU.Shape(); break; } case BOOL_COMMON: { BRepAlgoAPI_Common CO (this->getShape(), tool->getShape()); if (!CO.IsDone()) Standard_ConstructionError::Raise("operation failed"); shape = CO.Shape(); break; } default: Standard_ConstructionError::Raise("unknown operation"); break; } // extract single face or single shell int idx = 0; TopExp_Explorer exBO; for (exBO.Init(shape, TopAbs_SHELL); exBO.More(); exBO.Next()) { if (idx > 0) { Standard_ConstructionError::Raise("multiple object in result"); } const TopoDS_Shape& cur = exBO.Current(); this->setShape(cur); idx++; } if (idx == 0) { idx = 0; for (exBO.Init(shape, TopAbs_FACE); exBO.More(); exBO.Next()) { if (idx > 0) { Standard_ConstructionError::Raise("multiple object in result"); } const TopoDS_Shape& cur = exBO.Current(); this->setShape(cur); idx++; } } if (idx == 0) StdFail_NotDone::Raise("no results from boolean operation");; this->setShape(shape); // possible fix shape if (!this->fixShape()) StdFail_NotDone::Raise("Shapes not valid"); } 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 in boolean operation"); } return 0; } return 1; }
int EG_saveModel(const egObject *model, const char *name) { int i, len, outLevel; egadsModel *mshape; FILE *fp; if (model == NULL) return EGADS_NULLOBJ; if (model->magicnumber != MAGIC) return EGADS_NOTOBJ; if (model->oclass != MODEL) return EGADS_NOTMODEL; outLevel = EG_outLevel(model); if (name == NULL) { if (outLevel > 0) printf(" EGADS Warning: NULL Filename (EG_saveModel)!\n"); return EGADS_NONAME; } /* does file exist? */ fp = fopen(name, "r"); if (fp != NULL) { if (outLevel > 0) printf(" EGADS Warning: File %s Exists (EG_saveModel)!\n", name); fclose(fp); return EGADS_NOTFOUND; } /* find extension */ len = strlen(name); for (i = len-1; i > 0; i--) if (name[i] == '.') break; if (i == 0) { if (outLevel > 0) printf(" EGADS Warning: No Extension in %s (EG_saveModel)!\n", name); return EGADS_NODATA; } mshape = (egadsModel *) model->blind; if ((strcasecmp(&name[i],".step") == 0) || (strcasecmp(&name[i],".stp") == 0)) { /* STEP files */ STEPControl_Writer aWriter; TopExp_Explorer Exp; const STEPControl_StepModelType aVal = STEPControl_AsIs; for (Exp.Init(mshape->shape, TopAbs_WIRE, TopAbs_FACE); Exp.More(); Exp.Next()) aWriter.Transfer(Exp.Current(), aVal); for (Exp.Init(mshape->shape, TopAbs_FACE, TopAbs_SHELL); Exp.More(); Exp.Next()) aWriter.Transfer(Exp.Current(), aVal); for (Exp.Init(mshape->shape, TopAbs_SHELL, TopAbs_SOLID); Exp.More(); Exp.Next()) aWriter.Transfer(Exp.Current(), aVal); for (Exp.Init(mshape->shape, TopAbs_SOLID); Exp.More(); Exp.Next()) aWriter.Transfer(Exp.Current(), aVal); if (!aWriter.Write(name)) { printf(" EGADS Warning: STEP Write Error (EG_saveModel)!\n"); return EGADS_WRITERR; } } else if ((strcasecmp(&name[i],".iges") == 0) || (strcasecmp(&name[i],".igs") == 0)) { /* IGES files */ try { IGESControl_Controller::Init(); IGESControl_Writer iWrite; TopExp_Explorer Exp; for (Exp.Init(mshape->shape, TopAbs_WIRE, TopAbs_FACE); Exp.More(); Exp.Next()) iWrite.AddShape(Exp.Current()); for (Exp.Init(mshape->shape, TopAbs_FACE, TopAbs_SHELL); Exp.More(); Exp.Next()) iWrite.AddShape(Exp.Current()); for (Exp.Init(mshape->shape, TopAbs_SHELL, TopAbs_SOLID); Exp.More(); Exp.Next()) iWrite.AddShape(Exp.Current()); for (Exp.Init(mshape->shape, TopAbs_SOLID); Exp.More(); Exp.Next()) iWrite.AddShape(Exp.Current()); iWrite.ComputeModel(); if (!iWrite.Write(name)) { printf(" EGADS Warning: IGES Write Error (EG_saveModel)!\n"); return EGADS_WRITERR; } } catch (...) { printf(" EGADS Warning: Internal IGES Write Error (EG_saveModel)!\n"); return EGADS_WRITERR; } } else if ((strcasecmp(&name[i],".brep") == 0) || (strcasecmp(&name[i],".egads") == 0)) { /* Native OCC file or our filetype */ if (!BRepTools::Write(mshape->shape, name)) { printf(" EGADS Warning: OCC Write Error (EG_saveModel)!\n"); return EGADS_WRITERR; } if (strcasecmp(&name[i],".brep") == 0) return EGADS_SUCCESS; /* append the attributes -- output in the read order */ FILE *fp = fopen(name, "a"); if (fp == NULL) { printf(" EGADS Warning: EGADS Open Error (EG_saveModel)!\n"); return EGADS_WRITERR; } fprintf(fp, "\n##EGADS HEADER FILE-REV 1 ##\n"); /* write model attributes */ EG_writeAttrs(model, fp); TopExp_Explorer Exp; for (Exp.Init(mshape->shape, TopAbs_WIRE, TopAbs_FACE); Exp.More(); Exp.Next()) { TopoDS_Shape shape = Exp.Current(); for (i = 0; i < mshape->nbody; i++) { egObject *obj = mshape->bodies[i]; egadsBody *pbody = (egadsBody *) obj->blind; if (shape.IsSame(pbody->shape)) { EG_writeAttrs(obj, fp); break; } } } for (Exp.Init(mshape->shape, TopAbs_FACE, TopAbs_SHELL); Exp.More(); Exp.Next()) { TopoDS_Shape shape = Exp.Current(); for (i = 0; i < mshape->nbody; i++) { egObject *obj = mshape->bodies[i]; egadsBody *pbody = (egadsBody *) obj->blind; if (shape.IsSame(pbody->shape)) { EG_writeAttrs(obj, fp); break; } } } for (Exp.Init(mshape->shape, TopAbs_SHELL, TopAbs_SOLID); Exp.More(); Exp.Next()) { TopoDS_Shape shape = Exp.Current(); for (i = 0; i < mshape->nbody; i++) { egObject *obj = mshape->bodies[i]; egadsBody *pbody = (egadsBody *) obj->blind; if (shape.IsSame(pbody->shape)) { EG_writeAttrs(obj, fp); break; } } } for (Exp.Init(mshape->shape, TopAbs_SOLID); Exp.More(); Exp.Next()) { TopoDS_Shape shape = Exp.Current(); for (i = 0; i < mshape->nbody; i++) { egObject *obj = mshape->bodies[i]; egadsBody *pbody = (egadsBody *) obj->blind; if (shape.IsSame(pbody->shape)) { EG_writeAttrs(obj, fp); break; } } } fclose(fp); } else { if (outLevel > 0) printf(" EGADS Warning: Extension in %s Not Supported (EG_saveModel)!\n", name); return EGADS_NODATA; } return EGADS_SUCCESS; }
int EG_loadModel(egObject *context, int bflg, const char *name, egObject **model) { int i, j, stat, outLevel, len, nattr, egads = 0; egObject *omodel, *aobj; TopoDS_Shape source; egadsModel *mshape = NULL; FILE *fp; *model = NULL; if (context == NULL) return EGADS_NULLOBJ; if (context->magicnumber != MAGIC) return EGADS_NOTOBJ; if (context->oclass != CONTXT) return EGADS_NOTCNTX; outLevel = EG_outLevel(context); if (name == NULL) { if (outLevel > 0) printf(" EGADS Warning: NULL Filename (EG_loadModel)!\n"); return EGADS_NONAME; } /* does file exist? */ fp = fopen(name, "r"); if (fp == NULL) { if (outLevel > 0) printf(" EGADS Warning: File %s Not Found (EG_loadModel)!\n", name); return EGADS_NOTFOUND; } fclose(fp); /* find extension */ len = strlen(name); for (i = len-1; i > 0; i--) if (name[i] == '.') break; if (i == 0) { if (outLevel > 0) printf(" EGADS Warning: No Extension in %s (EG_loadModel)!\n", name); return EGADS_NODATA; } if ((strcasecmp(&name[i],".step") == 0) || (strcasecmp(&name[i],".stp") == 0)) { /* STEP files */ STEPControl_Reader aReader; IFSelect_ReturnStatus status = aReader.ReadFile(name); if (status != IFSelect_RetDone) { if (outLevel > 0) printf(" EGADS Error: STEP Read of %s = %d (EG_loadModel)!\n", name, status); return EGADS_NOLOAD; } // inspect the root transfers if (outLevel > 2) aReader.PrintCheckLoad(Standard_False, IFSelect_ItemsByEntity); int nroot = aReader.NbRootsForTransfer(); if (outLevel > 1) printf(" EGADS Info: %s Entries = %d\n", name, nroot); for (i = 1; i <= nroot; i++) { Standard_Boolean ok = aReader.TransferRoot(i); if ((!ok) && (outLevel > 0)) printf(" EGADS Warning: Transfer %d/%d is not OK!\n", i, nroot); } int nbs = aReader.NbShapes(); if (nbs <= 0) { if (outLevel > 0) printf(" EGADS Error: %s has No Shapes (EG_loadModel)!\n", name); return EGADS_NOLOAD; } if (outLevel > 1) printf(" EGADS Info: %s has %d Shape(s)\n", name, nbs); TopoDS_Compound compound; BRep_Builder builder3D; builder3D.MakeCompound(compound); for (i = 1; i <= nbs; i++) { TopoDS_Shape aShape = aReader.Shape(i); builder3D.Add(compound, aShape); } source = compound; } else if ((strcasecmp(&name[i],".iges") == 0) || (strcasecmp(&name[i],".igs") == 0)) { /* IGES files */ IGESControl_Reader iReader; Standard_Integer stats = iReader.ReadFile(name); if (stats != IFSelect_RetDone) { if (outLevel > 0) printf(" EGADS Error: IGES Read of %s = %d (EG_loadModel)!\n", name, stats); return EGADS_NOLOAD; } iReader.TransferRoots(); int nbs = iReader.NbShapes(); if (nbs <= 0) { if (outLevel > 0) printf(" EGADS Error: %s has No Shapes (EG_loadModel)!\n", name); return EGADS_NOLOAD; } if (outLevel > 1) printf(" EGADS Info: %s has %d Shape(s)\n", name, nbs); TopoDS_Compound compound; BRep_Builder builder3D; builder3D.MakeCompound(compound); for (i = 1; i <= nbs; i++) { TopoDS_Shape aShape = iReader.Shape(i); builder3D.Add(compound, aShape); } source = compound; } else if ((strcasecmp(&name[i],".brep") == 0) || (strcasecmp(&name[i],".egads") == 0)) { /* Native OCC file */ if (strcasecmp(&name[i],".egads") == 0) egads = 1; BRep_Builder builder; if (!BRepTools::Read(source, name, builder)) { if (outLevel > 0) printf(" EGADS Warning: Read Error on %s (EG_loadModel)!\n", name); return EGADS_NOLOAD; } } else { if (outLevel > 0) printf(" EGADS Warning: Extension in %s Not Supported (EG_loadModel)!\n", name); return EGADS_NODATA; } int nWire = 0; int nFace = 0; int nSheet = 0; int nSolid = 0; TopExp_Explorer Exp; for (Exp.Init(source, TopAbs_WIRE, TopAbs_FACE); Exp.More(); Exp.Next()) nWire++; for (Exp.Init(source, TopAbs_FACE, TopAbs_SHELL); Exp.More(); Exp.Next()) nFace++; for (Exp.Init(source, TopAbs_SHELL, TopAbs_SOLID); Exp.More(); Exp.Next()) nSheet++; for (Exp.Init(source, TopAbs_SOLID); Exp.More(); Exp.Next()) nSolid++; if (outLevel > 1) printf("\n EGADS Info: %s has %d Solids, %d Sheets, %d Faces and %d Wires\n", name, nSolid, nSheet, nFace, nWire); int nBody = nWire+nFace+nSheet+nSolid; if (nBody == 0) { source.Nullify(); if (outLevel > 0) printf(" EGADS Warning: Nothing found in %s (EG_loadModel)!\n", name); return EGADS_NODATA; } mshape = new egadsModel; mshape->shape = source; mshape->nbody = nBody; mshape->bodies = new egObject*[nBody]; for (i = 0; i < nBody; i++) { stat = EG_makeObject(context, &mshape->bodies[i]); if (stat != EGADS_SUCCESS) { for (int j = 0; j < i; j++) { egObject *obj = mshape->bodies[j]; egadsBody *pbody = (egadsBody *) obj->blind; delete pbody; EG_deleteObject(mshape->bodies[j]); } delete [] mshape->bodies; delete mshape; return stat; } egObject *pobj = mshape->bodies[i]; egadsBody *pbody = new egadsBody; pbody->nodes.objs = NULL; pbody->edges.objs = NULL; pbody->loops.objs = NULL; pbody->faces.objs = NULL; pbody->shells.objs = NULL; pbody->senses = NULL; pobj->blind = pbody; } i = 0; for (Exp.Init(mshape->shape, TopAbs_WIRE, TopAbs_FACE); Exp.More(); Exp.Next()) { egObject *obj = mshape->bodies[i++]; egadsBody *pbody = (egadsBody *) obj->blind; pbody->shape = Exp.Current(); } for (Exp.Init(mshape->shape, TopAbs_FACE, TopAbs_SHELL); Exp.More(); Exp.Next()) { egObject *obj = mshape->bodies[i++]; egadsBody *pbody = (egadsBody *) obj->blind; pbody->shape = Exp.Current(); } for (Exp.Init(mshape->shape, TopAbs_SHELL, TopAbs_SOLID); Exp.More(); Exp.Next()) { egObject *obj = mshape->bodies[i++]; egadsBody *pbody = (egadsBody *) obj->blind; pbody->shape = Exp.Current(); } for (Exp.Init(mshape->shape, TopAbs_SOLID); Exp.More(); Exp.Next()) { egObject *obj = mshape->bodies[i++]; egadsBody *pbody = (egadsBody *) obj->blind; pbody->shape = Exp.Current(); } stat = EG_makeObject(context, &omodel); if (stat != EGADS_SUCCESS) { source.Nullify(); for (i = 0; i < nBody; i++) { egObject *obj = mshape->bodies[i]; egadsBody *pbody = (egadsBody *) obj->blind; delete pbody; EG_deleteObject(mshape->bodies[i]); } delete [] mshape->bodies; delete mshape; return stat; } omodel->oclass = MODEL; omodel->blind = mshape; EG_referenceObject(omodel, context); for (i = 0; i < nBody; i++) { egObject *pobj = mshape->bodies[i]; egadsBody *pbody = (egadsBody *) pobj->blind; pobj->topObj = omodel; if (((bflg&1) == 0) && (egads == 0)) EG_splitPeriodics(pbody); stat = EG_traverseBody(context, i, pobj, omodel, pbody); if (stat != EGADS_SUCCESS) { mshape->nbody = i; EG_destroyTopology(omodel); delete [] mshape->bodies; delete mshape; return stat; } } *model = omodel; if (egads == 0) return EGADS_SUCCESS; /* get the attributes from the EGADS files */ fp = fopen(name, "r"); if (fp == NULL) { printf(" EGADS Info: Cannot reOpen %s (EG_loadModel)!\n", name); return EGADS_SUCCESS; } char line[81]; for (;;) { line[0] = line[1] = ' '; if (fgets(line, 81, fp) == NULL) break; if ((line[0] == '#') && (line[1] == '#')) break; } // got the header if ((line[0] == '#') && (line[1] == '#')) { if (outLevel > 1) printf(" Header = %s\n", line); // get number of model attributes fscanf(fp, "%d", &nattr); if (nattr != 0) EG_readAttrs(omodel, nattr, fp); for (i = 0; i < nBody; i++) { int otype, oindex; int rsolid, rshell, rface, rloop, redge, rnode; int nsolid, nshell, nface, nloop, nedge, nnode; fscanf(fp, " %d %d %d %d %d %d %d", &rsolid, &rshell, &rface, &rloop, &redge, &rnode, &nattr); if (outLevel > 2) printf(" read = %d %d %d %d %d %d %d\n", rsolid, rshell, rface, rloop, redge, rnode, nattr); egObject *pobj = mshape->bodies[i]; egadsBody *pbody = (egadsBody *) pobj->blind; nnode = pbody->nodes.map.Extent(); nedge = pbody->edges.map.Extent(); nloop = pbody->loops.map.Extent(); nface = pbody->faces.map.Extent(); nshell = pbody->shells.map.Extent(); nsolid = 0; if (pobj->mtype == SOLIDBODY) nsolid = 1; if ((nnode != rnode) || (nedge != redge) || (nloop != rloop) || (nface != rface) || (nshell != rshell) || (nsolid != rsolid)) { printf(" EGADS Info: %d %d, %d %d, %d %d, %d %d, %d %d, %d %d", nnode, rnode, nedge, redge, nloop, rloop, nface, rface, nshell, rshell, nsolid, rsolid); printf(" MisMatch on Attributes (EG_loadModel)!\n"); fclose(fp); return EGADS_SUCCESS; } // got the correct body -- transfer the attributes if (nattr != 0) EG_readAttrs(pobj, nattr, fp); for (;;) { j = fscanf(fp, "%d %d %d\n", &otype, &oindex, &nattr); if (outLevel > 2) printf(" %d: attr header = %d %d %d\n", j, otype, oindex, nattr); if (j != 3) break; if (otype == 0) break; if (otype == 1) { aobj = pbody->shells.objs[oindex]; } else if (otype == 2) { aobj = pbody->faces.objs[oindex]; } else if (otype == 3) { aobj = pbody->loops.objs[oindex]; } else if (otype == 4) { aobj = pbody->edges.objs[oindex]; } else { aobj = pbody->nodes.objs[oindex]; } EG_readAttrs(aobj, nattr, fp); } } } else { printf(" EGADS Info: EGADS Header not found in %s (EG_loadModel)!\n", name); return EGADS_SUCCESS; } fclose(fp); return EGADS_SUCCESS; }
//======================================================================= //function : Execute //purpose : //======================================================================= Standard_Integer GEOMImpl_ChamferDriver::Execute(TFunction_Logbook& log) const { if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); GEOMImpl_IChamfer aCI (aFunction); Standard_Integer aType = aFunction->GetType(); TopoDS_Shape aShape; Handle(GEOM_Function) aRefShape = aCI.GetShape(); TopoDS_Shape aShapeBase = aRefShape->GetValue(); if (aType == CHAMFER_SHAPE_EDGES_2D) { BRepFilletAPI_MakeFillet2d fill; TopoDS_Face aFace; Standard_Boolean aWireFlag = Standard_False; if (aShapeBase.ShapeType() == TopAbs_FACE) aFace = TopoDS::Face(aShapeBase); else if (aShapeBase.ShapeType() == TopAbs_WIRE) { TopoDS_Wire aWire = TopoDS::Wire(aShapeBase); BRepBuilderAPI_MakeFace aMF(aWire); aMF.Build(); if (!aMF.IsDone()) { StdFail_NotDone::Raise("Cannot build initial face from given wire"); } aFace = aMF.Face(); aWireFlag = Standard_True; } else StdFail_NotDone::Raise("Base shape is neither a face or a wire !"); fill.Init(aFace); double aD1_2D = aCI.GetD1(); double aD2_2D = aCI.GetD2(); TopoDS_Shape aShapeFace1, aShapeFace2; if (GEOMImpl_ILocalOperations::GetSubShape(aShapeBase, aCI.Get2DEdge1(), aShapeFace1) && GEOMImpl_ILocalOperations::GetSubShape(aShapeBase, aCI.Get2DEdge2(), aShapeFace2)) { fill.AddChamfer(TopoDS::Edge(aShapeFace1), TopoDS::Edge(aShapeFace2), aD1_2D, aD2_2D); } else StdFail_NotDone::Raise("Cannot get 2d egde from sub-shape index!"); fill.Build(); if (!fill.IsDone()) { StdFail_NotDone::Raise("Chamfer can not be computed on the given shape with the given parameters"); } if (aWireFlag) { BRepBuilderAPI_MakeWire MW; TopExp_Explorer exp (fill.Shape(), TopAbs_EDGE); for (; exp.More(); exp.Next()) MW.Add(TopoDS::Edge(exp.Current())); MW.Build(); if (!MW.IsDone()) StdFail_NotDone::Raise("Resulting wire cannot be built"); aShape = MW.Shape(); } else aShape = fill.Shape(); } else { // Check the shape type. It have to be shell // or solid, or compsolid, or compound of these shapes. if (!isGoodForChamfer(aShapeBase)) { StdFail_NotDone::Raise ("Wrong shape. Must be shell or solid, or compsolid or compound of these shapes"); } BRepFilletAPI_MakeChamfer fill (aShapeBase); if (aType == CHAMFER_SHAPE_ALL) { // symmetric chamfer on all edges double aD = aCI.GetD(); TopTools_IndexedDataMapOfShapeListOfShape M; GEOMImpl_Block6Explorer::MapShapesAndAncestors(aShapeBase, TopAbs_EDGE, TopAbs_FACE, M); for (int i = 1; i <= M.Extent(); i++) { TopoDS_Edge E = TopoDS::Edge(M.FindKey(i)); TopoDS_Face F = TopoDS::Face(M.FindFromIndex(i).First()); if (!BRepTools::IsReallyClosed(E, F) && !BRep_Tool::Degenerated(E) && M.FindFromIndex(i).Extent() == 2) fill.Add(aD, E, F); } }else if (aType == CHAMFER_SHAPE_EDGE || aType == CHAMFER_SHAPE_EDGE_AD) { // chamfer on edges, common to two faces, with D1 on the first face TopoDS_Shape aFace1, aFace2; if (GEOMImpl_ILocalOperations::GetSubShape(aShapeBase, aCI.GetFace1(), aFace1) && GEOMImpl_ILocalOperations::GetSubShape(aShapeBase, aCI.GetFace2(), aFace2)) { TopoDS_Face F = TopoDS::Face(aFace1); // fill map of edges of the second face TopTools_MapOfShape aMap; TopExp_Explorer Exp2 (aFace2, TopAbs_EDGE); for (; Exp2.More(); Exp2.Next()) { aMap.Add(Exp2.Current()); } // find edges of the first face, common with the second face TopExp_Explorer Exp (aFace1, TopAbs_EDGE); for (; Exp.More(); Exp.Next()) { if (aMap.Contains(Exp.Current())) { TopoDS_Edge E = TopoDS::Edge(Exp.Current()); if (!BRepTools::IsReallyClosed(E, F) && !BRep_Tool::Degenerated(E)) { if ( aType == CHAMFER_SHAPE_EDGE ) { double aD1 = aCI.GetD1(); double aD2 = aCI.GetD2(); fill.Add(aD1, aD2, E, F); } else { double aD = aCI.GetD(); double anAngle = aCI.GetAngle(); if ( (anAngle > 0) && (anAngle < (Standard_PI/2)) ) fill.AddDA(aD, anAngle, E, F); } } } } } } else if (aType == CHAMFER_SHAPE_FACES || aType == CHAMFER_SHAPE_FACES_AD) { // chamfer on all edges of the selected faces, with D1 on the selected face // (on first selected face, if the edge belongs to two selected faces) int aLen = aCI.GetLength(); int ind = 1; TopTools_MapOfShape aMap; TopTools_IndexedDataMapOfShapeListOfShape M; GEOMImpl_Block6Explorer::MapShapesAndAncestors(aShapeBase, TopAbs_EDGE, TopAbs_FACE, M); for (; ind <= aLen; ind++) { TopoDS_Shape aShapeFace; if (GEOMImpl_ILocalOperations::GetSubShape(aShapeBase, aCI.GetFace(ind), aShapeFace)) { TopoDS_Face F = TopoDS::Face(aShapeFace); TopExp_Explorer Exp (F, TopAbs_EDGE); for (; Exp.More(); Exp.Next()) { if (!aMap.Contains(Exp.Current())) { TopoDS_Edge E = TopoDS::Edge(Exp.Current()); if (!BRepTools::IsReallyClosed(E, F) && !BRep_Tool::Degenerated(E) && M.FindFromKey(E).Extent() == 2) if (aType == CHAMFER_SHAPE_FACES) { double aD1 = aCI.GetD1(); double aD2 = aCI.GetD2(); fill.Add(aD1, aD2, E, F); } else { double aD = aCI.GetD(); double anAngle = aCI.GetAngle(); if ( (anAngle > 0) && (anAngle < (Standard_PI/2)) ) fill.AddDA(aD, anAngle, E, F); } } } } } } else if (aType == CHAMFER_SHAPE_EDGES || aType == CHAMFER_SHAPE_EDGES_AD) { // chamfer on selected edges with lenght param D1 & D2. int aLen = aCI.GetLength(); int ind = 1; TopTools_MapOfShape aMap; TopTools_IndexedDataMapOfShapeListOfShape M; GEOMImpl_Block6Explorer::MapShapesAndAncestors(aShapeBase, TopAbs_EDGE, TopAbs_FACE, M); for (; ind <= aLen; ind++) { TopoDS_Shape aShapeEdge; if (GEOMImpl_ILocalOperations::GetSubShape(aShapeBase, aCI.GetEdge(ind), aShapeEdge)) { TopoDS_Edge E = TopoDS::Edge(aShapeEdge); const TopTools_ListOfShape& aFacesList = M.FindFromKey(E); TopoDS_Face F = TopoDS::Face( aFacesList.First() ); if (aType == CHAMFER_SHAPE_EDGES) { double aD1 = aCI.GetD1(); double aD2 = aCI.GetD2(); fill.Add(aD1, aD2, E, F); } else { double aD = aCI.GetD(); double anAngle = aCI.GetAngle(); if ( (anAngle > 0) && (anAngle < (Standard_PI/2)) ) fill.AddDA(aD, anAngle, E, F); } } } } else { } fill.Build(); if (!fill.IsDone()) { StdFail_NotDone::Raise("Chamfer can not be computed on the given shape with the given parameters"); } aShape = fill.Shape(); } if (aShape.IsNull()) return 0; // Check shape validity BRepCheck_Analyzer ana (aShape, false); if (!ana.IsValid()) { // 08.07.2008 added by skl during fixing bug 19761 from Mantis ShapeFix_ShapeTolerance aSFT; aSFT.LimitTolerance(aShape, Precision::Confusion(), Precision::Confusion(), TopAbs_SHAPE); Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape(aShape); aSfs->Perform(); aShape = aSfs->Shape(); // fix SameParameter flag BRepLib::SameParameter(aShape, 1.E-5, Standard_True); ana.Init(aShape); if (!ana.IsValid()) { Standard_CString anErrStr("Chamfer algorithm has produced an invalid shape result"); #ifdef THROW_ON_INVALID_SH Standard_ConstructionError::Raise(anErrStr); #else MESSAGE(anErrStr); //further processing can be performed here //... //in case of failure of automatic treatment //mark the corresponding GEOM_Object as problematic TDF_Label aLabel = aFunction->GetOwnerEntry(); if (!aLabel.IsRoot()) { Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel); if (!aMainObj.IsNull()) aMainObj->SetDirty(Standard_True); } #endif } } aFunction->SetValue(aShape); log.SetTouched(Label()); return 1; }