diff --git a/src/Mod/TechDraw/App/Cosmetic.h b/src/Mod/TechDraw/App/Cosmetic.h index 91cbf02a25..2f1f9f4b7d 100644 --- a/src/Mod/TechDraw/App/Cosmetic.h +++ b/src/Mod/TechDraw/App/Cosmetic.h @@ -120,7 +120,6 @@ protected: //********** CosmeticEdge ****************************************************** -//?? should this inherit BaseGeom or have a BaseGeom member? class TechDrawExport CosmeticEdge : public Base::Persistence, public TechDraw::BaseGeom { TYPESYSTEM_HEADER(); @@ -147,7 +146,7 @@ public: CosmeticEdge* copy(void) const; CosmeticEdge* clone(void) const; - Base::Vector3d permaStart; //persistent unscaled start/end points in View coords? + Base::Vector3d permaStart; //persistent unscaled start/end points in View coords Base::Vector3d permaEnd; double permaRadius; // void unscaleEnds(double scale); diff --git a/src/Mod/TechDraw/App/CosmeticEdgePy.xml b/src/Mod/TechDraw/App/CosmeticEdgePy.xml index 76583a8cd3..ea534e2338 100644 --- a/src/Mod/TechDraw/App/CosmeticEdgePy.xml +++ b/src/Mod/TechDraw/App/CosmeticEdgePy.xml @@ -37,18 +37,32 @@ - - - - - - - - - - - - + + + Gives the position of one end of this CosmeticEdge as vector. + + + + + + Gives the position of one end of this CosmeticEdge as vector. + + + + + + Gives the position of center point of this CosmeticEdge as vector. + + + + + + Gives the radius of CosmeticEdge in mm. + + + + + diff --git a/src/Mod/TechDraw/App/CosmeticEdgePyImp.cpp b/src/Mod/TechDraw/App/CosmeticEdgePyImp.cpp index e0edbd6d90..03c40c4f19 100644 --- a/src/Mod/TechDraw/App/CosmeticEdgePyImp.cpp +++ b/src/Mod/TechDraw/App/CosmeticEdgePyImp.cpp @@ -26,6 +26,11 @@ # include #endif +#include +#include +#include +#include + #include @@ -206,59 +211,135 @@ Py::String CosmeticEdgePy::getTag(void) const // } //} -//Py::Object CosmeticEdgePy::getStart(void) const -//{ -// Base::Vector3d point = getCosmeticEdgePtr()->permaStart; -// point = DrawUtil::invertY(point); -// return Py::asObject(new Base::VectorPy(point)); -//} +Py::Object CosmeticEdgePy::getStart(void) const +{ + Base::Vector3d point = getCosmeticEdgePtr()->permaStart; + return Py::asObject(new Base::VectorPy(point)); +} -//void CosmeticEdgePy::setStart(Py::Object arg) -//{ -// PyObject* p = arg.ptr(); -// if (PyObject_TypeCheck(p, &(Base::VectorPy::Type))) { -// Base::Vector3d point = static_cast(p)->value(); -// getCosmeticEdgePtr()->permaStart = -// DrawUtil::invertY(point); -// } -// else if (PyObject_TypeCheck(p, &PyTuple_Type)) { -// Base::Vector3d point = Base::getVectorFromTuple(p); -// getCosmeticEdgePtr()->permaStart = -// DrawUtil::invertY(point); -// } -// else { -// std::string error = std::string("type must be 'Vector', not "); -// error += p->ob_type->tp_name; -// throw Py::TypeError(error); -// } -//} +void CosmeticEdgePy::setStart(Py::Object arg) +{ + PyObject* p = arg.ptr(); + Base::Vector3d pNew; + if (PyObject_TypeCheck(p, &(Base::VectorPy::Type))) { + pNew = static_cast(p)->value(); + } + else if (PyObject_TypeCheck(p, &PyTuple_Type)) { + pNew = Base::getVectorFromTuple(p); + } + else { + std::string error = std::string("type must be 'Vector', not "); + error += p->ob_type->tp_name; + throw Py::TypeError(error); + } -//Py::Object CosmeticEdgePy::getEnd(void) const -//{ -// Base::Vector3d point = getCosmeticEdgePtr()->permaEnd; -// point = DrawUtil::invertY(point); -// return Py::asObject(new Base::VectorPy(point)); -//} + pNew = DrawUtil::invertY(pNew); + Base::Vector3d pEnd = getCosmeticEdgePtr()->permaEnd; + pEnd = DrawUtil::invertY(pEnd); + gp_Pnt gp1(pNew.x,pNew.y,pNew.z); + gp_Pnt gp2(pEnd.x,pEnd.y,pEnd.z); + TopoDS_Edge e = BRepBuilderAPI_MakeEdge(gp1, gp2); + auto oldGeom = getCosmeticEdgePtr()->m_geometry; + getCosmeticEdgePtr()->m_geometry = TechDraw::BaseGeom::baseFactory(e); + getCosmeticEdgePtr()->permaStart = pNew; + delete oldGeom; +} -//void CosmeticEdgePy::setEnd(Py::Object arg) -//{ -// PyObject* p = arg.ptr(); -// if (PyObject_TypeCheck(p, &(Base::VectorPy::Type))) { -// Base::Vector3d point = static_cast(p)->value(); -// getCosmeticEdgePtr()->permaEnd = -// DrawUtil::invertY(point); -// } -// else if (PyObject_TypeCheck(p, &PyTuple_Type)) { -// Base::Vector3d point = Base::getVectorFromTuple(p); -// getCosmeticEdgePtr()->permaEnd = -// DrawUtil::invertY(point); -// } -// else { -// std::string error = std::string("type must be 'Vector', not "); -// error += p->ob_type->tp_name; -// throw Py::TypeError(error); -// } -//} +Py::Object CosmeticEdgePy::getEnd(void) const +{ + Base::Vector3d point = getCosmeticEdgePtr()->permaEnd; + return Py::asObject(new Base::VectorPy(point)); +} + +void CosmeticEdgePy::setEnd(Py::Object arg) +{ + PyObject* p = arg.ptr(); + Base::Vector3d pNew; + if (PyObject_TypeCheck(p, &(Base::VectorPy::Type))) { + pNew = static_cast(p)->value(); + } + else if (PyObject_TypeCheck(p, &PyTuple_Type)) { + pNew = Base::getVectorFromTuple(p); + } + else { + std::string error = std::string("type must be 'Vector', not "); + error += p->ob_type->tp_name; + throw Py::TypeError(error); + } + + pNew = DrawUtil::invertY(pNew); + Base::Vector3d pStart = getCosmeticEdgePtr()->permaStart; + pStart = DrawUtil::invertY(pStart); + gp_Pnt gp1(pNew.x,pNew.y,pNew.z); + gp_Pnt gp2(pStart.x,pStart.y,pStart.z); + TopoDS_Edge e = BRepBuilderAPI_MakeEdge(gp2, gp1); + auto oldGeom = getCosmeticEdgePtr()->m_geometry; + getCosmeticEdgePtr()->m_geometry = TechDraw::BaseGeom::baseFactory(e); + getCosmeticEdgePtr()->permaEnd = pNew; + delete oldGeom; +} + +Py::Object CosmeticEdgePy::getRadius(void) const +{ + double r = getCosmeticEdgePtr()->permaRadius; + return Py::asObject(PyFloat_FromDouble(r)); +} + +void CosmeticEdgePy::setRadius(Py::Object arg) +{ + //TODO: check if the edge has a radius attrib + PyObject* p = arg.ptr(); + double r; + if (PyObject_TypeCheck(p, &PyFloat_Type)) { + r = PyFloat_AsDouble(p); + } + else if (PyObject_TypeCheck(p, &PyLong_Type)) { + r = (double) PyLong_AsLong(p); + } + else { + std::string error = std::string("type must be 'Float' or 'Int', not "); + error += p->ob_type->tp_name; + throw Py::TypeError(error); + } + + getCosmeticEdgePtr()->permaRadius = r; + auto oldGeom = getCosmeticEdgePtr()->m_geometry; + getCosmeticEdgePtr()->m_geometry = new TechDraw::Circle(getCosmeticEdgePtr()->permaStart, r); + delete oldGeom; +} + +Py::Object CosmeticEdgePy::getCenter(void) const +{ + Base::Vector3d point = getCosmeticEdgePtr()->permaStart; + return Py::asObject(new Base::VectorPy(point)); +} + +void CosmeticEdgePy::setCenter(Py::Object arg) +{ + PyObject* p = arg.ptr(); + Base::Vector3d pNew; + if (PyObject_TypeCheck(p, &(Base::VectorPy::Type))) { + pNew = static_cast(p)->value(); + } + else if (PyObject_TypeCheck(p, &PyTuple_Type)) { + pNew = Base::getVectorFromTuple(p); + } + else { + std::string error = std::string("type must be 'Vector', not "); + error += p->ob_type->tp_name; + throw Py::TypeError(error); + } + + pNew = DrawUtil::invertY(pNew); + auto oldGeom = getCosmeticEdgePtr()->m_geometry; + TechDraw::Circle* oldCircle = dynamic_cast(oldGeom); + + getCosmeticEdgePtr()->permaStart = pNew; + getCosmeticEdgePtr()->permaEnd = pNew; + getCosmeticEdgePtr()->permaRadius = oldCircle->radius; + getCosmeticEdgePtr()->m_geometry = new TechDraw::Circle(getCosmeticEdgePtr()->permaStart, oldCircle->radius); + delete oldGeom; +} PyObject *CosmeticEdgePy::getCustomAttributes(const char* /*attr*/) const { diff --git a/src/Mod/TechDraw/App/DrawViewPartPyImp.cpp b/src/Mod/TechDraw/App/DrawViewPartPyImp.cpp index 548ffd894a..04bd0603c7 100644 --- a/src/Mod/TechDraw/App/DrawViewPartPyImp.cpp +++ b/src/Mod/TechDraw/App/DrawViewPartPyImp.cpp @@ -348,8 +348,8 @@ PyObject* DrawViewPartPy::makeCosmeticCircle(PyObject *args) { PyObject* pPnt1 = nullptr; double radius = 5.0; - double angle1 = 0.0; - double angle2 = 360.0; +// double angle1 = 0.0; +// double angle2 = 360.0; int style = LineFormat::getDefEdgeStyle(); double weight = LineFormat::getDefEdgeWidth(); App::Color defCol = LineFormat::getDefEdgeColor(); @@ -364,22 +364,13 @@ PyObject* DrawViewPartPy::makeCosmeticCircle(PyObject *args) DrawViewPart* dvp = getDrawViewPartPtr(); Base::Vector3d pnt1 = DrawUtil::invertY(static_cast(pPnt1)->value()); - gp_Pnt loc(pnt1.x, pnt1.y, pnt1.z); - gp_Dir dir(0,0,1); - gp_Ax1 axis(loc, dir); - gp_Circ circle; - circle.SetAxis(axis); - circle.SetRadius(radius); - - Handle(Geom_Circle) hCircle = new Geom_Circle (circle); - BRepBuilderAPI_MakeEdge aMakeEdge(hCircle, angle1*(M_PI/180), angle2*(M_PI/180)); - TopoDS_Edge edge = aMakeEdge.Edge(); - TechDraw::BaseGeom* bg = TechDraw::BaseGeom::baseFactory(edge); + TechDraw::BaseGeom* bg = new TechDraw::Circle(pnt1, radius); std::string newTag = dvp->addCosmeticEdge(bg); TechDraw::CosmeticEdge* ce = dvp->getCosmeticEdge(newTag); if (ce != nullptr) { ce->permaStart = pnt1; ce->permaEnd = pnt1; + ce->permaRadius = radius; ce->m_format.m_style = style; ce->m_format.m_weight = weight; if (pColor == nullptr) { @@ -418,25 +409,13 @@ PyObject* DrawViewPartPy::makeCosmeticCircleArc(PyObject *args) //from here on is almost duplicate of makeCosmeticCircle DrawViewPart* dvp = getDrawViewPartPtr(); Base::Vector3d pnt1 = DrawUtil::invertY(static_cast(pPnt1)->value()); - gp_Pnt loc(pnt1.x, pnt1.y, pnt1.z); - gp_Dir dir(0,0,1); - gp_Ax1 axis(loc, dir); - gp_Circ circle; - circle.SetAxis(axis); - circle.SetRadius(radius); //full circle @ right loc - Handle(Geom_Circle) hCircle = new Geom_Circle (circle); - BRepBuilderAPI_MakeEdge aMakeEdge(hCircle, -angle2*(M_PI/180), -angle1*(M_PI/180)); //hack! - // right result, but ugly: - // Qt angles are cw, OCC angles are CCW - // Qt -y is up, OCC -y is down - - TopoDS_Edge edge = aMakeEdge.Edge(); - TechDraw::BaseGeom* bg = TechDraw::BaseGeom::baseFactory(edge); + TechDraw::BaseGeom* bg = new TechDraw::AOC(pnt1, radius, angle1, angle2); std::string newTag = dvp->addCosmeticEdge(bg); TechDraw::CosmeticEdge* ce = dvp->getCosmeticEdge(newTag); if (ce != nullptr) { ce->permaStart = pnt1; ce->permaEnd = pnt1; + ce->permaRadius = radius; ce->m_format.m_style = style; ce->m_format.m_weight = weight; if (pColor == nullptr) { diff --git a/src/Mod/TechDraw/App/Geometry.cpp b/src/Mod/TechDraw/App/Geometry.cpp index 5b6e1a9413..a242ee9298 100644 --- a/src/Mod/TechDraw/App/Geometry.cpp +++ b/src/Mod/TechDraw/App/Geometry.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -584,6 +585,25 @@ Ellipse::Ellipse(const TopoDS_Edge &e) angle = xaxis.AngleWithRef(gp_Dir(1, 0, 0), gp_Dir(0, 0, -1)); } +Ellipse::Ellipse(Base::Vector3d c, double mnr, double mjr) +{ + geomType = ELLIPSE; + center = c; + major = mjr; + minor = mnr; + angle = 0; + + GC_MakeEllipse me(gp_Ax2(gp_Pnt(c.x,c.y,c.z), gp_Dir(0.0,0.0,1.0)), + major, minor); + if (!me.IsDone()) { + Base::Console().Message("G:Ellipse - failed to make Ellipse\n"); + } + const Handle(Geom_Ellipse) gEllipse = me.Value(); + BRepBuilderAPI_MakeEdge mkEdge(gEllipse, 0.0, 2 * M_PI); + if (mkEdge.IsDone()) { + occEdge = mkEdge.Edge(); + } +} AOE::AOE(const TopoDS_Edge &e) : Ellipse(e) { @@ -629,6 +649,27 @@ Circle::Circle(void) center = Base::Vector3d(0.0, 0.0, 0.0); } +Circle::Circle(Base::Vector3d c, double r) +{ + geomType = CIRCLE; + radius = r; + center = c; + gp_Pnt loc(c.x, c.y, c.z); + gp_Dir dir(0,0,1); + gp_Ax1 axis(loc, dir); + gp_Circ circle; + circle.SetAxis(axis); + circle.SetRadius(r); + double angle1 = 0.0; + double angle2 = 360.0; + + Handle(Geom_Circle) hCircle = new Geom_Circle (circle); + BRepBuilderAPI_MakeEdge aMakeEdge(hCircle, angle1*(M_PI/180), angle2*(M_PI/180)); + TopoDS_Edge edge = aMakeEdge.Edge(); + occEdge = edge; +} + + Circle::Circle(const TopoDS_Edge &e) { geomType = CIRCLE; //center, radius @@ -706,6 +747,50 @@ AOC::AOC(const TopoDS_Edge &e) : Circle(e) } } +AOC::AOC(Base::Vector3d c, double r, double sAng, double eAng) : Circle() +{ + geomType = ARCOFCIRCLE; + + radius = r; + center = c; + gp_Pnt loc(c.x, c.y, c.z); + gp_Dir dir(0,0,1); + gp_Ax1 axis(loc, dir); + gp_Circ circle; + circle.SetAxis(axis); + circle.SetRadius(r); + + Handle(Geom_Circle) hCircle = new Geom_Circle (circle); + BRepBuilderAPI_MakeEdge aMakeEdge(hCircle, sAng*(M_PI/180), eAng*(M_PI/180)); + TopoDS_Edge edge = aMakeEdge.Edge(); + occEdge = edge; + + BRepAdaptor_Curve adp(edge); + + double f = adp.FirstParameter(); + double l = adp.LastParameter(); + gp_Pnt s = adp.Value(f); + gp_Pnt m = adp.Value((l+f)/2.0); + gp_Pnt ePt = adp.Value(l); //if start == end, it isn't an arc! + gp_Vec v1(m,s); //vector mid to start + gp_Vec v2(m,ePt); //vector mid to end + gp_Vec v3(0,0,1); //stdZ + double a = v3.DotCross(v1,v2); //error if v1 = v2? + + startAngle = fmod(f,2.0*M_PI); + endAngle = fmod(l,2.0*M_PI); + cw = (a < 0) ? true: false; + largeArc = (fabs(l-f) > M_PI) ? true : false; + + startPnt = Base::Vector3d(s.X(), s.Y(), s.Z()); + endPnt = Base::Vector3d(ePt.X(), ePt.Y(), s.Z()); + midPnt = Base::Vector3d(m.X(), m.Y(), s.Z()); + if (edge.Orientation() == TopAbs_REVERSED) { + reversed = true; + } +} + + AOC::AOC(void) : Circle() { geomType = ARCOFCIRCLE; diff --git a/src/Mod/TechDraw/App/Geometry.h b/src/Mod/TechDraw/App/Geometry.h index d1f587e579..29db108b31 100644 --- a/src/Mod/TechDraw/App/Geometry.h +++ b/src/Mod/TechDraw/App/Geometry.h @@ -133,8 +133,9 @@ typedef std::vector BaseGeomPtrVector; //obs? class TechDrawExport Circle: public BaseGeom { public: - Circle(const TopoDS_Edge &e); Circle(void); + Circle(const TopoDS_Edge &e); + Circle(Base::Vector3d center, double radius); ~Circle() = default; public: @@ -150,7 +151,8 @@ class TechDrawExport Circle: public BaseGeom class TechDrawExport Ellipse: public BaseGeom { public: - Ellipse(const TopoDS_Edge &e); + Ellipse(const TopoDS_Edge &e); + Ellipse(Base::Vector3d c, double mnr, double mjr); ~Ellipse() = default; public: @@ -188,6 +190,7 @@ class TechDrawExport AOC: public Circle { public: AOC(const TopoDS_Edge &e); + AOC(Base::Vector3d c, double r, double s, double e); AOC(void); ~AOC() = default;