bool IfcGeom::Kernel::convert(const IfcSchema::IfcExtrudedAreaSolid* l, TopoDS_Shape& shape) { const double height = l->Depth() * getValue(GV_LENGTH_UNIT); if (height < getValue(GV_PRECISION)) { Logger::Message(Logger::LOG_ERROR, "Non-positive extrusion height encountered for:", l->entity); return false; } TopoDS_Shape face; if ( !convert_face(l->SweptArea(),face) ) return false; gp_Trsf trsf; IfcGeom::Kernel::convert(l->Position(),trsf); gp_Dir dir; convert(l->ExtrudedDirection(),dir); shape.Nullify(); if (face.ShapeType() == TopAbs_COMPOUND) { // For compounds (most likely the result of a IfcCompositeProfileDef) // create a compound solid shape. TopExp_Explorer exp(face, TopAbs_FACE); TopoDS_CompSolid compound; BRep_Builder builder; builder.MakeCompSolid(compound); int num_faces_extruded = 0; for (; exp.More(); exp.Next(), ++num_faces_extruded) { builder.Add(compound, BRepPrimAPI_MakePrism(exp.Current(), height*dir)); } if (num_faces_extruded) { shape = compound; } } if (shape.IsNull()) { shape = BRepPrimAPI_MakePrism(face, height*dir); } shape.Move(trsf); return ! shape.IsNull(); }
//======================================================================= //function : CompsolidToCompound //purpose : //======================================================================= TopoDS_Shape GEOMUtils::CompsolidToCompound (const TopoDS_Shape& theCompsolid) { if (theCompsolid.ShapeType() != TopAbs_COMPSOLID) { return theCompsolid; } TopoDS_Compound aCompound; BRep_Builder B; B.MakeCompound(aCompound); TopTools_MapOfShape mapShape; TopoDS_Iterator It (theCompsolid, Standard_True, Standard_True); for (; It.More(); It.Next()) { TopoDS_Shape aShape_i = It.Value(); if (mapShape.Add(aShape_i)) { B.Add(aCompound, aShape_i); } } return aCompound; }
//======================================================================= //function : AddSimpleShapes //purpose : //======================================================================= void GEOMUtils::AddSimpleShapes (const TopoDS_Shape& theShape, TopTools_ListOfShape& theList) { if (theShape.ShapeType() != TopAbs_COMPOUND && theShape.ShapeType() != TopAbs_COMPSOLID) { theList.Append(theShape); return; } TopTools_MapOfShape mapShape; TopoDS_Iterator It (theShape, Standard_True, Standard_True); for (; It.More(); It.Next()) { TopoDS_Shape aShape_i = It.Value(); if (mapShape.Add(aShape_i)) { if (aShape_i.ShapeType() == TopAbs_COMPOUND || aShape_i.ShapeType() == TopAbs_COMPSOLID) { AddSimpleShapes(aShape_i, theList); } else { theList.Append(aShape_i); } } } }
bool ChCascadeDoc::GetVolumeProperties(const TopoDS_Shape& mshape, ///< pass the shape here const double density, ///< pass the density here ChVector<>& center_position, ///< get the position center, respect to shape pos. ChVector<>& inertiaXX, ///< get the inertia diagonal terms ChVector<>& inertiaXY, ///< get the inertia extradiagonal terms double& volume, ///< get the volume double& mass ///< get the mass ) { if (mshape.IsNull()) return false; GProp_GProps mprops; GProp_GProps vprops; BRepGProp::VolumeProperties(mshape,mprops); BRepGProp::VolumeProperties(mshape,vprops); mprops.Add(mprops, density); mass = mprops.Mass(); volume = vprops.Mass(); gp_Pnt G = mprops.CentreOfMass (); gp_Mat I = mprops.MatrixOfInertia(); center_position.x = G.X(); center_position.y = G.Y(); center_position.z = G.Z(); inertiaXX.x = I(1,1); inertiaXX.y = I(2,2); inertiaXX.z = I(3,3); inertiaXY.x = I(1,2); inertiaXY.y = I(1,3); inertiaXY.z = I(2,3); return true; }
virtual bool ForShape(TopoDS_Shape& mshape, TopLoc_Location& mloc, char* mname, int mlevel, TDF_Label& mlabel) { if (this->level_names.size() > mlevel) { if (wildcard_compare(level_names[mlevel].c_str(), mname)) { if (level_copy[mlevel] != -2) { level_copy[mlevel] = level_copy[mlevel] - 1; if (level_copy[mlevel] < -1) level_copy[mlevel] = -1; } if ((level_copy[mlevel] == 0) || (level_copy[mlevel] == -2)) { if (mlevel == this->level_names.size() - 1) { // Found!!! if (this->set_location_to_root) mshape.Location(mloc); // For single istance: only 1st found shape is considered if (!res_found) { res_found = true; res_shape = mshape; res_loc = mloc; res_level = mlevel; res_label = mlabel; } // Add to the shape compound, for multiple results aBuilder.Add(res_comp, mshape); } return true; // proceed! } return false; // break, matching name but not #ID, not needed to go deeper in levels } return false; // break, not matching, not needed to go deeper in levels } else return false; // break, not needed to go deeper in levels than in string wildcard }
Standard_Boolean GEOMImpl_HealingDriver::SuppressFaces (GEOMImpl_IHealing* theHI, const TopoDS_Shape& theOriginalShape, TopoDS_Shape& theOutShape) const { Handle(TColStd_HArray1OfInteger) aFaces = theHI->GetFaces(); Standard_Boolean aResult = Standard_False; if (aFaces.IsNull()) { ShHealOper_RemoveFace aHealer (theOriginalShape); aResult = aHealer.Perform(); if (aResult) theOutShape = aHealer.GetResultShape(); else raiseNotDoneExeption(aHealer.GetErrorStatus()); } else { TopTools_SequenceOfShape aShapesFaces; TopTools_IndexedMapOfShape aShapes; TopExp::MapShapes(theOriginalShape, aShapes); for (int i = 1; i <= aFaces->Length(); i++) { int indexOfFace = aFaces->Value(i); TopoDS_Shape aFace = aShapes.FindKey(indexOfFace); aShapesFaces.Append(aFace); } SuppressFacesRec(aShapesFaces, theOriginalShape, theOutShape); if ((theOriginalShape.ShapeType() == TopAbs_COMPOUND || theOriginalShape.ShapeType() == TopAbs_COMPSOLID)) { TopoDS_Shape aSh = theOutShape; theOutShape = GEOMImpl_GlueDriver::GlueFaces(aSh, Precision::Confusion(), Standard_True); } } return Standard_True; }
QString SetupResultBase::selectionName(ResultEntry *entry, const TopoDS_Shape &shape) { ResultEntry *parentEntry = entry; while(parentEntry->name.isEmpty()) parentEntry = parentEntry->parent; QString stringOut; QTextStream stream(&stringOut); stream << parentEntry->name; stream << '.'; TopTools_IndexedMapOfShape shapeMap; int index(-1); switch (shape.ShapeType()) { case TopAbs_FACE: TopExp::MapShapes(parentEntry->shape, TopAbs_FACE, shapeMap); stream << "Face"; break; case TopAbs_EDGE: TopExp::MapShapes(parentEntry->shape, TopAbs_EDGE, shapeMap); stream << "Edge"; break; case TopAbs_VERTEX: TopExp::MapShapes(parentEntry->shape, TopAbs_VERTEX, shapeMap); stream << "Vertex"; break; default: stream << "Unexpected shape type"; break; } index = shapeMap.FindIndex(shape); stream << index; return stringOut; }
App::DocumentObjectExecReturn *Sweep::execute(void) { if (Sections.getSize() == 0) return new App::DocumentObjectExecReturn("No sections linked."); App::DocumentObject* spine = Spine.getValue(); if (!(spine && spine->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))) return new App::DocumentObjectExecReturn("No spine linked."); const std::vector<std::string>& subedge = Spine.getSubValues(); TopoDS_Shape path; const Part::TopoShape& shape = static_cast<Part::Feature*>(spine)->Shape.getValue(); if (!shape._Shape.IsNull()) { try { if (!subedge.empty()) { BRepBuilderAPI_MakeWire mkWire; for (std::vector<std::string>::const_iterator it = subedge.begin(); it != subedge.end(); ++it) { TopoDS_Shape subshape = shape.getSubShape(it->c_str()); mkWire.Add(TopoDS::Edge(subshape)); } path = mkWire.Wire(); } else if (shape._Shape.ShapeType() == TopAbs_EDGE) { path = shape._Shape; } else if (shape._Shape.ShapeType() == TopAbs_WIRE) { BRepBuilderAPI_MakeWire mkWire(TopoDS::Wire(shape._Shape)); path = mkWire.Wire(); } else if (shape._Shape.ShapeType() == TopAbs_COMPOUND) { TopoDS_Iterator it(shape._Shape); for (; it.More(); it.Next()) { if (it.Value().IsNull()) return new App::DocumentObjectExecReturn("In valid element in spine."); if ((it.Value().ShapeType() != TopAbs_EDGE) && (it.Value().ShapeType() != TopAbs_WIRE)) { return new App::DocumentObjectExecReturn("Element in spine is neither an edge nor a wire."); } } Handle(TopTools_HSequenceOfShape) hEdges = new TopTools_HSequenceOfShape(); Handle(TopTools_HSequenceOfShape) hWires = new TopTools_HSequenceOfShape(); for (TopExp_Explorer xp(shape._Shape, TopAbs_EDGE); xp.More(); xp.Next()) hEdges->Append(xp.Current()); ShapeAnalysis_FreeBounds::ConnectEdgesToWires(hEdges, Precision::Confusion(), Standard_True, hWires); int len = hWires->Length(); if (len != 1) return new App::DocumentObjectExecReturn("Spine is not connected."); path = hWires->Value(1); } else { return new App::DocumentObjectExecReturn("Spine is neither an edge nor a wire."); } } catch (Standard_Failure) { return new App::DocumentObjectExecReturn("Invalid spine."); } } try { TopTools_ListOfShape profiles; const std::vector<App::DocumentObject*>& shapes = Sections.getValues(); std::vector<App::DocumentObject*>::const_iterator it; for (it = shapes.begin(); it != shapes.end(); ++it) { if (!(*it)->isDerivedFrom(Part::Feature::getClassTypeId())) return new App::DocumentObjectExecReturn("Linked object is not a shape."); TopoDS_Shape shape = static_cast<Part::Feature*>(*it)->Shape.getValue(); if (shape.IsNull()) return new App::DocumentObjectExecReturn("Linked shape is invalid."); // Extract first element of a compound if (shape.ShapeType() == TopAbs_COMPOUND) { TopoDS_Iterator it(shape); for (; it.More(); it.Next()) { if (!it.Value().IsNull()) { shape = it.Value(); break; } } } // There is a weird behaviour of BRepOffsetAPI_MakePipeShell when trying to add the wire as is. // If we re-create the wire then everything works fine. // http://forum.freecadweb.org/viewtopic.php?f=10&t=2673&sid=fbcd2ff4589f0b2f79ed899b0b990648#p20268 if (shape.ShapeType() == TopAbs_FACE) { TopoDS_Wire faceouterWire = ShapeAnalysis::OuterWire(TopoDS::Face(shape)); profiles.Append(faceouterWire); } else if (shape.ShapeType() == TopAbs_WIRE) { BRepBuilderAPI_MakeWire mkWire(TopoDS::Wire(shape)); profiles.Append(mkWire.Wire()); } else if (shape.ShapeType() == TopAbs_EDGE) { BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(shape)); profiles.Append(mkWire.Wire()); } else if (shape.ShapeType() == TopAbs_VERTEX) { profiles.Append(shape); } else { return new App::DocumentObjectExecReturn("Linked shape is not a vertex, edge, wire nor face."); } } Standard_Boolean isSolid = Solid.getValue() ? Standard_True : Standard_False; Standard_Boolean isFrenet = Frenet.getValue() ? Standard_True : Standard_False; BRepBuilderAPI_TransitionMode transMode; switch (Transition.getValue()) { case 1: transMode = BRepBuilderAPI_RightCorner; break; case 2: transMode = BRepBuilderAPI_RoundCorner; break; default: transMode = BRepBuilderAPI_Transformed; break; } if (path.ShapeType() == TopAbs_EDGE) { BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(path)); path = mkWire.Wire(); } BRepOffsetAPI_MakePipeShell mkPipeShell(TopoDS::Wire(path)); mkPipeShell.SetMode(isFrenet); mkPipeShell.SetTransitionMode(transMode); TopTools_ListIteratorOfListOfShape iter; for (iter.Initialize(profiles); iter.More(); iter.Next()) { mkPipeShell.Add(TopoDS_Shape(iter.Value())); } if (!mkPipeShell.IsReady()) Standard_Failure::Raise("shape is not ready to build"); mkPipeShell.Build(); if (isSolid) mkPipeShell.MakeSolid(); this->Shape.setValue(mkPipeShell.Shape()); return App::DocumentObject::StdReturn; } 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 sweep"); } }
App::DocumentObjectExecReturn *Revolution::execute(void) { App::DocumentObject* link = Sketch.getValue(); if (!link) return new App::DocumentObjectExecReturn("No sketch linked"); if (!link->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) return new App::DocumentObjectExecReturn("Linked object is not a Sketch or Part2DObject"); Part::Part2DObject* pcSketch=static_cast<Part::Part2DObject*>(link); TopoDS_Shape shape = pcSketch->Shape.getShape()._Shape; if (shape.IsNull()) return new App::DocumentObjectExecReturn("Linked shape object is empty"); // this is a workaround for an obscure OCC bug which leads to empty tessellations // for some faces. Making an explicit copy of the linked shape seems to fix it. // The error only happens when re-computing the shape. if (!this->Shape.getValue().IsNull()) { BRepBuilderAPI_Copy copy(shape); shape = copy.Shape(); if (shape.IsNull()) return new App::DocumentObjectExecReturn("Linked shape object is empty"); } TopExp_Explorer ex; std::vector<TopoDS_Wire> wires; for (ex.Init(shape, TopAbs_WIRE); ex.More(); ex.Next()) { wires.push_back(TopoDS::Wire(ex.Current())); } if (wires.empty()) // there can be several wires return new App::DocumentObjectExecReturn("Linked shape object is not a wire"); // get the Sketch plane Base::Placement SketchPlm = pcSketch->Placement.getValue(); // get reference axis App::DocumentObject *pcReferenceAxis = ReferenceAxis.getValue(); const std::vector<std::string> &subReferenceAxis = ReferenceAxis.getSubValues(); if (pcReferenceAxis && pcReferenceAxis == pcSketch) { bool hasValidAxis=false; Base::Axis axis; if (subReferenceAxis[0] == "V_Axis") { hasValidAxis = true; axis = pcSketch->getAxis(Part::Part2DObject::V_Axis); } else if (subReferenceAxis[0] == "H_Axis") { hasValidAxis = true; axis = pcSketch->getAxis(Part::Part2DObject::H_Axis); } else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0,4) == "Axis") { int AxId = std::atoi(subReferenceAxis[0].substr(4,4000).c_str()); if (AxId >= 0 && AxId < pcSketch->getAxisCount()) { hasValidAxis = true; axis = pcSketch->getAxis(AxId); } } if (hasValidAxis) { axis *= SketchPlm; Base::Vector3d base=axis.getBase(); Base::Vector3d dir=axis.getDirection(); Base.setValue(base.x,base.y,base.z); Axis.setValue(dir.x,dir.y,dir.z); } } // get revolve axis Base::Vector3f b = Base.getValue(); gp_Pnt pnt(b.x,b.y,b.z); Base::Vector3f v = Axis.getValue(); gp_Dir dir(v.x,v.y,v.z); // get the support of the Sketch if any App::DocumentObject* pcSupport = pcSketch->Support.getValue(); Part::Feature *SupportObject = 0; if (pcSupport && pcSupport->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) SupportObject = static_cast<Part::Feature*>(pcSupport); TopoDS_Shape aFace = makeFace(wires); if (aFace.IsNull()) return new App::DocumentObjectExecReturn("Creating a face from sketch failed"); // Rotate the face by half the angle to get revolution symmetric to sketch plane if (Midplane.getValue()) { gp_Trsf mov; mov.SetRotation(gp_Ax1(pnt, dir), Base::toRadians<double>(Angle.getValue()) * (-1.0) / 2.0); TopLoc_Location loc(mov); aFace.Move(loc); } this->positionBySketch(); TopLoc_Location invObjLoc = this->getLocation().Inverted(); pnt.Transform(invObjLoc.Transformation()); dir.Transform(invObjLoc.Transformation()); // Reverse angle if selected double angle = Base::toRadians<double>(Angle.getValue()); if (Reversed.getValue() && !Midplane.getValue()) angle *= (-1.0); try { // revolve the face to a solid BRepPrimAPI_MakeRevol RevolMaker(aFace.Moved(invObjLoc), gp_Ax1(pnt, dir), angle); if (RevolMaker.IsDone()) { TopoDS_Shape result = RevolMaker.Shape(); // if the sketch has a support fuse them to get one result object (PAD!) if (SupportObject) { const TopoDS_Shape& support = SupportObject->Shape.getValue(); if (!support.IsNull() && support.ShapeType() == TopAbs_SOLID) { // set the additive shape property for later usage in e.g. pattern this->AddShape.setValue(result); // Let's call algorithm computing a fuse operation: BRepAlgoAPI_Fuse mkFuse(support.Moved(invObjLoc), result); // Let's check if the fusion has been successful if (!mkFuse.IsDone()) throw Base::Exception("Fusion with support failed"); result = mkFuse.Shape(); } } this->Shape.setValue(result); } else return new App::DocumentObjectExecReturn("Could not revolve the sketch!"); return App::DocumentObject::StdReturn; } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); return new App::DocumentObjectExecReturn(e->GetMessageString()); } }
const std::list<gp_Trsf> LinearPattern::getTransformations(const std::vector<App::DocumentObject*>) { std::string stdDirection = StdDirection.getValue(); float distance = Length.getValue(); if (distance < Precision::Confusion()) throw Base::Exception("Pattern length too small"); int occurrences = Occurrences.getValue(); if (occurrences < 2) throw Base::Exception("At least two occurrences required"); bool reversed = Reversed.getValue(); gp_Dir dir; double offset = distance / (occurrences - 1); if (!stdDirection.empty()) { // Note: The placement code commented out below had the defect of working always on the // absolute X,Y,Z direction, not on the relative coordinate system of the Body feature. // It requires positionBySupport() to be called in Transformed::Execute() AFTER // the call to getTransformations() // New code thanks to logari81 if (stdDirection == "X") { //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(1,0,0)); dir = gp_Dir(1,0,0); } else if (stdDirection == "Y") { //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(0,1,0)); dir = gp_Dir(0,1,0); } else if(stdDirection == "Z") { //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(0,0,1)); dir = gp_Dir(0,0,1); } else { throw Base::Exception("Invalid direction (must be X, Y or Z)"); } } else { App::DocumentObject* refObject = Direction.getValue(); if (refObject == NULL) throw Base::Exception("No direction specified"); if (!refObject->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) throw Base::Exception("Direction reference must be edge or face of a feature"); std::vector<std::string> subStrings = Direction.getSubValues(); if (subStrings.empty() || subStrings[0].empty()) throw Base::Exception("No direction reference specified"); Part::Feature* refFeature = static_cast<Part::Feature*>(refObject); Part::TopoShape refShape = refFeature->Shape.getShape(); TopoDS_Shape ref = refShape.getSubShape(subStrings[0].c_str()); if (ref.ShapeType() == TopAbs_FACE) { TopoDS_Face refFace = TopoDS::Face(ref); if (refFace.IsNull()) throw Base::Exception("Failed to extract direction plane"); BRepAdaptor_Surface adapt(refFace); if (adapt.GetType() != GeomAbs_Plane) throw Base::Exception("Direction face must be planar"); dir = adapt.Plane().Axis().Direction(); //gp_Dir d = adapt.Plane().Axis().Direction(); //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(d.X(), d.Y(), d.Z())); } else if (ref.ShapeType() == TopAbs_EDGE) { TopoDS_Edge refEdge = TopoDS::Edge(ref); if (refEdge.IsNull()) throw Base::Exception("Failed to extract direction edge"); BRepAdaptor_Curve adapt(refEdge); if (adapt.GetType() != GeomAbs_Line) throw Base::Exception("Direction edge must be a straight line"); //gp_Dir d = adapt.Line().Direction(); //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(d.X(), d.Y(), d.Z())); dir = adapt.Line().Direction(); } else { throw Base::Exception("Direction reference must be edge or face"); } TopLoc_Location invObjLoc = this->getLocation().Inverted(); dir.Transform(invObjLoc.Transformation()); } // get the support placement // TODO: Check for NULL pointer /*Part::Feature* supportFeature = static_cast<Part::Feature*>(originals.front()); if (supportFeature == NULL) throw Base::Exception("Cannot work on invalid support shape"); Base::Placement supportPlacement = supportFeature->Placement.getValue(); dir *= supportPlacement; gp_Vec direction(dir.getDirection().x, dir.getDirection().y, dir.getDirection().z);*/ gp_Vec direction(dir.X(), dir.Y(), dir.Z()); if (reversed) direction.Reverse(); // Note: The original feature is NOT included in the list of transformations! Therefore // we start with occurrence number 1, not number 0 std::list<gp_Trsf> transformations; gp_Trsf trans; transformations.push_back(trans); // identity transformation for (int i = 1; i < occurrences; i++) { trans.SetTranslation(direction * i * offset); transformations.push_back(trans); } return transformations; }
App::DocumentObjectExecReturn *MultiFuse::execute(void) { std::vector<TopoDS_Shape> s; std::vector<App::DocumentObject*> obj = Shapes.getValues(); std::vector<App::DocumentObject*>::iterator it; for (it = obj.begin(); it != obj.end(); ++it) { if ((*it)->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { s.push_back(static_cast<Part::Feature*>(*it)->Shape.getValue()); } } bool argumentsAreInCompound = false; TopoDS_Shape compoundOfArguments; //if only one source shape, and it is a compound - fuse children of the compound if (s.size() == 1){ compoundOfArguments = s[0]; if (compoundOfArguments.ShapeType() == TopAbs_COMPOUND){ s.clear(); TopoDS_Iterator it(compoundOfArguments); for (; it.More(); it.Next()) { const TopoDS_Shape& aChild = it.Value(); s.push_back(aChild); } argumentsAreInCompound = true; } } if (s.size() >= 2) { try { std::vector<ShapeHistory> history; #if OCC_VERSION_HEX <= 0x060800 TopoDS_Shape resShape = s.front(); if (resShape.IsNull()) throw Base::Exception("Input shape is null"); for (std::vector<TopoDS_Shape>::iterator it = s.begin()+1; it != s.end(); ++it) { if (it->IsNull()) throw Base::Exception("Input shape is null"); // Let's call algorithm computing a fuse operation: BRepAlgoAPI_Fuse mkFuse(resShape, *it); // Let's check if the fusion has been successful if (!mkFuse.IsDone()) throw Base::Exception("Fusion failed"); resShape = mkFuse.Shape(); ShapeHistory hist1 = buildHistory(mkFuse, TopAbs_FACE, resShape, mkFuse.Shape1()); ShapeHistory hist2 = buildHistory(mkFuse, TopAbs_FACE, resShape, mkFuse.Shape2()); if (history.empty()) { history.push_back(hist1); history.push_back(hist2); } else { for (std::vector<ShapeHistory>::iterator jt = history.begin(); jt != history.end(); ++jt) *jt = joinHistory(*jt, hist1); history.push_back(hist2); } } #else BRepAlgoAPI_Fuse mkFuse; TopTools_ListOfShape shapeArguments,shapeTools; shapeArguments.Append(s.front()); for (std::vector<TopoDS_Shape>::iterator it = s.begin()+1; it != s.end(); ++it) { if (it->IsNull()) throw Base::Exception("Input shape is null"); shapeTools.Append(*it); } mkFuse.SetArguments(shapeArguments); mkFuse.SetTools(shapeTools); mkFuse.Build(); if (!mkFuse.IsDone()) throw Base::Exception("MultiFusion failed"); TopoDS_Shape resShape = mkFuse.Shape(); for (std::vector<TopoDS_Shape>::iterator it = s.begin(); it != s.end(); ++it) { history.push_back(buildHistory(mkFuse, TopAbs_FACE, resShape, *it)); } #endif if (resShape.IsNull()) throw Base::Exception("Resulting shape is null"); Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter() .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part/Boolean"); if (hGrp->GetBool("CheckModel", false)) { BRepCheck_Analyzer aChecker(resShape); if (! aChecker.IsValid() ) { return new App::DocumentObjectExecReturn("Resulting shape is invalid"); } } if (hGrp->GetBool("RefineModel", false)) { try { TopoDS_Shape oldShape = resShape; BRepBuilderAPI_RefineModel mkRefine(oldShape); resShape = mkRefine.Shape(); ShapeHistory hist = buildHistory(mkRefine, TopAbs_FACE, resShape, oldShape); for (std::vector<ShapeHistory>::iterator jt = history.begin(); jt != history.end(); ++jt) *jt = joinHistory(*jt, hist); } catch (Standard_Failure) { // do nothing } } this->Shape.setValue(resShape); if (argumentsAreInCompound){ //combine histories of every child of source compound into one ShapeHistory overallHist; TopTools_IndexedMapOfShape facesOfCompound; TopAbs_ShapeEnum type = TopAbs_FACE; TopExp::MapShapes(compoundOfArguments, type, facesOfCompound); for (std::size_t iChild = 0; iChild < history.size(); iChild++){ //loop over children of source compound //for each face of a child, find the inex of the face in compound, and assign the corresponding right-hand-size of the history TopTools_IndexedMapOfShape facesOfChild; TopExp::MapShapes(s[iChild], type, facesOfChild); for(std::pair<const int,ShapeHistory::List> &histitem: history[iChild].shapeMap){ //loop over elements of history - that is - over faces of the child of source compound int iFaceInChild = histitem.first; ShapeHistory::List &iFacesInResult = histitem.second; TopoDS_Shape srcFace = facesOfChild(iFaceInChild + 1); //+1 to convert our 0-based to OCC 1-bsed conventions int iFaceInCompound = facesOfCompound.FindIndex(srcFace)-1; overallHist.shapeMap[iFaceInCompound] = iFacesInResult; //this may overwrite existing info if the same face is used in several children of compound. This shouldn't be a problem, because the histories should match anyway... } } history.clear(); history.push_back(overallHist); } this->History.setValues(history); } catch (Standard_Failure& e) { return new App::DocumentObjectExecReturn(e.GetMessageString()); } } else { throw Base::Exception("Not enough shape objects linked"); } return App::DocumentObject::StdReturn; }
bool ProfileBased::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 noticeable 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 noticeable 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::RuntimeError("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 every 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 ProfileBased::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(); TopoDS_Shape sh = shape.getShape(); sh.Location(TopLoc_Location()); shape.setShape(sh); 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); } } }
void ProfileBased::getAxis(const App::DocumentObject *pcReferenceAxis, const std::vector<std::string> &subReferenceAxis, Base::Vector3d& base, Base::Vector3d& dir) { dir = Base::Vector3d(0,0,0); // If unchanged signals that no valid axis was found if (pcReferenceAxis == NULL) return; App::DocumentObject* profile = Profile.getValue(); gp_Pln sketchplane; if (profile->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) { Part::Part2DObject* sketch = getVerifiedSketch(); Base::Placement SketchPlm = sketch->Placement.getValue(); Base::Vector3d SketchVector = Base::Vector3d(0, 0, 1); Base::Rotation SketchOrientation = SketchPlm.getRotation(); SketchOrientation.multVec(SketchVector, SketchVector); Base::Vector3d SketchPos = SketchPlm.getPosition(); sketchplane = gp_Pln(gp_Pnt(SketchPos.x, SketchPos.y, SketchPos.z), gp_Dir(SketchVector.x, SketchVector.y, SketchVector.z)); if (pcReferenceAxis == profile) { bool hasValidAxis = false; Base::Axis axis; if (subReferenceAxis[0] == "V_Axis") { hasValidAxis = true; axis = sketch->getAxis(Part::Part2DObject::V_Axis); } else if (subReferenceAxis[0] == "H_Axis") { hasValidAxis = true; axis = sketch->getAxis(Part::Part2DObject::H_Axis); } else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0, 4) == "Axis") { int AxId = std::atoi(subReferenceAxis[0].substr(4, 4000).c_str()); if (AxId >= 0 && AxId < sketch->getAxisCount()) { hasValidAxis = true; axis = sketch->getAxis(AxId); } } if (hasValidAxis) { axis *= SketchPlm; base = axis.getBase(); dir = axis.getDirection(); return; } //else - an edge of the sketch was selected as an axis } } else if (profile->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { Base::Placement SketchPlm = getVerifiedObject()->Placement.getValue(); Base::Vector3d SketchVector = getProfileNormal(); Base::Vector3d SketchPos = SketchPlm.getPosition(); sketchplane = gp_Pln(gp_Pnt(SketchPos.x, SketchPos.y, SketchPos.z), gp_Dir(SketchVector.x, SketchVector.y, SketchVector.z)); } // get reference axis if (pcReferenceAxis->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) { const PartDesign::Line* line = static_cast<const PartDesign::Line*>(pcReferenceAxis); base = line->getBasePoint(); dir = line->getDirection(); // Check that axis is perpendicular with sketch plane! if (sketchplane.Axis().Direction().IsParallel(gp_Dir(dir.x, dir.y, dir.z), Precision::Angular())) throw Base::ValueError("Rotation axis must not be perpendicular with the sketch plane"); return; } if (pcReferenceAxis->getTypeId().isDerivedFrom(App::Line::getClassTypeId())) { const App::Line* line = static_cast<const App::Line*>(pcReferenceAxis); base = Base::Vector3d(0,0,0); line->Placement.getValue().multVec(Base::Vector3d (1,0,0), dir); // Check that axis is perpendicular with sketch plane! if (sketchplane.Axis().Direction().IsParallel(gp_Dir(dir.x, dir.y, dir.z), Precision::Angular())) throw Base::ValueError("Rotation axis must not be perpendicular with the sketch plane"); return; } if (pcReferenceAxis->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { if (subReferenceAxis.empty()) throw Base::ValueError("No rotation axis reference specified"); const Part::Feature* refFeature = static_cast<const Part::Feature*>(pcReferenceAxis); Part::TopoShape refShape = refFeature->Shape.getShape(); TopoDS_Shape ref = refShape.getSubShape(subReferenceAxis[0].c_str()); if (ref.ShapeType() == TopAbs_EDGE) { TopoDS_Edge refEdge = TopoDS::Edge(ref); if (refEdge.IsNull()) throw Base::ValueError("Failed to extract rotation edge"); BRepAdaptor_Curve adapt(refEdge); if (adapt.GetType() != GeomAbs_Line) throw Base::TypeError("Rotation edge must be a straight line"); gp_Pnt b = adapt.Line().Location(); base = Base::Vector3d(b.X(), b.Y(), b.Z()); gp_Dir d = adapt.Line().Direction(); dir = Base::Vector3d(d.X(), d.Y(), d.Z()); // Check that axis is co-planar with sketch plane! // Check that axis is perpendicular with sketch plane! if (sketchplane.Axis().Direction().IsParallel(d, Precision::Angular())) throw Base::ValueError("Rotation axis must not be perpendicular with the sketch plane"); return; } else { throw Base::TypeError("Rotation reference must be an edge"); } } throw Base::TypeError("Rotation axis reference is invalid"); }
App::DocumentObjectExecReturn *Transformed::execute(void) { rejected.clear(); std::vector<App::DocumentObject*> originals = Originals.getValues(); if (originals.empty()) // typically InsideMultiTransform return App::DocumentObject::StdReturn; this->positionBySupport(); // get transformations from subclass by calling virtual method std::list<gp_Trsf> transformations; try { transformations = getTransformations(originals); } catch (Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } if (transformations.empty()) return App::DocumentObject::StdReturn; // No transformations defined, exit silently // Get the support // NOTE: Because of the way we define the support, FeatureTransformed can only work on // one Body feature at a time // TODO: Currently, the support is simply the first Original. Change this to the Body feature later Part::Feature* supportFeature = static_cast<Part::Feature*>(getSupportObject()); const Part::TopoShape& supportTopShape = supportFeature->Shape.getShape(); if (supportTopShape._Shape.IsNull()) return new App::DocumentObjectExecReturn("Cannot transform invalid support shape"); // create an untransformed copy of the support shape Part::TopoShape supportShape(supportTopShape); supportShape.setTransform(Base::Matrix4D()); TopoDS_Shape support = supportShape._Shape; // NOTE: It would be possible to build a compound from all original addShapes/subShapes and then // transform the compounds as a whole. But we choose to apply the transformations to each // Original separately. This way it is easier to discover what feature causes a fuse/cut // to fail. The downside is that performance suffers when there are many originals. But it seems // safe to assume that in most cases there are few originals and many transformations for (std::vector<App::DocumentObject*>::const_iterator o = originals.begin(); o != originals.end(); o++) { TopoDS_Shape shape; bool fuse; if ((*o)->getTypeId().isDerivedFrom(PartDesign::Additive::getClassTypeId())) { PartDesign::Additive* addFeature = static_cast<PartDesign::Additive*>(*o); shape = addFeature->AddShape.getShape()._Shape; if (shape.IsNull()) return new App::DocumentObjectExecReturn("Shape of additive feature is empty"); fuse = true; } else if ((*o)->getTypeId().isDerivedFrom(PartDesign::Subtractive::getClassTypeId())) { PartDesign::Subtractive* subFeature = static_cast<PartDesign::Subtractive*>(*o); shape = subFeature->SubShape.getShape()._Shape; if (shape.IsNull()) return new App::DocumentObjectExecReturn("Shape of subtractive feature is empty"); fuse = false; } else { return new App::DocumentObjectExecReturn("Only additive and subtractive features can be transformed"); } // Transform the add/subshape and build a compound from the transformations, BRep_Builder builder; TopoDS_Compound transformedShapes; builder.MakeCompound(transformedShapes); std::vector<TopoDS_Shape> v_transformedShapes; // collect all the transformed shapes for intersection testing std::list<gp_Trsf>::const_iterator t = transformations.begin(); t++; // Skip first transformation, which is always the identity transformation for (; t != transformations.end(); t++) { // Make an explicit copy of the shape because the "true" parameter to BRepBuilderAPI_Transform // seems to be pretty broken BRepBuilderAPI_Copy copy(shape); shape = copy.Shape(); if (shape.IsNull()) throw Base::Exception("Transformed: Linked shape object is empty"); BRepBuilderAPI_Transform mkTrf(shape, *t, false); // No need to copy, now if (!mkTrf.IsDone()) return new App::DocumentObjectExecReturn("Transformation failed", (*o)); // Check for intersection with support if (!Part::checkIntersection(support, mkTrf.Shape(), false)) { Base::Console().Warning("Transformed shape does not intersect support %s: Removed\n", (*o)->getNameInDocument()); // Note: The removal happens in getSolid() after the fuse rejected.push_back(*t); } builder.Add(transformedShapes, mkTrf.Shape()); v_transformedShapes.push_back(mkTrf.Shape()); /* // Note: This method is only stable for Linear and Polar transformations. No need to // make an explicit copy of the shape, either TopoDS_Shape trfShape = shape.Moved(TopLoc_Location(*t)); // Check for intersection with support Bnd_Box transformed_bb; BRepBndLib::Add(trfShape, transformed_bb); if (support_bb.Distance(transformed_bb) > Precision::Confusion()) { Base::Console().Warning("Transformed shape does not intersect support %s: Removed\n", (*o)->getNameInDocument()); // Note: The removal happens in getSolid() after the fuse } builder.Add(transformedShapes, trfShape); v_transformedShapes.push_back(trfShape); */ } // Check for intersection of the original and the transformed shape for (std::vector<TopoDS_Shape>::const_iterator s = v_transformedShapes.begin(); s != v_transformedShapes.end(); s++) { // If there is only one transformed feature, this check is not necessary (though it might seem // illogical to the user why we allow overlapping shapes in this case! if (v_transformedShapes.size() == 1) break; if (Part::checkIntersection(shape, *s, false)) return new App::DocumentObjectExecReturn("Transformed objects are overlapping, try using a higher length or reducing the number of occurrences", (*o)); // Note: This limitation could be overcome by fusing the transformed features instead of // compounding them, probably at the expense of quite a bit of performance and complexity // in this code // For MultiTransform, just checking the first transformed shape is not sufficient - any two // features might overlap, even if the original and the first shape don't overlap! if (this->getTypeId() != PartDesign::MultiTransform::getClassTypeId()) break; else { // Check intersection with all other transformed shapes as well std::vector<TopoDS_Shape>::const_iterator s2 = s; s2++; for (; s2 != v_transformedShapes.end(); s2++) if (Part::checkIntersection(*s, *s2, false)) return new App::DocumentObjectExecReturn("Transformed objects are overlapping, try using a higher length or reducing the number of occurrences", (*o)); } } // Fuse/Cut the compounded transformed shapes with the support TopoDS_Shape result; if (fuse) { BRepAlgoAPI_Fuse mkFuse(support, transformedShapes); if (!mkFuse.IsDone()) return new App::DocumentObjectExecReturn("Fusion with support failed", *o); // we have to get the solids (fuse sometimes creates compounds) // Note: Because getSolid() only returns the first solid in the explorer, all // solids that are outside the support automatically disappear! result = this->getSolid(mkFuse.Shape()); // lets check if the result is a solid if (result.IsNull()) return new App::DocumentObjectExecReturn("Resulting shape is not a solid", *o); // check if mkFuse created more than one solids TopExp_Explorer xp; xp.Init(mkFuse.Shape(),TopAbs_SOLID); if (xp.More()) xp.Next(); if (!xp.More()) // There are no rejected transformations even rejected.clear(); // if the bb check guessed that there would be } else { BRepAlgoAPI_Cut mkCut(support, transformedShapes); if (!mkCut.IsDone()) return new App::DocumentObjectExecReturn("Cut out of support failed", *o); result = mkCut.Shape(); } support = result; // Use result of this operation for fuse/cut of next original } this->Shape.setValue(support); return App::DocumentObject::StdReturn; }
//======================================================================= //function : Execute //purpose : //======================================================================= Standard_Integer GEOMImpl_PlaneDriver::Execute(TFunction_Logbook& log) const { if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); GEOMImpl_IPlane aPI (aFunction); Standard_Integer aType = aFunction->GetType(); TopoDS_Shape aShape; double aSize = aPI.GetSize() / 2.0; if (aType == PLANE_PNT_VEC) { Handle(GEOM_Function) aRefPnt = aPI.GetPoint(); Handle(GEOM_Function) aRefVec = aPI.GetVector(); TopoDS_Shape aShape1 = aRefPnt->GetValue(); TopoDS_Shape aShape2 = aRefVec->GetValue(); if (aShape1.ShapeType() != TopAbs_VERTEX || aShape2.ShapeType() != TopAbs_EDGE) return 0; gp_Pnt aP = BRep_Tool::Pnt(TopoDS::Vertex(aShape1)); TopoDS_Edge anE = TopoDS::Edge(aShape2); TopoDS_Vertex V1, V2; TopExp::Vertices(anE, V1, V2, Standard_True); if (!V1.IsNull() && !V2.IsNull()) { gp_Vec aV (BRep_Tool::Pnt(V1), BRep_Tool::Pnt(V2)); gp_Pln aPln (aP, aV); aShape = BRepBuilderAPI_MakeFace(aPln, -aSize, +aSize, -aSize, +aSize).Shape(); } } else if (aType == PLANE_THREE_PNT) { Handle(GEOM_Function) aRefPnt1 = aPI.GetPoint1(); Handle(GEOM_Function) aRefPnt2 = aPI.GetPoint2(); Handle(GEOM_Function) aRefPnt3 = aPI.GetPoint3(); TopoDS_Shape aShape1 = aRefPnt1->GetValue(); TopoDS_Shape aShape2 = aRefPnt2->GetValue(); TopoDS_Shape aShape3 = aRefPnt3->GetValue(); if (aShape1.ShapeType() != TopAbs_VERTEX || aShape2.ShapeType() != TopAbs_VERTEX || aShape3.ShapeType() != TopAbs_VERTEX) return 0; gp_Pnt aP1 = BRep_Tool::Pnt(TopoDS::Vertex(aShape1)); gp_Pnt aP2 = BRep_Tool::Pnt(TopoDS::Vertex(aShape2)); gp_Pnt aP3 = BRep_Tool::Pnt(TopoDS::Vertex(aShape3)); if (aP1.Distance(aP2) < gp::Resolution() || aP1.Distance(aP3) < gp::Resolution() || aP2.Distance(aP3) < gp::Resolution()) Standard_ConstructionError::Raise("Plane creation aborted: coincident points given"); if (gp_Vec(aP1, aP2).IsParallel(gp_Vec(aP1, aP3), Precision::Angular())) Standard_ConstructionError::Raise("Plane creation aborted: points lay on one line"); GC_MakePlane aMakePlane (aP1, aP2, aP3); aShape = BRepBuilderAPI_MakeFace(aMakePlane, -aSize, +aSize, -aSize, +aSize).Shape(); } else if (aType == PLANE_FACE) { Handle(GEOM_Function) aRef = aPI.GetFace(); TopoDS_Shape aRefShape = aRef->GetValue(); //if (aRefShape.ShapeType() != TopAbs_FACE) return 0; //Handle(Geom_Surface) aGS = BRep_Tool::Surface(TopoDS::Face(aRefShape)); //if (!aGS->IsKind(STANDARD_TYPE(Geom_Plane))) { // Standard_TypeMismatch::Raise("Plane creation aborted: non-planar face given as argument"); //} //aShape = BRepBuilderAPI_MakeFace(aGS, -aSize, +aSize, -aSize, +aSize).Shape(); gp_Ax3 anAx3 = GEOMImpl_IMeasureOperations::GetPosition(aRefShape); gp_Pln aPln (anAx3); aShape = BRepBuilderAPI_MakeFace(aPln, -aSize, +aSize, -aSize, +aSize).Shape(); } else if (aType == PLANE_TANGENT_FACE) { Handle(GEOM_Function) aRefFace = aPI.GetFace(); TopoDS_Shape aShape1 = aRefFace->GetValue(); if(aShape1.IsNull()) Standard_TypeMismatch::Raise("Plane was not created.Basis face was not specified"); TopoDS_Face aFace = TopoDS::Face(aShape1); Standard_Real aKoefU = aPI.GetParameterU(); Standard_Real aKoefV = aPI.GetParameterV(); Standard_Real aUmin,aUmax,aVmin,aVmax; ShapeAnalysis::GetFaceUVBounds(aFace,aUmin,aUmax,aVmin,aVmax); Standard_Real aDeltaU = aUmax - aUmin; Standard_Real aDeltaV = aVmax - aVmin; Standard_Real aParamU = aUmin + aDeltaU*aKoefU; Standard_Real aParamV = aVmin + aDeltaV*aKoefV; Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace); if(aSurf.IsNull()) Standard_TypeMismatch::Raise("Plane was not created.Base surface is absent"); gp_Vec aVecU,aVecV; gp_Pnt aPLoc; aSurf->D1(aParamU,aParamV,aPLoc,aVecU,aVecV); BRepTopAdaptor_FClass2d clas(aFace,Precision::PConfusion()); TopAbs_State stOut= clas.PerformInfinitePoint(); gp_Pnt2d aP2d(aParamU,aParamV); TopAbs_State st= clas.Perform(aP2d); if(st == stOut) Standard_TypeMismatch::Raise("Plane was not created.Point lies outside the face"); gp_Vec aNorm = aVecU^aVecV; gp_Ax3 anAxis(aPLoc,gp_Dir(aNorm),gp_Dir(aVecU)); gp_Pln aPlane(anAxis); BRepBuilderAPI_MakeFace aTool(aPlane, -aSize, +aSize, -aSize, +aSize); if(aTool.IsDone()) aShape = aTool.Shape(); } else if (aType == PLANE_2_VEC) { Handle(GEOM_Function) aRefVec1 = aPI.GetVector1(); Handle(GEOM_Function) aRefVec2 = aPI.GetVector2(); TopoDS_Shape aShape1 = aRefVec1->GetValue(); TopoDS_Shape aShape2 = aRefVec2->GetValue(); if (aShape1.ShapeType() != TopAbs_EDGE || aShape2.ShapeType() != TopAbs_EDGE) return 0; TopoDS_Edge aVectX = TopoDS::Edge(aShape1); TopoDS_Edge aVectZ = TopoDS::Edge(aShape2); TopoDS_Vertex VX1, VX2, VZ1, VZ2; TopExp::Vertices( aVectX, VX1, VX2, Standard_True ); TopExp::Vertices( aVectZ, VZ1, VZ2, Standard_True ); gp_Vec aVX = gp_Vec( BRep_Tool::Pnt( VX1 ), BRep_Tool::Pnt( VX2 ) ); gp_Vec aVZ = gp_Vec( BRep_Tool::Pnt( VZ1 ), BRep_Tool::Pnt( VZ2 ) ); if ( aVX.Magnitude() < Precision::Confusion() || aVZ.Magnitude() < Precision::Confusion()) Standard_TypeMismatch::Raise("Invalid vector selected"); gp_Dir aDirX = gp_Dir( aVX.X(), aVX.Y(), aVX.Z() ); gp_Dir aDirZ = gp_Dir( aVZ.X(), aVZ.Y(), aVZ.Z() ); if ( aDirX.IsParallel( aDirZ, Precision::Angular() ) ) Standard_TypeMismatch::Raise("Parallel vectors selected"); gp_Ax3 aPlane = gp_Ax3( BRep_Tool::Pnt( VX1 ), aDirZ, aDirX ); BRepBuilderAPI_MakeFace aTool(aPlane, -aSize, +aSize, -aSize, +aSize); if(aTool.IsDone()) aShape = aTool.Shape(); } else if (aType == PLANE_LCS) { Handle(GEOM_Function) aRef = aPI.GetLCS(); double anOrientation = aPI.GetOrientation(); gp_Ax3 anAx3; if (aRef.IsNull()) { gp_Ax2 anAx2 = gp::XOY(); anAx3 = gp_Ax3( anAx2 ); } else { TopoDS_Shape aRefShape = aRef->GetValue(); if (aRefShape.ShapeType() != TopAbs_FACE) return 0; anAx3 = GEOMImpl_IMeasureOperations::GetPosition(aRefShape); } if ( anOrientation == 2) anAx3 = gp_Ax3(anAx3.Location(), anAx3.XDirection(), anAx3.YDirection() ); else if ( anOrientation == 3 ) anAx3 = gp_Ax3(anAx3.Location(), anAx3.YDirection(), anAx3.XDirection() ); gp_Pln aPln(anAx3); aShape = BRepBuilderAPI_MakeFace(aPln, -aSize, +aSize, -aSize, +aSize).Shape(); } else { } if (aShape.IsNull()) return 0; aFunction->SetValue(aShape); log.SetTouched(Label()); return 1; }
SALOME_WNT_EXPORT TopoDS_Shape ImportIGES (const TCollection_AsciiString& theFileName, const TCollection_AsciiString& theFormatName, TCollection_AsciiString& theError, const TDF_Label& theShapeLabel) { IGESControl_Reader aReader; TopoDS_Shape aResShape; Interface_Static::SetCVal("xstep.cascade.unit","M"); try { IFSelect_ReturnStatus status = aReader.ReadFile(theFileName.ToCString()); if (status == IFSelect_RetDone) { if( theFormatName == "IGES_UNIT" ) { Handle(IGESData_IGESModel) aModel = Handle(IGESData_IGESModel)::DownCast(aReader.Model()); gp_Pnt P(1.0,0.0,0.0); if(!aModel.IsNull()) { Handle(TCollection_HAsciiString) aUnitName = aModel->GlobalSection().UnitName(); //cout<<"aUnitName = "<<aUnitName->ToCString()<<endl; //cout<<"aUnitFlag = "<<aModel->GlobalSection().UnitFlag()<<endl; if( aUnitName->String()=="MM" ) { P = gp_Pnt(0.001,0.0,0.0); } else if( aUnitName->String()=="CM" ) { P = gp_Pnt(0.01,0.0,0.0); } } BRep_Builder B; TopoDS_Vertex V; B.MakeVertex(V,P,1.e-7); aResShape = V; return aResShape; } if( theFormatName == "IGES_SCALE" ) { //cout<<"need re-scale a model"<<endl; // set UnitFlag to 'meter' Handle(IGESData_IGESModel) aModel = Handle(IGESData_IGESModel)::DownCast(aReader.Model()); if(!aModel.IsNull()) { IGESData_GlobalSection aGS = aModel->GlobalSection(); aGS.SetUnitFlag(6); aModel->SetGlobalSection(aGS); } } MESSAGE("ImportIGES : all Geometry Transfer"); //OCC 5.1.2 porting // aReader.Clear(); // aReader.TransferRoots(false); aReader.ClearShapes(); aReader.TransferRoots(); MESSAGE("ImportIGES : count of shapes produced = " << aReader.NbShapes()); aResShape = aReader.OneShape(); // BEGIN: Store names of sub-shapes from file Handle(Interface_InterfaceModel) Model = aReader.WS()->Model(); Handle(XSControl_TransferReader) TR = aReader.WS()->TransferReader(); if (!TR.IsNull()) { Handle(Transfer_TransientProcess) TP = /*TransientProcess();*/TR->TransientProcess(); Standard_Integer nb = Model->NbEntities(); for (Standard_Integer i = 1; i <= nb; i++) { Handle(IGESData_IGESEntity) ent = Handle(IGESData_IGESEntity)::DownCast(Model->Value(i)); if (ent.IsNull() || ! ent->HasName()) continue; // find target shape Handle(Transfer_Binder) binder = TP->Find(ent); if (binder.IsNull()) continue; TopoDS_Shape S = TransferBRep::ShapeResult(binder); if (S.IsNull()) continue; // create label and set shape TDF_Label L; TDF_TagSource aTag; L = aTag.NewChild(theShapeLabel); TNaming_Builder tnBuild (L); tnBuild.Generated(S); // set a name TCollection_AsciiString string = ent->NameValue()->String(); string.LeftAdjust(); string.RightAdjust(); TCollection_ExtendedString str (string); TDataStd_Name::Set(L, str); } } // END: Store names } else { // switch (status) { // case IFSelect_RetVoid: // theError = "Nothing created or No data to process"; // break; // case IFSelect_RetError: // theError = "Error in command or input data"; // break; // case IFSelect_RetFail: // theError = "Execution was run, but has failed"; // break; // case IFSelect_RetStop: // theError = "Execution has been stopped. Quite possible, an exception was raised"; // break; // default: // break; // } theError = "Wrong format of the imported file. Can't import file."; aResShape.Nullify(); } } catch(Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); theError = aFail->GetMessageString(); aResShape.Nullify(); } return aResShape; }
//======================================================================= //function : Execute //purpose : //======================================================================= Standard_Integer GEOMImpl_RotateDriver::Execute(TFunction_Logbook& log) const { if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); if (aFunction.IsNull()) return 0; GEOMImpl_IRotate RI(aFunction); gp_Trsf aTrsf; gp_Pnt aCP, aP1, aP2; Standard_Integer aType = aFunction->GetType(); Handle(GEOM_Function) anOriginalFunction = RI.GetOriginal(); if (anOriginalFunction.IsNull()) return 0; TopoDS_Shape aShape, anOriginal = anOriginalFunction->GetValue(); if (anOriginal.IsNull()) return 0; if (aType == ROTATE || aType == ROTATE_COPY) { Handle(GEOM_Function) anAxis = RI.GetAxis(); if (anAxis.IsNull()) return 0; TopoDS_Shape A = anAxis->GetValue(); if (A.IsNull() || A.ShapeType() != TopAbs_EDGE) return 0; TopoDS_Edge anEdge = TopoDS::Edge(A); gp_Pnt aP1 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge)); gp_Pnt aP2 = BRep_Tool::Pnt(TopExp::LastVertex(anEdge)); gp_Dir aDir(gp_Vec(aP1, aP2)); gp_Ax1 anAx1(aP1, aDir); Standard_Real anAngle = RI.GetAngle(); if (fabs(anAngle) < Precision::Angular()) anAngle += 2*PI; // NPAL19665,19769 aTrsf.SetRotation(anAx1, anAngle); //NPAL18620: performance problem: multiple locations are accumulated // in shape and need a great time to process //BRepBuilderAPI_Transform aTransformation(anOriginal, aTrsf, Standard_False); //aShape = aTransformation.Shape(); TopLoc_Location aLocOrig = anOriginal.Location(); gp_Trsf aTrsfOrig = aLocOrig.Transformation(); //TopLoc_Location aLocRes (aTrsf * aTrsfOrig); // gp_Trsf::Multiply() has a bug aTrsfOrig.PreMultiply(aTrsf); TopLoc_Location aLocRes (aTrsfOrig); aShape = anOriginal.Located(aLocRes); } else if (aType == ROTATE_THREE_POINTS || aType == ROTATE_THREE_POINTS_COPY) { Handle(GEOM_Function) aCentPoint = RI.GetCentPoint(); Handle(GEOM_Function) aPoint1 = RI.GetPoint1(); Handle(GEOM_Function) aPoint2 = RI.GetPoint2(); if(aCentPoint.IsNull() || aPoint1.IsNull() || aPoint2.IsNull()) return 0; TopoDS_Shape aCV = aCentPoint->GetValue(); TopoDS_Shape aV1 = aPoint1->GetValue(); TopoDS_Shape aV2 = aPoint2->GetValue(); if(aCV.IsNull() || aCV.ShapeType() != TopAbs_VERTEX) return 0; if(aV1.IsNull() || aV1.ShapeType() != TopAbs_VERTEX) return 0; if(aV2.IsNull() || aV2.ShapeType() != TopAbs_VERTEX) return 0; aCP = BRep_Tool::Pnt(TopoDS::Vertex(aCV)); aP1 = BRep_Tool::Pnt(TopoDS::Vertex(aV1)); aP2 = BRep_Tool::Pnt(TopoDS::Vertex(aV2)); gp_Vec aVec1 (aCP, aP1); gp_Vec aVec2 (aCP, aP2); gp_Dir aDir (aVec1 ^ aVec2); gp_Ax1 anAx1 (aCP, aDir); Standard_Real anAngle = aVec1.Angle(aVec2); if (fabs(anAngle) < Precision::Angular()) anAngle += 2*PI; // NPAL19665 aTrsf.SetRotation(anAx1, anAngle); //NPAL18620: performance problem: multiple locations are accumulated // in shape and need a great time to process //BRepBuilderAPI_Transform aTransformation(anOriginal, aTrsf, Standard_False); //aShape = aTransformation.Shape(); TopLoc_Location aLocOrig = anOriginal.Location(); gp_Trsf aTrsfOrig = aLocOrig.Transformation(); //TopLoc_Location aLocRes (aTrsf * aTrsfOrig); // gp_Trsf::Multiply() has a bug aTrsfOrig.PreMultiply(aTrsf); TopLoc_Location aLocRes (aTrsfOrig); aShape = anOriginal.Located(aLocRes); } else if (aType == ROTATE_1D) { //Get direction Handle(GEOM_Function) anAxis = RI.GetAxis(); if(anAxis.IsNull()) return 0; TopoDS_Shape A = anAxis->GetValue(); if(A.IsNull() || A.ShapeType() != TopAbs_EDGE) return 0; TopoDS_Edge anEdge = TopoDS::Edge(A); gp_Pnt aP1 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge)); gp_Pnt aP2 = BRep_Tool::Pnt(TopExp::LastVertex(anEdge)); gp_Dir D(gp_Vec(aP1, aP2)); gp_Ax1 AX1(aP1, D); Standard_Integer nbtimes = RI.GetNbIter1(); Standard_Real angle = 360.0/nbtimes; TopoDS_Compound aCompound; BRep_Builder B; B.MakeCompound( aCompound ); TopLoc_Location aLocOrig = anOriginal.Location(); gp_Trsf aTrsfOrig = aLocOrig.Transformation(); for (int i = 0; i < nbtimes; i++ ) { if (i == 0) { // NPAL19665 B.Add(aCompound, anOriginal); } else { aTrsf.SetRotation(AX1, i*angle/* * PI180 */); //TopLoc_Location aLocRes (aTrsf * aTrsfOrig); // gp_Trsf::Multiply() has a bug gp_Trsf aTrsfNew (aTrsfOrig); aTrsfNew.PreMultiply(aTrsf); TopLoc_Location aLocRes (aTrsfNew); B.Add(aCompound, anOriginal.Located(aLocRes)); } //NPAL18620: performance problem: multiple locations are accumulated // in shape and need a great time to process //BRepBuilderAPI_Transform aBRepTransformation(anOriginal, aTrsf, Standard_False); //B.Add(aCompound, aBRepTransformation.Shape()); } aShape = aCompound; } else if (aType == ROTATE_2D) { //Get direction Handle(GEOM_Function) anAxis = RI.GetAxis(); if(anAxis.IsNull()) return 0; TopoDS_Shape A = anAxis->GetValue(); if(A.IsNull() || A.ShapeType() != TopAbs_EDGE) return 0; TopoDS_Edge anEdge = TopoDS::Edge(A); gp_Pnt aP1 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge)); gp_Pnt aP2 = BRep_Tool::Pnt(TopExp::LastVertex(anEdge)); gp_Dir D(gp_Vec(aP1, aP2)); gp_Ax1 AX1(aP1, D); gp_Trsf aTrsf1; gp_Trsf aTrsf2; gp_Trsf aTrsf3; gp_XYZ aDir2 = RI.GetDir2(); // can be set by previous execution if (aDir2.Modulus() < gp::Resolution()) { // Calculate direction as vector from the axis to the shape's center gp_Pnt P1; GProp_GProps System; if (anOriginal.ShapeType() == TopAbs_VERTEX) { P1 = BRep_Tool::Pnt(TopoDS::Vertex( anOriginal )); } else if ( anOriginal.ShapeType() == TopAbs_EDGE || anOriginal.ShapeType() == TopAbs_WIRE ) { BRepGProp::LinearProperties(anOriginal, System); P1 = System.CentreOfMass(); } else if ( anOriginal.ShapeType() == TopAbs_FACE || anOriginal.ShapeType() == TopAbs_SHELL ) { BRepGProp::SurfaceProperties(anOriginal, System); P1 = System.CentreOfMass(); } else { BRepGProp::VolumeProperties(anOriginal, System); P1 = System.CentreOfMass(); } Handle(Geom_Line) Line = new Geom_Line(AX1); GeomAPI_ProjectPointOnCurve aPrjTool( P1, Line ); gp_Pnt P2 = aPrjTool.NearestPoint(); if ( P1.IsEqual(P2, Precision::Confusion() ) ) return 0; aDir2 = gp_XYZ(P1.X()-P2.X(), P1.Y()-P2.Y(), P1.Z()-P2.Z()); // Attention: this abnormal action is done for good working of // TransformLikeOther(), used by RestoreSubShapes functionality RI.SetDir2(aDir2); } gp_Vec Vec (aDir2); Vec.Normalize(); gp_Vec elevVec(D); elevVec.Normalize(); Standard_Integer nbtimes2 = RI.GetNbIter2(); Standard_Integer nbtimes1 = RI.GetNbIter1(); Standard_Real step = RI.GetStep(); Standard_Real elevationstep = RI.GetElevationStep(); Standard_Real ang = RI.GetAngle(); TopLoc_Location aLocOrig = anOriginal.Location(); gp_Trsf aTrsfOrig = aLocOrig.Transformation(); gp_Vec aVec; TopoDS_Compound aCompound; BRep_Builder B; B.MakeCompound( aCompound ); Standard_Real DX, DY, DZ; for (int i = 0; i < nbtimes2; i++ ) { if (i != 0) { DX = i * step * Vec.X(); DY = i * step * Vec.Y(); DZ = i * step * Vec.Z(); aVec.SetCoord( DX, DY, DZ ); aTrsf1.SetTranslation(aVec); } for (int j = 0; j < nbtimes1; j++ ) { if (j == 0) { // NPAL19665 TopLoc_Location aLocRes (aTrsf1 * aTrsfOrig); B.Add(aCompound, anOriginal.Located(aLocRes)); } else { DX = j * elevationstep * elevVec.X(); DY = j * elevationstep * elevVec.Y(); DZ = j * elevationstep * elevVec.Z(); aVec.SetCoord( DX, DY, DZ ); aTrsf3.SetTranslation(aVec); aTrsf2.SetRotation(AX1, j*ang /* * PI180 */ ); //TopLoc_Location aLocRes (aTrsf2 * aTrsf1 * aTrsfOrig); // gp_Trsf::Multiply() has a bug gp_Trsf aTrsfNew (aTrsfOrig); aTrsfNew.PreMultiply(aTrsf1); aTrsfNew.PreMultiply(aTrsf2); aTrsfNew.PreMultiply(aTrsf3); TopLoc_Location aLocRes (aTrsfNew); B.Add(aCompound, anOriginal.Located(aLocRes)); } //NPAL18620: performance problem: multiple locations are accumulated // in shape and need a great time to process //BRepBuilderAPI_Transform aBRepTrsf1 (anOriginal, aTrsf1, Standard_False); //BRepBuilderAPI_Transform aBRepTrsf2 (aBRepTrsf1.Shape(), aTrsf2, Standard_False); //B.Add(aCompound, aBRepTrsf2.Shape()); } } aShape = aCompound; } else return 0; if (aShape.IsNull()) return 0; aFunction->SetValue(aShape); log.SetTouched(Label()); return 1; }
bool GraphicImporter::import() { bool success = false; if ( m_fileName.empty() ) { TopoDS_Shape shape; if ( m_shapeName.compare( "cube" ) == 0 ) { shape = OCCPartFactory::makeCube( 10, 10, 10 ); } if ( m_shapeName.compare( "cylinder" ) == 0 ) { shape = OCCPartFactory::makeCylinder( 5, 10 ); } if ( m_shapeName.compare( "bottle" ) == 0 ) { try { shape = OCCPartFactory::makeBottle( 50, 70, 30 ); } catch ( Standard_ConstructionError ) { shape.Nullify(); display_message( WARNING_MESSAGE, "Houston, we have a problem with the bottle" ); } } m_transformer->mapShape( shape ); if ( !shape.IsNull() ) success = true; } else { FileImportExport::FileFormat format = FileImportExport::FormatUnknown; FileImportExport reader; if ( m_fileName.rfind( ".brep" ) != std::string::npos || m_fileName.rfind( ".rle" ) != std::string::npos ) { format = FileImportExport::FormatBREP; } else if ( m_fileName.rfind( ".step" ) != std::string::npos || m_fileName.rfind( ".stp" ) != std::string::npos ) { format = FileImportExport::FormatSTEP; } else if ( m_fileName.rfind( ".iges" ) != std::string::npos || m_fileName.rfind( ".igs" ) != std::string::npos ) { format = FileImportExport::FormatIGES; } clock_t start, end; start = clock(); Handle_TopTools_HSequenceOfShape shapes; if ( reader.readModel( m_fileName, format ) ) { end = clock(); printf( "File read took %.2f seconds\n", ( end - start ) / double( CLOCKS_PER_SEC ) ); start = clock(); if ( reader.hasXDEInformation() ) m_transformer->mapShapes( reader.xDEInformation() ); else m_transformer->mapShapes( reader.sequenceOfShapes() ); end = clock(); printf( "Shape mapping took %.2f seconds\n", ( end - start ) / double( CLOCKS_PER_SEC ) ); success = true; } } return success; }
bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) { MESSAGE("NETGENPlugin_NETGEN_3D::Compute with maxElmentsize = " << _maxElementVolume); SMESHDS_Mesh* meshDS = aMesh.GetMeshDS(); const int invalid_ID = -1; SMESH::Controls::Area areaControl; SMESH::Controls::TSequenceOfXYZ nodesCoords; // ------------------------------------------------------------------- // get triangles on aShell and make a map of nodes to Netgen node IDs // ------------------------------------------------------------------- SMESH_MesherHelper helper(aMesh); SMESH_MesherHelper* myTool = &helper; bool _quadraticMesh = myTool->IsQuadraticSubMesh(aShape); typedef map< const SMDS_MeshNode*, int, TIDCompare > TNodeToIDMap; TNodeToIDMap nodeToNetgenID; list< const SMDS_MeshElement* > triangles; list< bool > isReversed; // orientation of triangles TopAbs_ShapeEnum mainType = aMesh.GetShapeToMesh().ShapeType(); bool checkReverse = ( mainType == TopAbs_COMPOUND || mainType == TopAbs_COMPSOLID ); // for the degeneraged edge: ignore all but one node on it; // map storing ids of degen edges and vertices and their netgen id: map< int, int* > degenShapeIdToPtrNgId; map< int, int* >::iterator shId_ngId; list< int > degenNgIds; StdMeshers_QuadToTriaAdaptor Adaptor; Adaptor.Compute(aMesh,aShape); for (TopExp_Explorer exp(aShape,TopAbs_FACE); exp.More(); exp.Next()) { const TopoDS_Shape& aShapeFace = exp.Current(); const SMESHDS_SubMesh * aSubMeshDSFace = meshDS->MeshElements( aShapeFace ); if ( aSubMeshDSFace ) { bool isRev = false; if ( checkReverse && helper.NbAncestors(aShapeFace, aMesh, aShape.ShapeType()) > 1 ) // IsReversedSubMesh() can work wrong on strongly curved faces, // so we use it as less as possible isRev = SMESH_Algo::IsReversedSubMesh( TopoDS::Face(aShapeFace), meshDS ); SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements(); while ( iteratorElem->more() ) // loop on elements on a face { // check element const SMDS_MeshElement* elem = iteratorElem->next(); if ( !elem ) return error( COMPERR_BAD_INPUT_MESH, "Null element encounters"); bool isTraingle = ( elem->NbNodes()==3 || (_quadraticMesh && elem->NbNodes()==6 )); if ( !isTraingle ) { //return error( COMPERR_BAD_INPUT_MESH, // SMESH_Comment("Not triangle element ")<<elem->GetID()); // using adaptor const list<const SMDS_FaceOfNodes*>* faces = Adaptor.GetTriangles(elem); if(faces==0) { return error( COMPERR_BAD_INPUT_MESH, SMESH_Comment("Not triangles in adaptor for element ")<<elem->GetID()); } list<const SMDS_FaceOfNodes*>::const_iterator itf = faces->begin(); for(; itf!=faces->end(); itf++ ) { triangles.push_back( (*itf) ); isReversed.push_back( isRev ); // put triange's nodes to nodeToNetgenID map SMDS_ElemIteratorPtr triangleNodesIt = (*itf)->nodesIterator(); while ( triangleNodesIt->more() ) { const SMDS_MeshNode * node = static_cast<const SMDS_MeshNode *>(triangleNodesIt->next()); if(myTool->IsMedium(node)) continue; nodeToNetgenID.insert( make_pair( node, invalid_ID )); } } } else { // keep a triangle triangles.push_back( elem ); isReversed.push_back( isRev ); // put elem nodes to nodeToNetgenID map SMDS_ElemIteratorPtr triangleNodesIt = elem->nodesIterator(); while ( triangleNodesIt->more() ) { const SMDS_MeshNode * node = static_cast<const SMDS_MeshNode *>(triangleNodesIt->next()); if(myTool->IsMedium(node)) continue; nodeToNetgenID.insert( make_pair( node, invalid_ID )); } } #ifdef _DEBUG_ // check if a trainge is degenerated areaControl.GetPoints( elem, nodesCoords ); double area = areaControl.GetValue( nodesCoords ); if ( area <= DBL_MIN ) { MESSAGE( "Warning: Degenerated " << elem ); } #endif } // look for degeneraged edges and vetices for (TopExp_Explorer expE(aShapeFace,TopAbs_EDGE); expE.More(); expE.Next()) { TopoDS_Edge aShapeEdge = TopoDS::Edge( expE.Current() ); if ( BRep_Tool::Degenerated( aShapeEdge )) { degenNgIds.push_back( invalid_ID ); int* ptrIdOnEdge = & degenNgIds.back(); // remember edge id int edgeID = meshDS->ShapeToIndex( aShapeEdge ); degenShapeIdToPtrNgId.insert( make_pair( edgeID, ptrIdOnEdge )); // remember vertex id int vertexID = meshDS->ShapeToIndex( TopExp::FirstVertex( aShapeEdge )); degenShapeIdToPtrNgId.insert( make_pair( vertexID, ptrIdOnEdge )); } } } } // --------------------------------- // Feed the Netgen with surface mesh // --------------------------------- int Netgen_NbOfNodes = 0; int Netgen_param2ndOrder = 0; double Netgen_paramFine = 1.; double Netgen_paramSize = pow( 72, 1/6. ) * pow( _maxElementVolume, 1/3. ); double Netgen_point[3]; int Netgen_triangle[3]; int Netgen_tetrahedron[4]; Ng_Init(); Ng_Mesh * Netgen_mesh = Ng_NewMesh(); // set nodes and remember thier netgen IDs bool isDegen = false, hasDegen = !degenShapeIdToPtrNgId.empty(); TNodeToIDMap::iterator n_id = nodeToNetgenID.begin(); for ( ; n_id != nodeToNetgenID.end(); ++n_id ) { const SMDS_MeshNode* node = n_id->first; // ignore nodes on degenerated edge if ( hasDegen ) { int shapeId = node->GetPosition()->GetShapeId(); shId_ngId = degenShapeIdToPtrNgId.find( shapeId ); isDegen = ( shId_ngId != degenShapeIdToPtrNgId.end() ); if ( isDegen && *(shId_ngId->second) != invalid_ID ) { n_id->second = *(shId_ngId->second); continue; } } Netgen_point [ 0 ] = node->X(); Netgen_point [ 1 ] = node->Y(); Netgen_point [ 2 ] = node->Z(); Ng_AddPoint(Netgen_mesh, Netgen_point); n_id->second = ++Netgen_NbOfNodes; // set netgen ID if ( isDegen ) // all nodes on a degen edge get one netgen ID *(shId_ngId->second) = n_id->second; } // set triangles list< const SMDS_MeshElement* >::iterator tria = triangles.begin(); list< bool >::iterator reverse = isReversed.begin(); for ( ; tria != triangles.end(); ++tria, ++reverse ) { int i = 0; SMDS_ElemIteratorPtr triangleNodesIt = (*tria)->nodesIterator(); while ( triangleNodesIt->more() ) { const SMDS_MeshNode * node = static_cast<const SMDS_MeshNode *>(triangleNodesIt->next()); if(myTool->IsMedium(node)) continue; Netgen_triangle[ *reverse ? 2 - i : i ] = nodeToNetgenID[ node ]; ++i; } if ( !hasDegen || // ignore degenerated triangles, they have 2 or 3 same ids (Netgen_triangle[0] != Netgen_triangle[1] && Netgen_triangle[0] != Netgen_triangle[2] && Netgen_triangle[2] != Netgen_triangle[1] )) { Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle); } } // ------------------------- // Generate the volume mesh // ------------------------- Ng_Meshing_Parameters Netgen_param; Netgen_param.secondorder = Netgen_param2ndOrder; Netgen_param.fineness = Netgen_paramFine; Netgen_param.maxh = Netgen_paramSize; Ng_Result status; try { #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 OCC_CATCH_SIGNALS; #endif status = Ng_GenerateVolumeMesh(Netgen_mesh, &Netgen_param); } catch (Standard_Failure& exc) { error(COMPERR_OCC_EXCEPTION, exc.GetMessageString()); status = NG_VOLUME_FAILURE; } catch (...) { error("Exception in Ng_GenerateVolumeMesh()"); status = NG_VOLUME_FAILURE; } if ( GetComputeError()->IsOK() ) { switch ( status ) { case NG_SURFACE_INPUT_ERROR: error( status, "NG_SURFACE_INPUT_ERROR"); case NG_VOLUME_FAILURE: error( status, "NG_VOLUME_FAILURE"); case NG_STL_INPUT_ERROR: error( status, "NG_STL_INPUT_ERROR"); case NG_SURFACE_FAILURE: error( status, "NG_SURFACE_FAILURE"); case NG_FILE_NOT_FOUND: error( status, "NG_FILE_NOT_FOUND"); }; } int Netgen_NbOfNodesNew = Ng_GetNP(Netgen_mesh); int Netgen_NbOfTetra = Ng_GetNE(Netgen_mesh); MESSAGE("End of Volume Mesh Generation. status=" << status << ", nb new nodes: " << Netgen_NbOfNodesNew - Netgen_NbOfNodes << ", nb tetra: " << Netgen_NbOfTetra); // ------------------------------------------------------------------- // Feed back the SMESHDS with the generated Nodes and Volume Elements // ------------------------------------------------------------------- bool isOK = ( /*status == NG_OK &&*/ Netgen_NbOfTetra > 0 );// get whatever built if ( isOK ) { // vector of nodes in which node index == netgen ID vector< const SMDS_MeshNode* > nodeVec ( Netgen_NbOfNodesNew + 1 ); // insert old nodes into nodeVec for ( n_id = nodeToNetgenID.begin(); n_id != nodeToNetgenID.end(); ++n_id ) { nodeVec.at( n_id->second ) = n_id->first; } // create and insert new nodes into nodeVec int nodeIndex = Netgen_NbOfNodes + 1; int shapeID = meshDS->ShapeToIndex( aShape ); for ( ; nodeIndex <= Netgen_NbOfNodesNew; ++nodeIndex ) { Ng_GetPoint( Netgen_mesh, nodeIndex, Netgen_point ); SMDS_MeshNode * node = meshDS->AddNode(Netgen_point[0], Netgen_point[1], Netgen_point[2]); meshDS->SetNodeInVolume(node, shapeID); nodeVec.at(nodeIndex) = node; } // create tetrahedrons for ( int elemIndex = 1; elemIndex <= Netgen_NbOfTetra; ++elemIndex ) { Ng_GetVolumeElement(Netgen_mesh, elemIndex, Netgen_tetrahedron); SMDS_MeshVolume * elt = myTool->AddVolume (nodeVec.at( Netgen_tetrahedron[0] ), nodeVec.at( Netgen_tetrahedron[1] ), nodeVec.at( Netgen_tetrahedron[2] ), nodeVec.at( Netgen_tetrahedron[3] )); meshDS->SetMeshElementOnShape(elt, shapeID ); } } Ng_DeleteMesh(Netgen_mesh); Ng_Exit(); NETGENPlugin_Mesher::RemoveTmpFiles(); return (status == NG_OK); }
//! project a single face using HLR - used for section faces TopoDS_Face DrawViewSection::projectFace(const TopoDS_Shape &face, gp_Pnt faceCenter, const Base::Vector3d &direction) { if(face.IsNull()) { throw Base::Exception("DrawViewSection::projectFace - input Face is NULL"); } Base::Vector3d origin(faceCenter.X(),faceCenter.Y(),faceCenter.Z()); gp_Ax2 viewAxis = TechDrawGeometry::getViewAxis(origin,direction); HLRBRep_Algo *brep_hlr = new HLRBRep_Algo(); brep_hlr->Add(face); HLRAlgo_Projector projector( viewAxis ); brep_hlr->Projector(projector); brep_hlr->Update(); brep_hlr->Hide(); HLRBRep_HLRToShape hlrToShape(brep_hlr); TopoDS_Shape hardEdges = hlrToShape.VCompound(); // TopoDS_Shape outEdges = hlrToShape.OutLineVCompound(); std::vector<TopoDS_Edge> faceEdges; TopExp_Explorer expl(hardEdges, TopAbs_EDGE); int i; for (i = 1 ; expl.More(); expl.Next(),i++) { const TopoDS_Edge& edge = TopoDS::Edge(expl.Current()); if (edge.IsNull()) { Base::Console().Log("INFO - DVS::projectFace - hard edge: %d is NULL\n",i); continue; } faceEdges.push_back(edge); } //TODO: verify that outline edges aren't required //if edge is both hard & outline, it will be duplicated? are hard edges enough? // TopExp_Explorer expl2(outEdges, TopAbs_EDGE); // for (i = 1 ; expl2.More(); expl2.Next(),i++) { // const TopoDS_Edge& edge = TopoDS::Edge(expl2.Current()); // if (edge.IsNull()) { // Base::Console().Log("INFO - GO::projectFace - outline edge: %d is NULL\n",i); // continue; // } // bool addEdge = true; // //is edge already in faceEdges? maybe need to use explorer for this for IsSame to work? // for (auto& e:faceEdges) { // if (e.IsPartner(edge)) { // addEdge = false; // Base::Console().Message("TRACE - DVS::projectFace - skipping an edge 1\n"); // } // } // expl.ReInit(); // for (; expl.More(); expl.Next()){ // const TopoDS_Edge& eHard = TopoDS::Edge(expl.Current()); // if (eHard.IsPartner(edge)) { // addEdge = false; // Base::Console().Message("TRACE - DVS::projectFace - skipping an edge 2\n"); // } // } // if (addEdge) { // faceEdges.push_back(edge); // } // } TopoDS_Face projectedFace; if (faceEdges.empty()) { Base::Console().Log("LOG - DVS::projectFace - no faceEdges\n"); return projectedFace; } //recreate the wires for this single face EdgeWalker ew; ew.loadEdges(faceEdges); bool success = ew.perform(); if (success) { std::vector<TopoDS_Wire> fw = ew.getResultNoDups(); if (!fw.empty()) { std::vector<TopoDS_Wire> sortedWires = ew.sortStrip(fw, true); if (sortedWires.empty()) { return projectedFace; } BRepBuilderAPI_MakeFace mkFace(sortedWires.front(),true); //true => only want planes? std::vector<TopoDS_Wire>::iterator itWire = ++sortedWires.begin(); //starting with second face for (; itWire != sortedWires.end(); itWire++) { mkFace.Add(*itWire); } projectedFace = mkFace.Face(); } } else { Base::Console().Warning("DVS::projectFace - input is not planar graph. No face detection\n"); } return projectedFace; }
int TaskCheckGeometryResults::goBOPSingleCheck(const TopoDS_Shape& shapeIn, ResultEntry *theRoot, const QString &baseName) { //ArgumentAnalyser was moved at version 6.6. no back port for now. #if OCC_VERSION_HEX >= 0x060600 //Reference use: src/BOPTest/BOPTest_CheckCommands.cxx //I don't why we need to make a copy, but it doesn't work without it. //BRepAlgoAPI_Check also makes a copy of the shape. //didn't use BRepAlgoAPI_Check because it calls BRepCheck_Analyzer itself and //doesnt give us access to it. so I didn't want to run BRepCheck_Analyzer twice to get invalid results. //BOPAlgo_ArgumentAnalyzer can check 2 objects with respect to a boolean op. //this is left for another time. TopoDS_Shape BOPCopy = BRepBuilderAPI_Copy(shapeIn).Shape(); BOPAlgo_ArgumentAnalyzer BOPCheck; // BOPCheck.StopOnFirstFaulty() = true; //this doesn't run any faster but gives us less results. BOPCheck.SetShape1(BOPCopy); //all settings are false by default. so only turn on what we want. BOPCheck.ArgumentTypeMode() = true; BOPCheck.SelfInterMode() = true; BOPCheck.SmallEdgeMode() = true; BOPCheck.RebuildFaceMode() = true; #if OCC_VERSION_HEX >= 0x060700 BOPCheck.ContinuityMode() = true; #endif #if OCC_VERSION_HEX >= 0x060900 BOPCheck.SetParallelMode(true); //this doesn't help for speed right now(occt 6.9.1). BOPCheck.TangentMode() = true; //these 4 new tests add about 5% processing time. BOPCheck.MergeVertexMode() = true; BOPCheck.CurveOnSurfaceMode() = true; BOPCheck.MergeEdgeMode() = true; #endif Base::TimeInfo start_time; BOPCheck.Perform(); float bopAlgoTime = Base::TimeInfo::diffTimeF(start_time,Base::TimeInfo()); #ifdef FC_DEBUG std::cout << std::endl << "BopAlgo check time is: " << bopAlgoTime << std::endl << std::endl; #endif if (!BOPCheck.HasFaulty()) return 0; ResultEntry *entry = new ResultEntry(); entry->parent = theRoot; entry->shape = BOPCopy; //this will cause a problem, with existing entry. i.e. entry is true. entry->name = baseName; entry->type = shapeEnumToString(shapeIn.ShapeType()); entry->error = QObject::tr("Invalid"); entry->viewProviderRoot = currentSeparator; entry->viewProviderRoot->ref(); goSetupResultBoundingBox(entry); theRoot->children.push_back(entry); const BOPAlgo_ListOfCheckResult &BOPResults = BOPCheck.GetCheckResult(); BOPAlgo_ListIteratorOfListOfCheckResult BOPResultsIt(BOPResults); for (; BOPResultsIt.More(); BOPResultsIt.Next()) { const BOPAlgo_CheckResult ¤t = BOPResultsIt.Value(); const BOPCol_ListOfShape &faultyShapes1 = current.GetFaultyShapes1(); BOPCol_ListIteratorOfListOfShape faultyShapes1It(faultyShapes1); for (;faultyShapes1It.More(); faultyShapes1It.Next()) { const TopoDS_Shape &faultyShape = faultyShapes1It.Value(); ResultEntry *faultyEntry = new ResultEntry(); faultyEntry->parent = entry; faultyEntry->shape = faultyShape; faultyEntry->buildEntryName(); faultyEntry->type = shapeEnumToString(faultyShape.ShapeType()); faultyEntry->error = getBOPCheckString(current.GetCheckStatus()); faultyEntry->viewProviderRoot = currentSeparator; entry->viewProviderRoot->ref(); goSetupResultBoundingBox(faultyEntry); if (faultyShape.ShapeType() == TopAbs_FACE) { goSetupResultTypedSelection(faultyEntry, faultyShape, TopAbs_FACE); } else if (faultyShape.ShapeType() == TopAbs_EDGE) { goSetupResultTypedSelection(faultyEntry, faultyShape, TopAbs_EDGE); } else if (faultyShape.ShapeType() == TopAbs_VERTEX) { goSetupResultTypedSelection(faultyEntry, faultyShape, TopAbs_VERTEX); } entry->children.push_back(faultyEntry); } } return 1; #else return 0; #endif }
void TaskCheckGeometryResults::goCheck() { Gui::WaitCursor wc; int selectedCount(0), checkedCount(0), invalidShapes(0); std::vector<Gui::SelectionSingleton::SelObj> selection = Gui::Selection().getSelection(); std::vector<Gui::SelectionSingleton::SelObj>::iterator it; ResultEntry *theRoot = new ResultEntry(); for (it = selection.begin(); it != selection.end(); ++it) { selectedCount++; Part::Feature *feature = dynamic_cast<Part::Feature *>((*it).pObject); if (!feature) continue; currentSeparator = Gui::Application::Instance->activeDocument()->getViewProvider(feature)->getRoot(); if (!currentSeparator) continue; TopoDS_Shape shape = feature->Shape.getValue(); QString baseName; QTextStream baseStream(&baseName); baseStream << (*it).DocName; baseStream << "." << (*it).FeatName; if (strlen((*it).SubName) > 0) { shape = feature->Shape.getShape().getSubShape((*it).SubName); baseStream << "." << (*it).SubName; } if (shape.IsNull()) continue; checkedCount++; checkedMap.Clear(); buildShapeContent(baseName, shape); BRepCheck_Analyzer shapeCheck(shape); if (!shapeCheck.IsValid()) { invalidShapes++; ResultEntry *entry = new ResultEntry(); entry->parent = theRoot; entry->shape = shape; entry->name = baseName; entry->type = shapeEnumToString(shape.ShapeType()); entry->error = QObject::tr("Invalid"); entry->viewProviderRoot = currentSeparator; entry->viewProviderRoot->ref(); goSetupResultBoundingBox(entry); theRoot->children.push_back(entry); recursiveCheck(shapeCheck, shape, entry); continue; //don't run BOPAlgo_ArgumentAnalyzer if BRepCheck_Analyzer finds something. } else { //BOPAlgo_ArgumentAnalyzer can be really slow! //so only run it when the shape seems valid to BRepCheck_Analyzer And //when the option is set. ParameterGrp::handle group = App::GetApplication().GetUserParameter(). GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry"); bool runSignal = group->GetBool("RunBOPCheck", false); //for now, user has edit the config file to turn it on. //following line ensures that the config file has the setting. group->SetBool("RunBOPCheck", runSignal); if (runSignal) invalidShapes += goBOPSingleCheck(shape, theRoot, baseName); } } model->setResults(theRoot); treeView->expandAll(); treeView->header()->resizeSections(QHeaderView::ResizeToContents); QString aMessage; QTextStream aStream(&aMessage); aStream << checkedCount << " processed out of " << selectedCount << " selected\n"; aStream << invalidShapes << " invalid shapes."; message->setText(aMessage); Gui::Selection().clearSelection(); }
App::DocumentObjectExecReturn *Draft::execute(void) { // Get parameters // Base shape Part::TopoShape TopShape; try { TopShape = getBaseShape(); } catch (Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } // Faces where draft should be applied // Note: Cannot be const reference currently because of BRepOffsetAPI_DraftAngle::Remove() bug, see below std::vector<std::string> SubVals = Base.getSubValuesStartsWith("Face"); if (SubVals.size() == 0) return new App::DocumentObjectExecReturn("No faces specified"); // Draft angle double angle = Angle.getValue() / 180.0 * M_PI; // Pull direction gp_Dir pullDirection; App::DocumentObject* refDirection = PullDirection.getValue(); if (refDirection != NULL) { if (refDirection->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) { PartDesign::Line* line = static_cast<PartDesign::Line*>(refDirection); Base::Vector3d d = line->getDirection(); pullDirection = gp_Dir(d.x, d.y, d.z); } else if (refDirection->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { std::vector<std::string> subStrings = PullDirection.getSubValues(); if (subStrings.empty() || subStrings[0].empty()) throw Base::Exception("No pull direction reference specified"); Part::Feature* refFeature = static_cast<Part::Feature*>(refDirection); Part::TopoShape refShape = refFeature->Shape.getShape(); TopoDS_Shape ref = refShape.getSubShape(subStrings[0].c_str()); if (ref.ShapeType() == TopAbs_EDGE) { TopoDS_Edge refEdge = TopoDS::Edge(ref); if (refEdge.IsNull()) throw Base::Exception("Failed to extract pull direction reference edge"); BRepAdaptor_Curve adapt(refEdge); if (adapt.GetType() != GeomAbs_Line) throw Base::Exception("Pull direction reference edge must be linear"); pullDirection = adapt.Line().Direction(); } else { throw Base::Exception("Pull direction reference must be an edge or a datum line"); } } else { throw Base::Exception("Pull direction reference must be an edge of a feature or a datum line"); } TopLoc_Location invObjLoc = this->getLocation().Inverted(); pullDirection.Transform(invObjLoc.Transformation()); } // Neutral plane gp_Pln neutralPlane; App::DocumentObject* refPlane = NeutralPlane.getValue(); if (refPlane == NULL) { // Try to guess a neutral plane from the first selected face // Get edges of first selected face TopoDS_Shape face = TopShape.getSubShape(SubVals[0].c_str()); TopTools_IndexedMapOfShape mapOfEdges; TopExp::MapShapes(face, TopAbs_EDGE, mapOfEdges); bool found = false; for (int i = 1; i <= mapOfEdges.Extent(); i++) { // Note: What happens if mapOfEdges(i) is the degenerated edge of a cone? // But in that case the draft is not possible anyway! BRepAdaptor_Curve c(TopoDS::Edge(mapOfEdges(i))); gp_Pnt p1 = c.Value(c.FirstParameter()); gp_Pnt p2 = c.Value(c.LastParameter()); if (c.IsClosed()) { // Edge is a circle or a circular arc (other types are not allowed for drafting) neutralPlane = gp_Pln(p1, c.Circle().Axis().Direction()); found = true; break; } else { // Edge is linear // Find midpoint of edge and create auxiliary plane through midpoint normal to edge gp_Pnt pm = c.Value((c.FirstParameter() + c.LastParameter()) / 2.0); Handle(Geom_Plane) aux = new Geom_Plane(pm, gp_Dir(p2.X() - p1.X(), p2.Y() - p1.Y(), p2.Z() - p1.Z())); // Intersect plane with face. Is there no easier way? BRepAdaptor_Surface adapt(TopoDS::Face(face), Standard_False); Handle(Geom_Surface) sf = adapt.Surface().Surface(); GeomAPI_IntSS intersector(aux, sf, Precision::Confusion()); if (!intersector.IsDone()) continue; Handle(Geom_Curve) icurve = intersector.Line(1); if (!icurve->IsKind(STANDARD_TYPE(Geom_Line))) continue; // TODO: How to extract the line from icurve without creating an edge first? TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(icurve); BRepAdaptor_Curve c(edge); neutralPlane = gp_Pln(pm, c.Line().Direction()); found = true; break; } } if (!found) throw Base::Exception("No neutral plane specified and none can be guessed"); } else { if (refPlane->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId())) { PartDesign::Plane* plane = static_cast<PartDesign::Plane*>(refPlane); Base::Vector3d b = plane->getBasePoint(); Base::Vector3d n = plane->getNormal(); neutralPlane = gp_Pln(gp_Pnt(b.x, b.y, b.z), gp_Dir(n.x, n.y, n.z)); } else if (refPlane->getTypeId().isDerivedFrom(App::Plane::getClassTypeId())) { neutralPlane = Feature::makePlnFromPlane(refPlane); } else if (refPlane->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { std::vector<std::string> subStrings = NeutralPlane.getSubValues(); if (subStrings.empty() || subStrings[0].empty()) throw Base::Exception("No neutral plane reference specified"); Part::Feature* refFeature = static_cast<Part::Feature*>(refPlane); Part::TopoShape refShape = refFeature->Shape.getShape(); TopoDS_Shape ref = refShape.getSubShape(subStrings[0].c_str()); if (ref.ShapeType() == TopAbs_FACE) { TopoDS_Face refFace = TopoDS::Face(ref); if (refFace.IsNull()) throw Base::Exception("Failed to extract neutral plane reference face"); BRepAdaptor_Surface adapt(refFace); if (adapt.GetType() != GeomAbs_Plane) throw Base::Exception("Neutral plane reference face must be planar"); neutralPlane = adapt.Plane(); } else if (ref.ShapeType() == TopAbs_EDGE) { if (refDirection != NULL) { // Create neutral plane through edge normal to pull direction TopoDS_Edge refEdge = TopoDS::Edge(ref); if (refEdge.IsNull()) throw Base::Exception("Failed to extract neutral plane reference edge"); BRepAdaptor_Curve c(refEdge); if (c.GetType() != GeomAbs_Line) throw Base::Exception("Neutral plane reference edge must be linear"); double a = c.Line().Angle(gp_Lin(c.Value(c.FirstParameter()), pullDirection)); if (std::fabs(a - M_PI_2) > Precision::Confusion()) throw Base::Exception("Neutral plane reference edge must be normal to pull direction"); neutralPlane = gp_Pln(c.Value(c.FirstParameter()), pullDirection); } else { throw Base::Exception("Neutral plane reference can only be an edge if pull direction is defined"); } } else { throw Base::Exception("Neutral plane reference must be a face"); } } else { throw Base::Exception("Neutral plane reference must be face of a feature or a datum plane"); } TopLoc_Location invObjLoc = this->getLocation().Inverted(); neutralPlane.Transform(invObjLoc.Transformation()); } if (refDirection == NULL) { // Choose pull direction normal to neutral plane pullDirection = neutralPlane.Axis().Direction(); } // Reversed pull direction bool reversed = Reversed.getValue(); if (reversed) angle *= -1.0; this->positionByBaseFeature(); // create an untransformed copy of the base shape Part::TopoShape baseShape(TopShape); baseShape.setTransform(Base::Matrix4D()); try { BRepOffsetAPI_DraftAngle mkDraft; // Note: // LocOpe_SplitDrafts can split a face with a wire and apply draft to both parts // Not clear though whether the face must have free boundaries // LocOpe_DPrism can create a stand-alone draft prism. The sketch can only have a single // wire, though. // BRepFeat_MakeDPrism requires a support for the operation but will probably support multiple // wires in the sketch bool success; do { success = true; mkDraft.Init(baseShape.getShape()); for (std::vector<std::string>::iterator it=SubVals.begin(); it != SubVals.end(); ++it) { TopoDS_Face face = TopoDS::Face(baseShape.getSubShape(it->c_str())); // TODO: What is the flag for? mkDraft.Add(face, pullDirection, angle, neutralPlane); if (!mkDraft.AddDone()) { // Note: the function ProblematicShape returns the face on which the error occurred // Note: mkDraft.Remove() stumbles on a bug in Draft_Modification::Remove() and is // therefore unusable. See http://forum.freecadweb.org/viewtopic.php?f=10&t=3209&start=10#p25341 // The only solution is to discard mkDraft and start over without the current face // mkDraft.Remove(face); Base::Console().Error("Adding face failed on %s. Omitted\n", it->c_str()); success = false; SubVals.erase(it); break; } } } while (!success); mkDraft.Build(); if (!mkDraft.IsDone()) return new App::DocumentObjectExecReturn("Failed to create draft"); TopoDS_Shape shape = mkDraft.Shape(); if (shape.IsNull()) return new App::DocumentObjectExecReturn("Resulting shape is null"); this->Shape.setValue(getSolid(shape)); return App::DocumentObject::StdReturn; } catch (Standard_Failure) { Handle(Standard_Failure) e = Standard_Failure::Caught(); return new App::DocumentObjectExecReturn(e->GetMessageString()); } }
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; }
App::DocumentObjectExecReturn *Transformed::execute(void) { rejected.clear(); std::vector<App::DocumentObject*> originals = Originals.getValues(); if (originals.empty()) // typically InsideMultiTransform return App::DocumentObject::StdReturn; this->positionBySupport(); // get transformations from subclass by calling virtual method std::vector<gp_Trsf> transformations; try { std::list<gp_Trsf> t_list = getTransformations(originals); transformations.insert(transformations.end(), t_list.begin(), t_list.end()); } catch (Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } if (transformations.empty()) return App::DocumentObject::StdReturn; // No transformations defined, exit silently // Get the support Part::Feature* supportFeature; try { supportFeature = getBaseObject(); } catch (Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } const Part::TopoShape& supportTopShape = supportFeature->Shape.getShape(); if (supportTopShape._Shape.IsNull()) return new App::DocumentObjectExecReturn("Cannot transform invalid support shape"); // create an untransformed copy of the support shape Part::TopoShape supportShape(supportTopShape); supportShape.setTransform(Base::Matrix4D()); TopoDS_Shape support = supportShape._Shape; typedef std::set<std::vector<gp_Trsf>::const_iterator> trsf_it; typedef std::map<App::DocumentObject*, trsf_it> rej_it_map; rej_it_map nointersect_trsfms; // NOTE: It would be possible to build a compound from all original addShapes/subShapes and then // transform the compounds as a whole. But we choose to apply the transformations to each // Original separately. This way it is easier to discover what feature causes a fuse/cut // to fail. The downside is that performance suffers when there are many originals. But it seems // safe to assume that in most cases there are few originals and many transformations for (std::vector<App::DocumentObject*>::const_iterator o = originals.begin(); o != originals.end(); ++o) { // Extract the original shape and determine whether to cut or to fuse TopoDS_Shape shape; bool fuse; if ((*o)->getTypeId().isDerivedFrom(PartDesign::FeatureAddSub::getClassTypeId())) { PartDesign::FeatureAddSub* feature = static_cast<PartDesign::FeatureAddSub*>(*o); shape = feature->AddSubShape.getShape()._Shape; if (shape.IsNull()) return new App::DocumentObjectExecReturn("Shape of additive feature is empty"); fuse = (feature->getAddSubType() == FeatureAddSub::Additive) ? true : false; } else { return new App::DocumentObjectExecReturn("Only additive and subtractive features can be transformed"); } // Transform the add/subshape and collect the resulting shapes for overlap testing typedef std::vector<std::vector<gp_Trsf>::const_iterator> trsf_it_vec; trsf_it_vec v_transformations; std::vector<TopoDS_Shape> v_transformedShapes; std::vector<gp_Trsf>::const_iterator t = transformations.begin(); ++t; // Skip first transformation, which is always the identity transformation for (; t != transformations.end(); ++t) { // Make an explicit copy of the shape because the "true" parameter to BRepBuilderAPI_Transform // seems to be pretty broken BRepBuilderAPI_Copy copy(shape); shape = copy.Shape(); if (shape.IsNull()) return new App::DocumentObjectExecReturn("Transformed: Linked shape object is empty"); BRepBuilderAPI_Transform mkTrf(shape, *t, false); // No need to copy, now if (!mkTrf.IsDone()) return new App::DocumentObjectExecReturn("Transformation failed", (*o)); // Check for intersection with support try { if (!Part::checkIntersection(support, mkTrf.Shape(), false, true)) { #ifdef FC_DEBUG // do not write this in release mode because a message appears already in the task view Base::Console().Warning("Transformed shape does not intersect support %s: Removed\n", (*o)->getNameInDocument()); #endif nointersect_trsfms[*o].insert(t); } else { v_transformations.push_back(t); v_transformedShapes.push_back(mkTrf.Shape()); // Note: Transformations that do not intersect the support are ignored in the overlap tests } } catch (Standard_Failure) { // Note: Ignoring this failure is probably pointless because if the intersection check fails, the later // fuse operation of the transformation result will also fail Handle_Standard_Failure e = Standard_Failure::Caught(); std::string msg("Transformation: Intersection check failed"); if (e->GetMessageString() != NULL) msg += std::string(": '") + e->GetMessageString() + "'"; return new App::DocumentObjectExecReturn(msg.c_str()); } } if (v_transformedShapes.empty()) continue; // Skip the overlap check and go on to next original if (v_transformedShapes.empty()) continue; // Skip the boolean operation and go on to next original //insert scheme here. TopoDS_Compound compoundTool; std::vector<TopoDS_Shape> individualTools; divideTools(v_transformedShapes, individualTools, compoundTool); // Fuse/Cut the compounded transformed shapes with the support TopoDS_Shape result; TopoDS_Shape current = support; if (fuse) { BRepAlgoAPI_Fuse mkFuse(current, compoundTool); if (!mkFuse.IsDone()) return new App::DocumentObjectExecReturn("Fusion with support failed", *o); // we have to get the solids (fuse sometimes creates compounds) current = this->getSolid(mkFuse.Shape()); // lets check if the result is a solid if (current.IsNull()) return new App::DocumentObjectExecReturn("Resulting shape is not a solid", *o); std::vector<TopoDS_Shape>::const_iterator individualIt; for (individualIt = individualTools.begin(); individualIt != individualTools.end(); ++individualIt) { BRepAlgoAPI_Fuse mkFuse2(current, *individualIt); if (!mkFuse2.IsDone()) return new App::DocumentObjectExecReturn("Fusion with support failed", *o); // we have to get the solids (fuse sometimes creates compounds) current = this->getSolid(mkFuse2.Shape()); // lets check if the result is a solid if (current.IsNull()) return new App::DocumentObjectExecReturn("Resulting shape is not a solid", *o); } } else { BRepAlgoAPI_Cut mkCut(current, compoundTool); if (!mkCut.IsDone()) return new App::DocumentObjectExecReturn("Cut out of support failed", *o); current = mkCut.Shape(); std::vector<TopoDS_Shape>::const_iterator individualIt; for (individualIt = individualTools.begin(); individualIt != individualTools.end(); ++individualIt) { BRepAlgoAPI_Cut mkCut2(current, *individualIt); if (!mkCut2.IsDone()) return new App::DocumentObjectExecReturn("Cut out of support failed", *o); current = this->getSolid(mkCut2.Shape()); if (current.IsNull()) return new App::DocumentObjectExecReturn("Resulting shape is not a solid", *o); } } support = current; // Use result of this operation for fuse/cut of next original } support = refineShapeIfActive(support); for (rej_it_map::const_iterator it = nointersect_trsfms.begin(); it != nointersect_trsfms.end(); ++it) for (trsf_it::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) rejected[it->first].push_back(**it2); this->Shape.setValue(support); return App::DocumentObject::StdReturn; }
bool Constraint::getPoints(std::vector<Base::Vector3d> &points, std::vector<Base::Vector3d> &normals, int * scale) const { std::vector<App::DocumentObject*> Objects = References.getValues(); std::vector<std::string> SubElements = References.getSubValues(); // Extract geometry from References TopoDS_Shape sh; for (std::size_t i = 0; i < Objects.size(); i++) { App::DocumentObject* obj = Objects[i]; Part::Feature* feat = static_cast<Part::Feature*>(obj); const Part::TopoShape& toposhape = feat->Shape.getShape(); if (toposhape.isNull()) return false; sh = toposhape.getSubShape(SubElements[i].c_str()); if (sh.ShapeType() == TopAbs_VERTEX) { const TopoDS_Vertex& vertex = TopoDS::Vertex(sh); gp_Pnt p = BRep_Tool::Pnt(vertex); points.push_back(Base::Vector3d(p.X(), p.Y(), p.Z())); normals.push_back(NormalDirection.getValue()); //OvG: Scale by whole object mass in case of a vertex GProp_GProps props; BRepGProp::VolumeProperties(toposhape.getShape(), props); double lx = props.Mass(); *scale = this->calcDrawScaleFactor(sqrt(lx)*0.5); //OvG: setup draw scale for constraint } else if (sh.ShapeType() == TopAbs_EDGE) { BRepAdaptor_Curve curve(TopoDS::Edge(sh)); double fp = curve.FirstParameter(); double lp = curve.LastParameter(); GProp_GProps props; BRepGProp::LinearProperties(TopoDS::Edge(sh), props); double l = props.Mass(); // Create points with 10 units distance, but at least one at the beginning and end of the edge int steps; if (l >= 30) //OvG: Increase 10 units distance proportionately to l for larger objects. { *scale = this->calcDrawScaleFactor(l); //OvG: setup draw scale for constraint steps = (int)round(l / (10*( *scale))); steps = steps<3?3:steps; } else if (l >= 20) { steps = (int)round(l / 10); *scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint } else { steps = 1; *scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint } steps = steps>CONSTRAINTSTEPLIMIT?CONSTRAINTSTEPLIMIT:steps; //OvG: Place upper limit on number of steps double step = (lp - fp) / steps; for (int i = 0; i < steps + 1; i++) { gp_Pnt p = curve.Value(i * step); points.push_back(Base::Vector3d(p.X(), p.Y(), p.Z())); normals.push_back(NormalDirection.getValue()); } } else if (sh.ShapeType() == TopAbs_FACE) { TopoDS_Face face = TopoDS::Face(sh); // Surface boundaries BRepAdaptor_Surface surface(face); double ufp = surface.FirstUParameter(); double ulp = surface.LastUParameter(); double vfp = surface.FirstVParameter(); double vlp = surface.LastVParameter(); double l; double lv, lu; // Surface normals BRepGProp_Face props(face); gp_Vec normal; gp_Pnt center; // Get an estimate for the number of arrows by finding the average length of curves Handle(Adaptor3d_HSurface) hsurf; hsurf = new BRepAdaptor_HSurface(surface); Adaptor3d_IsoCurve isoc(hsurf); try { isoc.Load(GeomAbs_IsoU, ufp); l = GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion()); } catch (const Standard_Failure&) { gp_Pnt p1 = hsurf->Value(ufp, vfp); gp_Pnt p2 = hsurf->Value(ufp, vlp); l = p1.Distance(p2); } try { isoc.Load(GeomAbs_IsoU, ulp); lv = (l + GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion()))/2.0; } catch (const Standard_Failure&) { gp_Pnt p1 = hsurf->Value(ulp, vfp); gp_Pnt p2 = hsurf->Value(ulp, vlp); lv = (l + p1.Distance(p2))/2.0; } try { isoc.Load(GeomAbs_IsoV, vfp); l = GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion()); } catch (const Standard_Failure&) { gp_Pnt p1 = hsurf->Value(ufp, vfp); gp_Pnt p2 = hsurf->Value(ulp, vfp); l = p1.Distance(p2); } try { isoc.Load(GeomAbs_IsoV, vlp); lu = (l + GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion()))/2.0; } catch (const Standard_Failure&) { gp_Pnt p1 = hsurf->Value(ufp, vlp); gp_Pnt p2 = hsurf->Value(ulp, vlp); lu = (l + p1.Distance(p2))/2.0; } int stepsv; if (lv >= 30) //OvG: Increase 10 units distance proportionately to lv for larger objects. { *scale = this->calcDrawScaleFactor(lv,lu); //OvG: setup draw scale for constraint stepsv = (int)round(lv / (10*( *scale))); stepsv = stepsv<3?3:stepsv; } else if (lv >= 20.0) { stepsv = (int)round(lv / 10); *scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint } else { stepsv = 2; // Minimum of three arrows to ensure (as much as possible) that at least one is displayed *scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint } stepsv = stepsv>CONSTRAINTSTEPLIMIT?CONSTRAINTSTEPLIMIT:stepsv; //OvG: Place upper limit on number of steps int stepsu; if (lu >= 30) //OvG: Increase 10 units distance proportionately to lu for larger objects. { *scale = this->calcDrawScaleFactor(lv,lu); //OvG: setup draw scale for constraint stepsu = (int)round(lu / (10*( *scale))); stepsu = stepsu<3?3:stepsu; } else if (lu >= 20.0) { stepsu = (int)round(lu / 10); *scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint } else { stepsu = 2; *scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint } stepsu = stepsu>CONSTRAINTSTEPLIMIT?CONSTRAINTSTEPLIMIT:stepsu; //OvG: Place upper limit on number of steps double stepv = (vlp - vfp) / stepsv; double stepu = (ulp - ufp) / stepsu; // Create points and normals for (int i = 0; i < stepsv + 1; i++) { for (int j = 0; j < stepsu + 1; j++) { double v = vfp + i * stepv; double u = ufp + j * stepu; gp_Pnt p = surface.Value(u, v); BRepClass_FaceClassifier classifier(face, p, Precision::Confusion()); if (classifier.State() != TopAbs_OUT) { points.push_back(Base::Vector3d(p.X(), p.Y(), p.Z())); props.Normal(u, v,center,normal); normal.Normalize(); normals.push_back(Base::Vector3d(normal.X(), normal.Y(), normal.Z())); } } } } } return true; }
//================================================================ // Function : TexturesExt_Presentation::sampleKitchen // Purpose : kitchen with texturized items in it. //================================================================ void TexturesExt_Presentation::sampleKitchen() { TopoDS_Shape aShape; if (!loadShape(aShape, "Kitchen\\Room.brep")) return; gp_Trsf aTrsf; gp_Ax3 NewCoordSystem (gp_Pnt(-1,-1, -1),gp_Dir(0,0,1)); gp_Ax3 CurrentCoordSystem(gp_Pnt(0,0,0),gp_Dir(0,0,1)); aTrsf.SetDisplacement(CurrentCoordSystem, NewCoordSystem); aShape.Location(TopLoc_Location(aTrsf)); moveScale(aShape); // draw kitchen room whithout one wall (to better see the insides) TopTools_IndexedMapOfShape aFaces; TopExp::MapShapes(aShape, TopAbs_FACE, aFaces); Standard_Integer nbFaces = aFaces.Extent(); // create a wooden kitchen floor // the floor's face will be textured with texture from chataignier.gif DISP(Texturize(aFaces(5),"plancher.gif",1,1,2,1)); // texturize other faces of the room with texture from wallpaper.gif (walls) DISP(Texturize(aFaces(1),"wallpaper.gif",1,1,8,6)); DISP(Texturize(aFaces(3),"wallpaper.gif",1,1,8,6)); DISP(Texturize(aFaces(4),"wallpaper.gif",1,1,8,6)); // DISP(drawShape(aFaces(1), Quantity_NOC_LIGHTPINK, Standard_False)); // DISP(drawShape(aFaces(3), Quantity_NOC_LIGHTPINK, Standard_False)); // DISP(drawShape(aFaces(4), Quantity_NOC_LIGHTPINK, Standard_False)); // texturize furniture items with "wooden" texture if (loadShape(aShape, "Kitchen\\MODERN_Table_1.brep")) { moveScale(aShape); DISP(Texturize(aShape, "chataignier.gif")); } if (loadShape(aShape, "Kitchen\\MODERN_Chair_1.brep")) { moveScale(aShape); DISP(Texturize(aShape, "chataignier.gif")); } if (loadShape(aShape, "Kitchen\\MODERN_Cooker_1.brep")) { moveScale(aShape); aFaces.Clear(); TopExp::MapShapes(aShape, TopAbs_FACE, aFaces); nbFaces = aFaces.Extent(); for (Standard_Integer i = 1; i <= nbFaces; i++) { if (i >= 59) DISP(drawShape(aFaces(i), Graphic3d_NOM_STEEL, Standard_False)); else if (i >= 29) DISP(drawShape(aFaces(i), Graphic3d_NOM_ALUMINIUM, Standard_False)); else if (i == 28) DISP(Texturize(aFaces(i), "cookerplate.gif")); else DISP(Texturize(aFaces(i), "chataignier.gif")); } } if (loadShape(aShape, "Kitchen\\MODERN_Cooker_1_opened.brep")) { moveScale(aShape); DISP(Texturize(aShape, "chataignier.gif")); } if (loadShape(aShape, "Kitchen\\MODERN_Exhaust_1.brep")) { moveScale(aShape); DISP(drawShape(aShape, Graphic3d_NOM_STONE, Standard_False)); } if (loadShape(aShape, "Kitchen\\MODERN_MVCooker_1.brep")) { moveScale(aShape); DISP(drawShape(aShape, Graphic3d_NOM_SILVER, Standard_False)); } if (loadShape(aShape, "Kitchen\\MODERN_MVCooker_1_opened.brep")) { moveScale(aShape); DISP(drawShape(aShape, Graphic3d_NOM_SILVER, Standard_False)); } if (loadShape(aShape, "Kitchen\\MODERN_Sink_1.brep")) { moveScale(aShape); aFaces.Clear(); TopExp::MapShapes(aShape, TopAbs_FACE, aFaces); nbFaces = aFaces.Extent(); for (Standard_Integer i = 1; i <= nbFaces; i++) { if (i < 145) DISP(drawShape(aFaces(i), Graphic3d_NOM_ALUMINIUM, Standard_False)); else if (i == 145) DISP(Texturize(aFaces(i), "cookerplate.gif")); else DISP(Texturize(aFaces(i), "chataignier.gif")); } } if (loadShape(aShape, "Kitchen\\MODERN_Sink_1_opened.brep")) { moveScale(aShape); DISP(Texturize(aShape, "chataignier.gif")); } if (loadShape(aShape, "Kitchen\\MODERN_Refrigerator_1.brep")) { moveScale(aShape); DISP(drawShape(aShape, Graphic3d_NOM_CHROME, Standard_False)); } if (loadShape(aShape, "Kitchen\\MODERN_Refrigerator_1_opened.brep")) { moveScale(aShape); DISP(drawShape(aShape, Graphic3d_NOM_CHROME, Standard_False)); } getViewer()->Update(); }
//======================================================================= // function: MakeAloneVertices // purpose: //======================================================================= void NMTTools_PaveFiller::MakeAloneVertices() { Standard_Integer i, aNbFFs, nF1, nF2, j, aNbPnts, nFx, aNbV; Standard_Real aTolF1, aTolF2, aTolSum, aTolV; TColStd_ListIteratorOfListOfInteger aIt; TColStd_ListOfInteger aLI; TopoDS_Vertex aV; TopoDS_Compound aCompound; BRep_Builder aBB; TopTools_DataMapOfShapeListOfInteger aDMVFF, aDMVFF1; TopTools_DataMapIteratorOfDataMapOfShapeListOfInteger aItDMVFF; TopTools_DataMapOfShapeShape aDMVV; TopTools_DataMapOfIntegerShape aDMIV; TopTools_DataMapOfShapeInteger aDMVI; TopTools_DataMapIteratorOfDataMapOfShapeInteger aItDMVI; TopTools_DataMapIteratorOfDataMapOfIntegerShape aItDMIV; // aBB.MakeCompound(aCompound); // myAloneVertices.Clear(); // BOPTools_CArray1OfSSInterference& aFFs=myIP->SSInterferences(); // // 1. Collect alone vertices from FFs aNbV=0; aNbFFs=aFFs.Extent(); for (i=1; i<=aNbFFs; ++i) { BOPTools_SSInterference& aFFi=aFFs(i); aFFi.Indices(nF1, nF2); // const TopoDS_Face aF1=TopoDS::Face(myDS->Shape(nF1));//mpv const TopoDS_Face aF2=TopoDS::Face(myDS->Shape(nF2));//mpv // aTolF1=BRep_Tool::Tolerance(aF1); aTolF2=BRep_Tool::Tolerance(aF2); aTolSum=aTolF1+aTolF2; // aLI.Clear(); aLI.Append(nF1); aLI.Append(nF2); // const IntTools_SequenceOfPntOn2Faces& aSeqAlonePnts=aFFi.AlonePnts(); aNbPnts=aSeqAlonePnts.Length(); for (j=1; j<=aNbPnts; ++j) { const gp_Pnt& aP=aSeqAlonePnts(j).P1().Pnt(); BOPTools_Tools::MakeNewVertex(aP, aTolSum, aV); aDMVFF.Bind(aV, aLI); aBB.Add(aCompound, aV); ++aNbV; } } if (!aNbV) { return; } // // 2. Try to fuse alone vertices themselves; FuseVertices(aCompound, aDMVV); // // if some are fused, replace them by new ones aItDMVFF.Initialize(aDMVFF); for (; aItDMVFF.More(); aItDMVFF.Next()) { const TopoDS_Shape& aVx=aItDMVFF.Key(); const TColStd_ListOfInteger& aLIx=aItDMVFF.Value(); // if (!aDMVV.IsBound(aVx)) { aDMVFF1.Bind(aVx, aLIx); } else { const TopoDS_Shape& aVy=aDMVV.Find(aVx); if (aDMVFF1.IsBound(aVy)) { TColStd_ListOfInteger& aLIy=aDMVFF1.ChangeFind(aVy); aIt.Initialize(aLIx); for(; aIt.More(); aIt.Next()) { nFx=aIt.Value(); aLIy.Append(nFx); } } else { aDMVFF1.Bind(aVy, aLIx); } } } aDMVFF.Clear(); // // refine lists of faces in aDMVFF1; aItDMVFF.Initialize(aDMVFF1); for (; aItDMVFF.More(); aItDMVFF.Next()) { TColStd_MapOfInteger aMIy; TColStd_ListOfInteger aLIy; // const TopoDS_Shape& aVx=aItDMVFF.Key(); TColStd_ListOfInteger& aLIx=aDMVFF1.ChangeFind(aVx); aIt.Initialize(aLIx); for(; aIt.More(); aIt.Next()) { nFx=aIt.Value(); if (aMIy.Add(nFx)) { aLIy.Append(nFx); } } aLIx.Clear(); aLIx.Append(aLIy); } //================================== // // 3. Collect vertices from DS Standard_Integer aNbS, nV, nVSD, aNbVDS, i1, i2, aNbVSD; // aNbS=myDS->NumberOfShapesOfTheObject(); // old shapes for (i=1; i<=aNbS; ++i) { const TopoDS_Shape& aS=myDS->Shape(i); if (aS.ShapeType() != TopAbs_VERTEX){ continue; } // nVSD=FindSDVertex(i); nV=(nVSD) ? nVSD : i; const TopoDS_Shape& aVx=myDS->Shape(nV); if (!aDMVI.IsBound(aVx)) { aDMVI.Bind(aVx, nV); } } // new shapes i1=myDS->NumberOfSourceShapes()+1; i2=myDS->NumberOfInsertedShapes(); for (i=i1; i<=i2; ++i) { const TopoDS_Shape aS=myDS->Shape(i);//mpv if (aS.ShapeType() != TopAbs_VERTEX){ continue; } if (!aDMVI.IsBound(aS)) { aDMVI.Bind(aS, i); } } // // 4. Initialize BoundSortBox on aDMVI // Handle(Bnd_HArray1OfBox) aHAB; Bnd_BoundSortBox aBSB; // aNbVDS=aDMVI.Extent(); aHAB=new Bnd_HArray1OfBox(1, aNbVDS); // aItDMVI.Initialize(aDMVI); for (i=1; aItDMVI.More(); aItDMVI.Next(), ++i) { Bnd_Box aBox; // nV=aItDMVI.Value(); aV=TopoDS::Vertex(aItDMVI.Key()); aTolV=BRep_Tool::Tolerance(aV); aBox.SetGap(aTolV); BRepBndLib::Add(aV, aBox); aHAB->SetValue(i, aBox); // aDMIV.Bind(i, aV); } aBSB.Initialize(aHAB); // // 5. Compare aItDMVFF.Initialize(aDMVFF1); for (; aItDMVFF.More(); aItDMVFF.Next()) { Bnd_Box aBoxV; // const TColStd_ListOfInteger& aLIFF=aItDMVFF.Value(); aV=TopoDS::Vertex(aItDMVFF.Key()); // aTolV=BRep_Tool::Tolerance(aV); aBoxV.SetGap(aTolV); BRepBndLib::Add(aV, aBoxV); // const TColStd_ListOfInteger& aLIVSD=aBSB.Compare(aBoxV); aNbVSD=aLIVSD.Extent(); if (aNbVSD==0) { // add new vertex in DS and update map myAloneVertices BooleanOperations_AncestorsSeqAndSuccessorsSeq anASSeq; // myDS->InsertShapeAndAncestorsSuccessors(aV, anASSeq); nV=myDS->NumberOfInsertedShapes(); // aIt.Initialize(aLIFF); for (; aIt.More(); aIt.Next()) { nFx=aIt.Value(); if (myAloneVertices.Contains(nFx)) { TColStd_IndexedMapOfInteger& aMVx=myAloneVertices.ChangeFromKey(nFx); aMVx.Add(nV); } else { TColStd_IndexedMapOfInteger aMVx; aMVx.Add(nV); myAloneVertices.Add(nFx, aMVx); } } } } // qqf { Standard_Integer aNbF, aNbAV, nF, k; NMTTools_IndexedDataMapOfIndexedMapOfInteger aMAVF; // aNbF=myAloneVertices.Extent(); if (aNbF<2) { return; } // // 1. fill map Alone Vertex/Face -> aMAVF for (i=1; i<=aNbF; ++i) { nF=myAloneVertices.FindKey(i); const TColStd_IndexedMapOfInteger& aMAV=myAloneVertices(i); aNbAV=aMAV.Extent(); for(j=1; j<=aNbAV; ++j) { nV=aMAV(j); if (aMAVF.Contains(nV)) { TColStd_IndexedMapOfInteger& aMF=aMAVF.ChangeFromKey(nV); aMF.Add(nF); } else{ TColStd_IndexedMapOfInteger aMF; aMF.Add(nF); aMAVF.Add(nV, aMF); } } } // // 2 Obtain pairs of faces aNbAV=aMAVF.Extent(); for (i=1; i<=aNbAV; ++i) { const TColStd_IndexedMapOfInteger& aMF=aMAVF(i); aNbF=aMF.Extent(); for(j=1; j<aNbF; ++j) { nF1=aMF(j); for(k=j+1; k<=aNbF; ++k) { nF2=aMF(k); myIP->Add(nF1, nF2, Standard_True, NMTDS_TI_FF); } } } } // qqt }
bool SMESH_Algo::IsReversedSubMesh (const TopoDS_Face& theFace, SMESHDS_Mesh* theMeshDS) { if ( theFace.IsNull() || !theMeshDS ) return false; // find out orientation of a meshed face int faceID = theMeshDS->ShapeToIndex( theFace ); TopoDS_Shape aMeshedFace = theMeshDS->IndexToShape( faceID ); bool isReversed = ( theFace.Orientation() != aMeshedFace.Orientation() ); const SMESHDS_SubMesh * aSubMeshDSFace = theMeshDS->MeshElements( faceID ); if ( !aSubMeshDSFace ) return isReversed; // find element with node located on face and get its normal const SMDS_FacePosition* facePos = 0; int vertexID = 0; gp_Pnt nPnt[3]; gp_Vec Ne; bool normalOK = false; SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements(); while ( iteratorElem->more() ) // loop on elements on theFace { const SMDS_MeshElement* elem = iteratorElem->next(); if ( elem && elem->NbNodes() > 2 ) { SMDS_ElemIteratorPtr nodesIt = elem->nodesIterator(); const SMDS_FacePosition* fPos = 0; int i = 0, vID = 0; while ( nodesIt->more() ) { // loop on nodes const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode *>(nodesIt->next()); if ( i == 3 ) i = 2; nPnt[ i++ ].SetCoord( node->X(), node->Y(), node->Z() ); // check position const SMDS_PositionPtr& pos = node->GetPosition(); if ( !pos ) continue; if ( pos->GetTypeOfPosition() == SMDS_TOP_FACE ) { fPos = dynamic_cast< const SMDS_FacePosition* >( pos.get() ); } else if ( pos->GetTypeOfPosition() == SMDS_TOP_VERTEX ) { vID = pos->GetShapeId(); } } if ( fPos || ( !normalOK && vID )) { // compute normal gp_Vec v01( nPnt[0], nPnt[1] ), v02( nPnt[0], nPnt[2] ); if ( v01.SquareMagnitude() > RealSmall() && v02.SquareMagnitude() > RealSmall() ) { Ne = v01 ^ v02; normalOK = ( Ne.SquareMagnitude() > RealSmall() ); } // we need position on theFace or at least on vertex if ( normalOK ) { vertexID = vID; if ((facePos = fPos)) break; } } } } if ( !normalOK ) return isReversed; // node position on face double u,v; if ( facePos ) { u = facePos->GetUParameter(); v = facePos->GetVParameter(); } else if ( vertexID ) { TopoDS_Shape V = theMeshDS->IndexToShape( vertexID ); if ( V.IsNull() || V.ShapeType() != TopAbs_VERTEX ) return isReversed; gp_Pnt2d uv = BRep_Tool::Parameters( TopoDS::Vertex( V ), theFace ); u = uv.X(); v = uv.Y(); } else { return isReversed; } // face normal at node position TopLoc_Location loc; Handle(Geom_Surface) surf = BRep_Tool::Surface( theFace, loc ); if ( surf.IsNull() || surf->Continuity() < GeomAbs_C1 ) return isReversed; gp_Vec d1u, d1v; surf->D1( u, v, nPnt[0], d1u, d1v ); gp_Vec Nf = (d1u ^ d1v).Transformed( loc ); if ( theFace.Orientation() == TopAbs_REVERSED ) Nf.Reverse(); return Ne * Nf < 0.; }
void ProfileBased::getUpToFace(TopoDS_Face& upToFace, const TopoDS_Shape& support, const TopoDS_Face& supportface, const TopoDS_Shape& sketchshape, const std::string& method, const gp_Dir& dir, const double offset) { if ((method == "UpToLast") || (method == "UpToFirst")) { // Check for valid support object if (support.IsNull()) throw Base::ValueError("SketchBased: Up to face: No support in Sketch and no base feature!"); std::vector<Part::cutFaces> cfaces = Part::findAllFacesCutBy(support, sketchshape, dir); if (cfaces.empty()) throw Base::ValueError("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); } // Check whether the face has limits or not. Unlimited faces have no wire // Note: Datum planes are always unlimited TopExp_Explorer Ex(upToFace,TopAbs_WIRE); if (Ex.More()) { // Remove the limits of the upToFace so that the extrusion works even if sketchshape is larger // than the upToFace bool remove_limits = false; 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; } } // It must also be checked that all projected inner wires of the upToFace // lie outside the sketch shape. If this is not the case then the sketch // shape is not completely covered by the upToFace. See #0003141 if (!remove_limits) { TopoDS_Wire outerWire = ShapeAnalysis::OuterWire(upToFace); for (Ex.Init(upToFace, TopAbs_WIRE); Ex.More(); Ex.Next()) { if (!outerWire.IsSame(Ex.Current())) { BRepProj_Projection proj(TopoDS::Wire(Ex.Current()), sketchshape, -dir); if (proj.More()) { 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); // use the placement of the adapter, not of the upToFace loc = TopLoc_Location(adapt.Trsf()); BRepBuilderAPI_MakeFace mkFace(adapt.Surface().Surface() #if OCC_VERSION_HEX >= 0x060502 , Precision::Confusion() #endif ); if (!mkFace.IsDone()) throw Base::ValueError("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::ValueError("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::ValueError("SketchBased: Up to face: Must not intersect sketch!"); // Move the face in the extrusion direction // TODO: For non-planar faces, we could consider offsetting the surface if (fabs(offset) > Precision::Confusion()) { if (adapt2.GetType() == GeomAbs_Plane) { gp_Trsf mov; mov.SetTranslation(offset * gp_Vec(dir)); TopLoc_Location loc(mov); upToFace.Move(loc); } else { throw Base::TypeError("SketchBased: Up to Face: Offset not supported yet for non-planar faces"); } } }