App::DocumentObjectExecReturn *Thickness::execute(void) { // Base shape Part::TopoShape TopShape; try { TopShape = getBaseShape(); } catch (Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } TopTools_ListOfShape closingFaces; const std::vector<std::string>& subStrings = Base.getSubValues(); for (std::vector<std::string>::const_iterator it = subStrings.begin(); it != subStrings.end(); ++it) { TopoDS_Face face = TopoDS::Face(TopShape.getSubShape(it->c_str())); closingFaces.Append(face); } bool reversed = Reversed.getValue(); double thickness = (reversed ? -1. : 1. )*Value.getValue(); double tol = Precision::Confusion(); short mode = (short)Mode.getValue(); short join = (short)Join.getValue(); //we do not offer tangent join type if(join == 1) join = 2; if (fabs(thickness) > 2*tol) this->Shape.setValue(getSolid(TopShape.makeThickSolid(closingFaces, thickness, tol, false, false, mode, join))); else this->Shape.setValue(getSolid(TopShape.getShape())); return App::DocumentObject::StdReturn; }
void Pipe::buildPipePath(const Part::TopoShape& shape, const std::vector< std::string >& subedge, TopoDS_Shape& path) { if (!shape.getShape().IsNull()) { try { if (!subedge.empty()) { //if(SpineTangent.getValue()) //getContiniusEdges(shape, subedge); 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.getShape().ShapeType() == TopAbs_EDGE) { path = shape.getShape(); } else if (shape.getShape().ShapeType() == TopAbs_WIRE) { BRepBuilderAPI_MakeWire mkWire(TopoDS::Wire(shape.getShape())); path = mkWire.Wire(); } else if (shape.getShape().ShapeType() == TopAbs_COMPOUND) { TopoDS_Iterator it(shape.getShape()); for (; it.More(); it.Next()) { if (it.Value().IsNull()) throw Base::Exception("In valid element in spine."); if ((it.Value().ShapeType() != TopAbs_EDGE) && (it.Value().ShapeType() != TopAbs_WIRE)) { throw Base::Exception("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.getShape(), 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) throw Base::Exception("Spine is not connected."); path = hWires->Value(1); } else { throw Base::Exception("Spine is neither an edge nor a wire."); } } catch (Standard_Failure) { throw Base::Exception("Invalid spine."); } } }
App::DocumentObjectExecReturn *Body::execute(void) { /* Base::Console().Error("Body '%s':\n", getNameInDocument()); App::DocumentObject* tip = Tip.getValue(); Base::Console().Error(" Tip: %s\n", (tip == NULL) ? "None" : tip->getNameInDocument()); std::vector<App::DocumentObject*> model = Model.getValues(); Base::Console().Error(" Model:\n"); for (std::vector<App::DocumentObject*>::const_iterator m = model.begin(); m != model.end(); m++) { if (*m == NULL) continue; Base::Console().Error(" %s", (*m)->getNameInDocument()); if (Body::isSolidFeature(*m)) { App::DocumentObject* baseFeature = static_cast<PartDesign::Feature*>(*m)->BaseFeature.getValue(); Base::Console().Error(", Base: %s\n", baseFeature == NULL ? "None" : baseFeature->getNameInDocument()); } else { Base::Console().Error("\n"); } } */ App::DocumentObject* tip = Tip.getValue(); Part::TopoShape tipShape; if ( tip ) { if ( !tip->getTypeId().isDerivedFrom ( PartDesign::Feature::getClassTypeId() ) && tip != BaseFeature.getValue () ) { return new App::DocumentObjectExecReturn ( "Linked object is not a PartDesign feature" ); } // get the shape of the tip tipShape = static_cast<Part::Feature *>(tip)->Shape.getShape(); if ( tipShape.getShape().IsNull () ) { return new App::DocumentObjectExecReturn ( "Tip shape is empty" ); } // We should hide here the transformation of the baseFeature tipShape.transformShape (tipShape.getTransform(), true ); } else { tipShape = Part::TopoShape(); } Shape.setValue ( tipShape ); 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); } } }