diff --git a/src/Mod/Part/App/PartFeatures.cpp b/src/Mod/Part/App/PartFeatures.cpp index 57b9d9af0..dc239da90 100644 --- a/src/Mod/Part/App/PartFeatures.cpp +++ b/src/Mod/Part/App/PartFeatures.cpp @@ -24,6 +24,10 @@ #include "PreCompiled.h" #ifndef _PreComp_ # include +# include +# include +# include +# include # include # include # include @@ -32,7 +36,9 @@ # include # include # include +# include # include +# include #endif @@ -43,10 +49,14 @@ using namespace Part; PROPERTY_SOURCE(Part::RuledSurface, Part::Feature) +const char* RuledSurface::OrientationEnums[] = {"Automatic","Forward","Reversed",NULL}; + RuledSurface::RuledSurface() { ADD_PROPERTY_TYPE(Curve1,(0),"Ruled Surface",App::Prop_None,"Curve of ruled surface"); ADD_PROPERTY_TYPE(Curve2,(0),"Ruled Surface",App::Prop_None,"Curve of ruled surface"); + ADD_PROPERTY_TYPE(Orientation,((long)0),"Ruled Surface",App::Prop_None,"Orientation of ruled surface"); + Orientation.setEnums(OrientationEnums); } short RuledSurface::mustExecute() const @@ -55,6 +65,8 @@ short RuledSurface::mustExecute() const return 1; if (Curve2.isTouched()) return 1; + if (Orientation.isTouched()) + return 1; return 0; } @@ -109,6 +121,60 @@ App::DocumentObjectExecReturn *RuledSurface::execute(void) if (curve1.IsNull() || curve2.IsNull()) return new App::DocumentObjectExecReturn("Linked shapes are empty."); + + if (Orientation.getValue() == 0) { + // Automatic + Handle_Adaptor3d_HCurve a1; + Handle_Adaptor3d_HCurve a2; + if (curve1.ShapeType() == TopAbs_EDGE && curve2.ShapeType() == TopAbs_EDGE) { + BRepAdaptor_Curve adapt1(TopoDS::Edge(curve1)); + BRepAdaptor_Curve adapt2(TopoDS::Edge(curve2)); + a1 = new BRepAdaptor_HCurve(adapt1); + a2 = new BRepAdaptor_HCurve(adapt2); + } + else if (curve1.ShapeType() == TopAbs_WIRE && curve2.ShapeType() == TopAbs_WIRE) { + BRepAdaptor_CompCurve adapt1(TopoDS::Wire(curve1)); + BRepAdaptor_CompCurve adapt2(TopoDS::Wire(curve2)); + a1 = new BRepAdaptor_HCompCurve(adapt1); + a2 = new BRepAdaptor_HCompCurve(adapt2); + } + + if (!a1.IsNull() && !a2.IsNull()) { + // get end points of 1st curve + gp_Pnt p1 = a1->Value(a1->FirstParameter()); + gp_Pnt p2 = a1->Value(a1->LastParameter()); + if (curve1.Orientation() == TopAbs_REVERSED) { + std::swap(p1, p2); + } + + // get end points of 2nd curve + gp_Pnt p3 = a2->Value(a2->FirstParameter()); + gp_Pnt p4 = a2->Value(a2->LastParameter()); + if (curve2.Orientation() == TopAbs_REVERSED) { + std::swap(p3, p4); + } + + // Form two triangles (P1,P2,P3) and (P4,P3,P2) and check their normals. + // If the dot product is negative then it's assumed that the resulting face + // is twisted, hence the 2nd edge is reversed. + gp_Vec v1(p1, p2); + gp_Vec v2(p1, p3); + gp_Vec n1 = v1.Crossed(v2); + + gp_Vec v3(p4, p3); + gp_Vec v4(p4, p2); + gp_Vec n2 = v3.Crossed(v4); + + if (n1.Dot(n2) < 0) { + curve2.Reverse(); + } + } + } + else if (Orientation.getValue() == 2) { + // Reverse + curve2.Reverse(); + } + if (curve1.ShapeType() == TopAbs_EDGE && curve2.ShapeType() == TopAbs_EDGE) { TopoDS_Face face = BRepFill::Face(TopoDS::Edge(curve1), TopoDS::Edge(curve2)); this->Shape.setValue(face); diff --git a/src/Mod/Part/App/PartFeatures.h b/src/Mod/Part/App/PartFeatures.h index 0bf9971e1..609ac6f04 100644 --- a/src/Mod/Part/App/PartFeatures.h +++ b/src/Mod/Part/App/PartFeatures.h @@ -38,6 +38,7 @@ class RuledSurface : public Part::Feature public: RuledSurface(); + App::PropertyEnumeration Orientation; App::PropertyLinkSub Curve1; App::PropertyLinkSub Curve2; @@ -53,6 +54,9 @@ public: protected: void onChanged (const App::Property* prop); + +private: + static const char* OrientationEnums[]; }; class Loft : public Part::Feature