/*************************************************************************** * Copyright (c) 2019 WandererFan * * Copyright (c) 2022 Benjamin Bræstrup Sayoc * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ # include #include #include #include #include #include #include "Cosmetic.h" #include "DrawUtil.h" #include "DrawViewPart.h" #include "GeometryObject.h" #include "Preferences.h" using namespace TechDraw; using namespace std; using DU = DrawUtil; TYPESYSTEM_SOURCE(TechDraw::CosmeticEdge, Base::Persistence) //note this ctor has no occEdge or first/last point for geometry! CosmeticEdge::CosmeticEdge() { permaRadius = 0.0; m_geometry = std::make_shared (); initialize(); } CosmeticEdge::CosmeticEdge(const CosmeticEdge* ce) { TechDraw::BaseGeomPtr newGeom = ce->m_geometry->copy(); //these endpoints are already YInverted permaStart = ce->permaStart; permaEnd = ce->permaEnd; permaRadius = ce->permaRadius; m_geometry = newGeom; m_format = ce->m_format; initialize(); } CosmeticEdge::CosmeticEdge(const Base::Vector3d& pt1, const Base::Vector3d& pt2) : CosmeticEdge::CosmeticEdge(TopoDS_EdgeFromVectors(pt1, pt2)) { } CosmeticEdge::CosmeticEdge(const TopoDS_Edge& e) : CosmeticEdge(TechDraw::BaseGeom::baseFactory(e, true)) { } CosmeticEdge::CosmeticEdge(const TechDraw::BaseGeomPtr g) { // Base::Console().message("CE::CE(bg)\n"); m_geometry = g; //we assume input edge is already in Yinverted coordinates permaStart = m_geometry->getStartPoint(); permaEnd = m_geometry->getEndPoint(); if ((g->getGeomType() == GeomType::CIRCLE) || (g->getGeomType() == GeomType::ARCOFCIRCLE)) { TechDraw::CirclePtr circ = std::static_pointer_cast(g); permaStart = circ->center; permaEnd = circ->center; permaRadius = circ->radius; if (g->getGeomType() == GeomType::ARCOFCIRCLE) { TechDraw::AOCPtr aoc = std::static_pointer_cast(circ); aoc->clockwiseAngle(g->clockwiseAngle()); aoc->startPnt = g->getStartPoint(); aoc->startAngle = g->getStartAngle(); aoc->endPnt = g->getEndPoint(); aoc->endAngle = g->getEndAngle(); // aoc->largeArc = g->largeArc; } } initialize(); } CosmeticEdge::~CosmeticEdge() { //shared pointer will delete m_geometry when ref count goes to zero. } void CosmeticEdge::initialize() { m_geometry->setClassOfEdge(EdgeClass::HARD); m_geometry->setHlrVisible( true); m_geometry->setCosmetic(true); m_geometry->source(SourceType::COSMETICEDGE); m_geometry->setCosmeticTag(getTagAsString()); } TopoDS_Edge CosmeticEdge::TopoDS_EdgeFromVectors(const Base::Vector3d& pt1, const Base::Vector3d& pt2) { gp_Pnt gp1(pt1.x, pt1.y, pt1.z); gp_Pnt gp2(pt2.x, pt2.y, pt2.z); return BRepBuilderAPI_MakeEdge(gp1, gp2); } TechDraw::BaseGeomPtr CosmeticEdge::scaledGeometry(const double scale) { TopoDS_Edge e = m_geometry->getOCCEdge(); TopoDS_Shape s = ShapeUtils::scaleShape(e, scale); TopoDS_Edge newEdge = TopoDS::Edge(s); TechDraw::BaseGeomPtr newGeom = TechDraw::BaseGeom::baseFactory(newEdge); newGeom->setClassOfEdge(EdgeClass::HARD); newGeom->setHlrVisible( true); newGeom->setCosmetic(true); newGeom->source(SourceType::COSMETICEDGE); newGeom->setCosmeticTag(getTagAsString()); return newGeom; } TechDraw::BaseGeomPtr CosmeticEdge::scaledAndRotatedGeometry(const double scale, const double rotDegrees) { TopoDS_Edge e = m_geometry->getOCCEdge(); bool saveCW = m_geometry->clockwiseAngle(); // Mirror shape in Y and scale TopoDS_Shape s = ShapeUtils::mirrorShape(e, gp_Pnt(0.0, 0.0, 0.0), scale); // rotate using OXYZ as the coordinate system s = ShapeUtils::rotateShape(s, gp_Ax2(), rotDegrees); s = ShapeUtils::mirrorShape(s); TopoDS_Edge newEdge = TopoDS::Edge(s); TechDraw::BaseGeomPtr newGeom = TechDraw::BaseGeom::baseFactory(newEdge); newGeom->setClassOfEdge(EdgeClass::HARD); newGeom->setHlrVisible( true); newGeom->setCosmetic(true); newGeom->source(SourceType::COSMETICEDGE); newGeom->setCosmeticTag(getTagAsString()); newGeom->clockwiseAngle(saveCW); return newGeom; } //! makes an unscaled, unrotated line from two scaled & rotated end points. //! the result of this method should be used in addCosmeticEdge(). TechDraw::BaseGeomPtr CosmeticEdge::makeCanonicalLine(DrawViewPart* dvp, Base::Vector3d start, Base::Vector3d end) { Base::Vector3d cStart = CosmeticVertex::makeCanonicalPoint(dvp, start); Base::Vector3d cEnd = CosmeticVertex::makeCanonicalPoint(dvp, end); gp_Pnt gStart = Base::convertTo(cStart); gp_Pnt gEnd = Base::convertTo(cEnd); TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(gStart, gEnd); return TechDraw::BaseGeom::baseFactory(edge); } //! makes an unscaled, unrotated line from two canonical points. TechDraw::BaseGeomPtr CosmeticEdge::makeLineFromCanonicalPoints(Base::Vector3d start, Base::Vector3d end) { gp_Pnt gStart = Base::convertTo(start); gp_Pnt gEnd = Base::convertTo(end); TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(gStart, gEnd); return TechDraw::BaseGeom::baseFactory(edge); } std::string CosmeticEdge::toString() const { std::stringstream ss; ss << getTagAsString() << ", $$$, "; if (m_geometry) { ss << m_geometry->getGeomType() << ", $$$, " << m_geometry->toString() << ", $$$, " << m_format.toString(); } return ss.str(); } void CosmeticEdge::dump(const char* title) const { Base::Console().message("CE::dump - %s \n", title); Base::Console().message("CE::dump - %s \n", toString().c_str()); } // Persistence implementers unsigned int CosmeticEdge::getMemSize () const { return 1; } void CosmeticEdge::Save(Base::Writer &writer) const { // TODO: this should be using m_format->Save(writer) instead of saving the individual // fields. writer.Stream() << writer.ind() << "