[TD]Cosmetic function overhaul (#14216)

* [TD]Cosmetic geometry and tools update

- all cosmetics to store geometry in same form
- all cosmetics to survive scaling and rotation
- extension functions to survive scaling and rotation

* [TD]overhaul leader point storage and editing

- add py routine makeLeader(points)

* [TD]add leader conversion utility

* [TD]Set Leader RotateWithView default to true

* [TD]fix intersection vertex position

* [TD]add CosmeticEdge::makeLineFromCanonicalPoints

* [TD]fix 2 Extension tools

- positioning in DrawCosmeticCircle
- mishandling of points in execLineParallelPerpendicular

* [TD]Remove duplicate constexpr

* [TD]fix 2x Cosmetic arc tools

* [TD]refactor LineFormat out of Cosmetic

* [TD]move cosmetic appearance settings to LineFormat

* [TD]remove 2 unused methods

* [TD]apply format to blue line & circle tools

* [TD]fix ballon arrowhead does not rotate with view

* [TD]fix CosmeticCircle3Points

* [TD]allow multiple cosmetic object deletions

* [TD]fix extend/shorten centerline
This commit is contained in:
WandererFan
2024-05-23 09:41:42 -04:00
committed by GitHub
parent a8d093280e
commit 50f970efd7
56 changed files with 1812 additions and 1076 deletions

View File

@@ -149,5 +149,7 @@ PyMOD_INIT_FUNC(TechDraw)
TechDraw::DrawWeldSymbolPython::init();
TechDraw::DrawBrokenViewPython::init();
TechDraw::LineFormat::initCurrentLineFormat();
PyMOD_Return(mod);
}

View File

@@ -72,7 +72,7 @@
#include "ProjectionAlgos.h"
#include "TechDrawExport.h"
#include "CosmeticVertexPy.h"
#include "DrawLeaderLinePy.h"
namespace TechDraw {
//module level static C++ functions go here
@@ -191,6 +191,9 @@ public:
add_varargs_method("makeCanonicalPoint", &Module::makeCanonicalPoint,
"makeCanonicalPoint(DrawViewPart, Vector3d) - Returns the unscaled, unrotated version of the input point)"
);
add_varargs_method("makeLeader", &Module::makeLeader,
"makeLeader(parent - DrawViewPart, points - [Vector], startSymbol - int, endSymbol - int) - Creates a leader line attached to parent. Points are in page coordinates with (0, 0) at lowerleft.s"
);
initialize("This is a module for making drawings"); // register with Python
}
~Module() override {}
@@ -1286,6 +1289,42 @@ private:
cPoint = CosmeticVertex::makeCanonicalPoint(dvp, cPoint, unscale);
return Py::asObject(new Base::VectorPy(cPoint));
}
Py::Object makeLeader(const Py::Tuple& args)
{
PyObject* pDvp(nullptr);
PyObject* pPointList(nullptr);
int iStartSymbol = 0;
int iEndSymbol = 0;
TechDraw::DrawViewPart* dvp = nullptr;
if (!PyArg_ParseTuple(args.ptr(), "OO!|ii", &pDvp, &(PyList_Type), &pPointList, &iStartSymbol, &iEndSymbol)) {
throw Py::TypeError("expected (DrawViewPart, listofpoints, startsymbolindex, endsymbolindex");
}
if (PyObject_TypeCheck(pDvp, &(TechDraw::DrawViewPartPy::Type))) {
App::DocumentObject* obj = static_cast<App::DocumentObjectPy*>(pDvp)->getDocumentObjectPtr();
dvp = static_cast<TechDraw::DrawViewPart*>(obj);
}
std::vector<Base::Vector3d> pointList;
try {
Py::Sequence list(pPointList);
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
if (PyObject_TypeCheck((*it).ptr(), &(Base::VectorPy::Type))) {
Base::Vector3d temp = static_cast<Base::VectorPy*>((*it).ptr())->value();
pointList.push_back(temp);
}
}
}
catch (Standard_Failure& e) {
throw Py::Exception(Part::PartExceptionOCCError, e.GetMessageString());
}
auto newLeader = DrawLeaderLine::makeLeader(dvp, pointList, iStartSymbol, iEndSymbol);
// return the new leader as DrawLeaderPy
return Py::asObject(new DrawLeaderLinePy(newLeader));
}
};
PyObject* initModule()

View File

@@ -174,6 +174,8 @@ SET(TechDraw_SRCS
XMLQuery.h
LineGenerator.cpp
LineGenerator.h
LineFormat.cpp
LineFormat.h
)
SET(Geometry_SRCS

View File

@@ -885,10 +885,10 @@ void CenterLine::Save(Base::Writer &writer) const
// style is deprecated in favour of line number, but we still save and restore it
// to avoid problems with old documents.
writer.Stream() << writer.ind() << "<Style value=\"" << m_format.m_style << "\"/>" << std::endl;
writer.Stream() << writer.ind() << "<Weight value=\"" << m_format.m_weight << "\"/>" << std::endl;
writer.Stream() << writer.ind() << "<Color value=\"" << m_format.m_color.asHexString() << "\"/>" << std::endl;
const char v = m_format.m_visible?'1':'0';
writer.Stream() << writer.ind() << "<Style value=\"" << m_format.getStyle() << "\"/>" << std::endl;
writer.Stream() << writer.ind() << "<Weight value=\"" << m_format.getWidth() << "\"/>" << std::endl;
writer.Stream() << writer.ind() << "<Color value=\"" << m_format.getColor().asHexString() << "\"/>" << std::endl;
const char v = m_format.getVisible() ? '1' : '0';
writer.Stream() << writer.ind() << "<Visible value=\"" << v << "\"/>" << std::endl;
//stored geometry
@@ -984,14 +984,16 @@ void CenterLine::Restore(Base::XMLReader &reader)
// style is deprecated in favour of line number, but we still save and restore it
// to avoid problems with old documents.
reader.readElement("Style");
m_format.m_style = reader.getAttributeAsInteger("value");
m_format.setStyle(reader.getAttributeAsInteger("value"));
reader.readElement("Weight");
m_format.m_weight = reader.getAttributeAsFloat("value");
m_format.setWidth(reader.getAttributeAsFloat("value"));
reader.readElement("Color");
std::string temp = reader.getAttribute("value");
m_format.m_color.fromHexString(temp);
std::string tempHex = reader.getAttribute("value");
App::Color tempColor;
tempColor.fromHexString(tempHex);
m_format.setColor(tempColor);
reader.readElement("Visible");
m_format.m_visible = (int)reader.getAttributeAsInteger("value")==0?false:true;
m_format.setVisible( (int)reader.getAttributeAsInteger("value")==0 ? false : true);
//stored geometry
reader.readElement("GeometryType");

View File

@@ -115,10 +115,10 @@ Py::Dict CenterLinePy::getFormat() const
TechDraw::LineFormat* format= &(this->getCenterLinePtr()->m_format);
Py::Dict dict;
dict.setItem("style", Py::Long(format->m_style));
dict.setItem("weight", Py::Float(format->m_weight));
dict.setItem("color", Py::Tuple(DrawUtil::colorToPyTuple(format->m_color), true));
dict.setItem("visible", Py::Boolean(format->m_visible));
dict.setItem("style", Py::Long(format->getStyle()));
dict.setItem("weight", Py::Float(format->getWidth()));
dict.setItem("color", Py::Tuple(DrawUtil::colorToPyTuple(format->getColor()), true));
dict.setItem("visible", Py::Boolean(format->getVisible()));
return dict;
}
@@ -138,10 +138,10 @@ void CenterLinePy::setFormat(Py::Dict arg)
}
TechDraw::LineFormat* format = &(this->getCenterLinePtr()->m_format);
format->m_style = style;
format->m_weight = weight;
format->m_color = DrawUtil::pyTupleToColor(pColor);
format->m_visible = Base::asBoolean(visible);
format->setStyle(style);
format->setWidth(weight);
format->setColor(DrawUtil::pyTupleToColor(pColor));
format->setVisible(Base::asBoolean(visible));
}
Py::String CenterLinePy::getTag() const

View File

@@ -37,11 +37,8 @@
#include "DrawUtil.h"
#include "DrawViewPart.h"
#include "GeometryObject.h"
#include "LineGroup.h"
#include "LineGenerator.h"
#include "Preferences.h"
using namespace TechDraw;
using namespace std;
using DU = DrawUtil;
@@ -50,67 +47,11 @@ using DU = DrawUtil;
#define COSMETICEDGE 1
#define CENTERLINE 2
LineFormat::LineFormat()
{
m_style = getDefEdgeStyle();
m_weight = getDefEdgeWidth();
m_color= getDefEdgeColor();
m_visible = true;
m_lineNumber = LineGenerator::fromQtStyle((Qt::PenStyle)m_style);
}
LineFormat::LineFormat(const int style,
const double weight,
const App::Color& color,
const bool visible) :
m_style(style),
m_weight(weight),
m_color(color),
m_visible(visible),
m_lineNumber(LineGenerator::fromQtStyle((Qt::PenStyle)m_style))
{
}
void LineFormat::dump(const char* title)
{
Base::Console().Message("LF::dump - %s \n", title);
Base::Console().Message("LF::dump - %s \n", toString().c_str());
}
std::string LineFormat::toString() const
{
std::stringstream ss;
ss << m_style << ", " <<
m_weight << ", " <<
m_color.asHexString() << ", " <<
m_visible;
return ss.str();
}
//static preference getters.
double LineFormat::getDefEdgeWidth()
{
return TechDraw::LineGroup::getDefaultWidth("Graphic");
}
App::Color LineFormat::getDefEdgeColor()
{
return Preferences::normalColor();
}
int LineFormat::getDefEdgeStyle()
{
return Preferences::getPreferenceGroup("Decorations")->GetInt("CenterLineStyle", 2); //dashed
}
//******************************************
TYPESYSTEM_SOURCE(TechDraw::CosmeticEdge, Base::Persistence)
//note this ctor has no occEdge or first/last point for geometry!
CosmeticEdge::CosmeticEdge()
{
// Base::Console().Message("CE::CE()\n");
permaRadius = 0.0;
m_geometry = std::make_shared<TechDraw::BaseGeom> ();
initialize();
@@ -118,7 +59,6 @@ CosmeticEdge::CosmeticEdge()
CosmeticEdge::CosmeticEdge(const CosmeticEdge* ce)
{
// Base::Console().Message("CE::CE(ce)\n");
TechDraw::BaseGeomPtr newGeom = ce->m_geometry->copy();
//these endpoints are already YInverted
permaStart = ce->permaStart;
@@ -130,13 +70,12 @@ CosmeticEdge::CosmeticEdge(const CosmeticEdge* ce)
}
CosmeticEdge::CosmeticEdge(const Base::Vector3d& pt1, const Base::Vector3d& pt2) :
// 🠓 returns TopoDS_Edge
CosmeticEdge::CosmeticEdge(TopoDS_EdgeFromVectors(pt1, pt2))
CosmeticEdge::CosmeticEdge(TopoDS_EdgeFromVectors(pt1, pt2))
{
}
// 🠓 returns TechDraw::BaseGeomPtr
CosmeticEdge::CosmeticEdge(const TopoDS_Edge& e) : CosmeticEdge(TechDraw::BaseGeom::baseFactory(e))
CosmeticEdge::CosmeticEdge(const TopoDS_Edge& e) :
CosmeticEdge(TechDraw::BaseGeom::baseFactory(e))
{
}
@@ -153,6 +92,15 @@ CosmeticEdge::CosmeticEdge(const TechDraw::BaseGeomPtr g)
permaStart = circ->center;
permaEnd = circ->center;
permaRadius = circ->radius;
if (g->getGeomType() == TechDraw::GeomType::ARCOFCIRCLE) {
TechDraw::AOCPtr aoc = std::static_pointer_cast<TechDraw::AOC>(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();
}
@@ -173,15 +121,10 @@ void CosmeticEdge::initialize()
m_geometry->setCosmeticTag(getTagAsString());
}
// TODO: not sure that this method should be doing the inversion. CV for example
// accepts input point as is. The caller should have figured out the correct points.
TopoDS_Edge CosmeticEdge::TopoDS_EdgeFromVectors(const Base::Vector3d& pt1, const Base::Vector3d& pt2)
{
// Base::Console().Message("CE::CE(p1, p2)\n");
Base::Vector3d p1 = DrawUtil::invertY(pt1);
Base::Vector3d p2 = DrawUtil::invertY(pt2);
gp_Pnt gp1(p1.x, p1.y, p1.z);
gp_Pnt gp2(p2.x, p2.y, p2.z);
gp_Pnt gp1(pt1.x, pt1.y, pt1.z);
gp_Pnt gp2(pt2.x, pt2.y, pt2.z);
return BRepBuilderAPI_MakeEdge(gp1, gp2);
}
@@ -202,7 +145,7 @@ TechDraw::BaseGeomPtr CosmeticEdge::scaledGeometry(const double scale)
TechDraw::BaseGeomPtr CosmeticEdge::scaledAndRotatedGeometry(const double scale, const double rotDegrees)
{
TopoDS_Edge e = m_geometry->getOCCEdge();
// TopoDS_Shape s = TechDraw::scaleShape(e, scale);
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
@@ -215,11 +158,11 @@ TechDraw::BaseGeomPtr CosmeticEdge::scaledAndRotatedGeometry(const double scale,
newGeom->setCosmetic(true);
newGeom->source(COSMETICEDGE);
newGeom->setCosmeticTag(getTagAsString());
newGeom->clockwiseAngle(saveCW);
return newGeom;
}
//! makes an unscaled, unrotated line from two scaled & rotated end points. If points is Gui space coordinates,
//! they should be inverted (DU::invertY) before calling this method.
//! 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)
{
@@ -228,7 +171,16 @@ TechDraw::BaseGeomPtr CosmeticEdge::makeCanonicalLine(DrawViewPart* dvp, Base::V
gp_Pnt gStart = DU::togp_Pnt(cStart);
gp_Pnt gEnd = DU::togp_Pnt(cEnd);
TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(gStart, gEnd);
return TechDraw::BaseGeom::baseFactory(edge)->inverted();
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 = DU::togp_Pnt(start);
gp_Pnt gEnd = DU::togp_Pnt(end);
TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(gStart, gEnd);
return TechDraw::BaseGeom::baseFactory(edge);
}
std::string CosmeticEdge::toString() const
@@ -261,10 +213,10 @@ 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() << "<Style value=\"" << m_format.m_style << "\"/>" << endl;
writer.Stream() << writer.ind() << "<Weight value=\"" << m_format.m_weight << "\"/>" << endl;
writer.Stream() << writer.ind() << "<Color value=\"" << m_format.m_color.asHexString() << "\"/>" << endl;
const char v = m_format.m_visible?'1':'0';
writer.Stream() << writer.ind() << "<Style value=\"" << m_format.getStyle() << "\"/>" << endl;
writer.Stream() << writer.ind() << "<Weight value=\"" << m_format.getWidth() << "\"/>" << endl;
writer.Stream() << writer.ind() << "<Color value=\"" << m_format.getColor().asHexString() << "\"/>" << endl;
const char v = m_format.getVisible() ? '1' : '0';
writer.Stream() << writer.ind() << "<Visible value=\"" << v << "\"/>" << endl;
writer.Stream() << writer.ind() << "<GeometryType value=\"" << m_geometry->getGeomType() <<"\"/>" << endl;
@@ -292,14 +244,16 @@ void CosmeticEdge::Restore(Base::XMLReader &reader)
}
// Base::Console().Message("CE::Restore - reading elements\n");
reader.readElement("Style");
m_format.m_style = reader.getAttributeAsInteger("value");
m_format.setStyle(reader.getAttributeAsInteger("value"));
reader.readElement("Weight");
m_format.m_weight = reader.getAttributeAsFloat("value");
m_format.setWidth(reader.getAttributeAsFloat("value"));
reader.readElement("Color");
std::string temp = reader.getAttribute("value");
m_format.m_color.fromHexString(temp);
std::string tempHex = reader.getAttribute("value");
App::Color tempColor;
tempColor.fromHexString(tempHex);
m_format.setColor(tempColor);
reader.readElement("Visible");
m_format.m_visible = reader.getAttributeAsInteger("value") != 0;
m_format.setVisible(reader.getAttributeAsInteger("value") != 0);
reader.readElement("GeometryType");
TechDraw::GeomType gType = static_cast<TechDraw::GeomType>(reader.getAttributeAsInteger("value"));
@@ -378,20 +332,12 @@ void CosmeticEdge::assignTag(const TechDraw::CosmeticEdge* ce)
throw Base::TypeError("CosmeticEdge tag can not be assigned as types do not match.");
}
CosmeticEdge* CosmeticEdge::copy() const
{
// Base::Console().Message("CE::copy()\n");
CosmeticEdge* newCE = new CosmeticEdge();
TechDraw::BaseGeomPtr newGeom = m_geometry->copy();
newCE->m_geometry = newGeom;
newCE->m_format = m_format;
return newCE;
}
CosmeticEdge* CosmeticEdge::clone() const
{
// Base::Console().Message("CE::clone()\n");
CosmeticEdge* cpy = this->copy();
Base::Console().Message("CE::clone()\n");
CosmeticEdge* cpy = new CosmeticEdge();
cpy->m_geometry = m_geometry->copy();
cpy->m_format = m_format;
cpy->tag = this->tag;
return cpy;
}
@@ -412,10 +358,10 @@ TYPESYSTEM_SOURCE(TechDraw::GeomFormat, Base::Persistence)
GeomFormat::GeomFormat() :
m_geomIndex(-1)
{
m_format.m_style = LineFormat::getDefEdgeStyle();
m_format.m_weight = LineFormat::getDefEdgeWidth();
m_format.m_color = LineFormat::getDefEdgeColor();
m_format.m_visible = true;
m_format.setStyle(LineFormat::getDefEdgeStyle());
m_format.setWidth(LineFormat::getDefEdgeWidth());
m_format.setColor(LineFormat::getDefEdgeColor());
m_format.setVisible(true);
m_format.setLineNumber(LineFormat::InvalidLine);
createNewTag();
@@ -424,10 +370,10 @@ GeomFormat::GeomFormat() :
GeomFormat::GeomFormat(const GeomFormat* gf)
{
m_geomIndex = gf->m_geomIndex;
m_format.m_style = gf->m_format.m_style;
m_format.m_weight = gf->m_format.m_weight;
m_format.m_color = gf->m_format.m_color;
m_format.m_visible = gf->m_format.m_visible;
m_format.setStyle(gf->m_format.getStyle());
m_format.setWidth(gf->m_format.getWidth());
m_format.setColor(gf->m_format.getColor());
m_format.setVisible(gf->m_format.getVisible());
m_format.setLineNumber(gf->m_format.getLineNumber());
createNewTag();
@@ -437,10 +383,10 @@ GeomFormat::GeomFormat(const int idx,
const TechDraw::LineFormat& fmt) :
m_geomIndex(idx)
{
m_format.m_style = fmt.m_style;
m_format.m_weight = fmt.m_weight;
m_format.m_color = fmt.m_color;
m_format.m_visible = fmt.m_visible;
m_format.setStyle(fmt.getStyle());
m_format.setWidth(fmt.getWidth());
m_format.setColor(fmt.getColor());
m_format.setVisible(fmt.getVisible());
m_format.setLineNumber(fmt.getLineNumber());
createNewTag();
@@ -472,13 +418,13 @@ unsigned int GeomFormat::getMemSize () const
void GeomFormat::Save(Base::Writer &writer) const
{
const char v = m_format.m_visible?'1':'0';
const char v = m_format.getVisible() ? '1' : '0';
writer.Stream() << writer.ind() << "<GeomIndex value=\"" << m_geomIndex << "\"/>" << endl;
// style is deprecated in favour of line number, but we still save and restore it
// to avoid problems with old documents.
writer.Stream() << writer.ind() << "<Style value=\"" << m_format.m_style << "\"/>" << endl;
writer.Stream() << writer.ind() << "<Weight value=\"" << m_format.m_weight << "\"/>" << endl;
writer.Stream() << writer.ind() << "<Color value=\"" << m_format.m_color.asHexString() << "\"/>" << endl;
writer.Stream() << writer.ind() << "<Style value=\"" << m_format.getStyle() << "\"/>" << endl;
writer.Stream() << writer.ind() << "<Weight value=\"" << m_format.getWidth() << "\"/>" << endl;
writer.Stream() << writer.ind() << "<Color value=\"" << m_format.getColor().asHexString() << "\"/>" << endl;
writer.Stream() << writer.ind() << "<Visible value=\"" << v << "\"/>" << endl;
writer.Stream() << writer.ind() << "<LineNumber value=\"" << m_format.getLineNumber() << "\"/>" << endl;
}
@@ -496,14 +442,16 @@ void GeomFormat::Restore(Base::XMLReader &reader)
// style is deprecated in favour of line number, but we still save and restore it
// to avoid problems with old documents.
reader.readElement("Style");
m_format.m_style = reader.getAttributeAsInteger("value");
m_format.setStyle(reader.getAttributeAsInteger("value"));
reader.readElement("Weight");
m_format.m_weight = reader.getAttributeAsFloat("value");
m_format.setWidth(reader.getAttributeAsFloat("value"));
reader.readElement("Color");
std::string temp = reader.getAttribute("value");
m_format.m_color.fromHexString(temp);
std::string tempHex = reader.getAttribute("value");
App::Color tempColor;
tempColor.fromHexString(tempHex);
m_format.setColor(tempColor);
reader.readElement("Visible");
m_format.m_visible = (int)reader.getAttributeAsInteger("value")==0?false:true;
m_format.setVisible((int)reader.getAttributeAsInteger("value") == 0 ? false : true);
// older documents may not have the LineNumber element, so we need to check the
// next entry. if it is a start element, then we check if it is a start element
// for LineNumber.
@@ -566,10 +514,10 @@ GeomFormat* GeomFormat::copy() const
{
GeomFormat* newFmt = new GeomFormat();
newFmt->m_geomIndex = m_geomIndex;
newFmt->m_format.m_style = m_format.m_style;
newFmt->m_format.m_weight = m_format.m_weight;
newFmt->m_format.m_color = m_format.m_color;
newFmt->m_format.m_visible = m_format.m_visible;
newFmt->m_format.setStyle(m_format.getStyle());
newFmt->m_format.setWidth(m_format.getWidth());
newFmt->m_format.setColor(m_format.getColor());
newFmt->m_format.setVisible(m_format.getVisible());
newFmt->m_format.setLineNumber(m_format.getLineNumber());
return newFmt;
}

View File

@@ -31,54 +31,13 @@
#include <Base/Vector3D.h>
#include "Geometry.h"
#include "LineFormat.h"
class TopoDS_Edge;
namespace TechDraw {
class DrawViewPart;
//general purpose line format specifier
class TechDrawExport LineFormat
{
public:
static constexpr size_t InvalidLine{0};
LineFormat();
LineFormat(const int style,
const double weight,
const App::Color& color,
const bool visible);
~LineFormat() = default;
int getStyle() const { return m_style; }
void setStyle(int style) { m_style = style; }
double getWidth() const { return m_weight; }
void setWidth(double width) {m_weight = width; }
App::Color getColor() const { return m_color; }
void setColor(App::Color color) { m_color = color; }
QColor getQColor() const { return m_color.asValue<QColor>(); }
void setQColor(QColor qColor) { m_color.set(qColor.redF(), qColor.greenF(), qColor.blueF(), 1.0 - qColor.alphaF()); }
bool getVisible() const { return m_visible; }
void setVisible(bool viz) { m_visible = viz; }
int getLineNumber() const { return m_lineNumber; }
void setLineNumber(int number) { m_lineNumber = number; }
int m_style;
double m_weight;
App::Color m_color;
bool m_visible;
int m_lineNumber {1};
static double getDefEdgeWidth();
static App::Color getDefEdgeColor();
static int getDefEdgeStyle();
void dump(const char* title);
std::string toString() const;
};
//********** CosmeticEdge ******************************************************
class TechDrawExport CosmeticEdge : public Base::Persistence, public TechDraw::BaseGeom
@@ -99,6 +58,11 @@ public:
TechDraw::BaseGeomPtr scaledAndRotatedGeometry(const double scale, const double rotDegrees);
static TechDraw::BaseGeomPtr makeCanonicalLine(DrawViewPart* dvp, Base::Vector3d start, Base::Vector3d end);
static TechDraw::BaseGeomPtr makeLineFromCanonicalPoints(Base::Vector3d start, Base::Vector3d end);
LineFormat format() const { return m_format; }
void setFormat(LineFormat newFormat) { m_format = newFormat; }
std::string toString() const override;
void dump(const char* title) const;
@@ -108,7 +72,6 @@ public:
void Restore(Base::XMLReader &/*reader*/) override;
PyObject *getPyObject() override;
CosmeticEdge* copy() const;
CosmeticEdge* clone() const;
Base::Vector3d permaStart; //persistent unscaled start/end points in View coords

View File

@@ -15,16 +15,6 @@
<Author Licence="LGPL" Name="WandererFan" EMail="wandererfan@gmail.com" />
<UserDocu>CosmeticEdge specifies an extra (cosmetic) edge in Views</UserDocu>
</Documentation>
<Methode Name="clone" Const="true">
<Documentation>
<UserDocu>Create a clone of this CosmeticEdge</UserDocu>
</Documentation>
</Methode>
<Methode Name="copy" Const="true">
<Documentation>
<UserDocu>Create a copy of this CosmeticEdge</UserDocu>
</Documentation>
</Methode>
<Attribute Name="Tag" ReadOnly="true">
<Documentation>
<UserDocu>Gives the tag of the CosmeticEdge as string.</UserDocu>

View File

@@ -62,59 +62,59 @@ int CosmeticEdgePy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
}
//From Part::GeometryPy.cpp
PyObject* CosmeticEdgePy::clone(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return nullptr;
// PyObject* CosmeticEdgePy::clone(PyObject *args)
// {
// if (!PyArg_ParseTuple(args, ""))
// return nullptr;
TechDraw::CosmeticEdge* geom = this->getCosmeticEdgePtr();
PyTypeObject* type = this->GetType();
PyObject* cpy = nullptr;
// let the type object decide
if (type->tp_new)
cpy = type->tp_new(type, this, nullptr);
if (!cpy) {
PyErr_SetString(PyExc_RuntimeError, "failed to create clone of CosmeticEdge");
return nullptr;
}
// TechDraw::CosmeticEdge* geom = this->getCosmeticEdgePtr();
// PyTypeObject* type = this->GetType();
// PyObject* cpy = nullptr;
// // let the type object decide
// if (type->tp_new)
// cpy = type->tp_new(type, this, nullptr);
// if (!cpy) {
// PyErr_SetString(PyExc_RuntimeError, "failed to create clone of CosmeticEdge");
// return nullptr;
// }
TechDraw::CosmeticEdgePy* geompy = static_cast<TechDraw::CosmeticEdgePy*>(cpy);
// the PyMake function must have created the corresponding instance of the 'CosmeticEdge' subclass
// so delete it now to avoid a memory leak
if (geompy->_pcTwinPointer) {
TechDraw::CosmeticEdge* clone = static_cast<TechDraw::CosmeticEdge*>(geompy->_pcTwinPointer);
delete clone;
}
geompy->_pcTwinPointer = geom->clone();
return cpy;
}
// TechDraw::CosmeticEdgePy* geompy = static_cast<TechDraw::CosmeticEdgePy*>(cpy);
// // the PyMake function must have created the corresponding instance of the 'CosmeticEdge' subclass
// // so delete it now to avoid a memory leak
// if (geompy->_pcTwinPointer) {
// TechDraw::CosmeticEdge* clone = static_cast<TechDraw::CosmeticEdge*>(geompy->_pcTwinPointer);
// delete clone;
// }
// geompy->_pcTwinPointer = geom->clone();
// return cpy;
// }
PyObject* CosmeticEdgePy::copy(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return nullptr;
// PyObject* CosmeticEdgePy::copy(PyObject *args)
// {
// if (!PyArg_ParseTuple(args, ""))
// return nullptr;
TechDraw::CosmeticEdge* geom = this->getCosmeticEdgePtr();
PyTypeObject* type = this->GetType();
PyObject* cpy = nullptr;
// let the type object decide
if (type->tp_new)
cpy = type->tp_new(type, this, nullptr);
if (!cpy) {
PyErr_SetString(PyExc_RuntimeError, "failed to create copy of CosmeticEdge");
return nullptr;
}
// TechDraw::CosmeticEdge* ce = this->getCosmeticEdgePtr();
// PyTypeObject* type = this->GetType();
// PyObject* cpy = nullptr;
// // let the type object decide
// if (type->tp_new)
// cpy = type->tp_new(type, this, nullptr);
// if (!cpy) {
// PyErr_SetString(PyExc_RuntimeError, "failed to create copy of CosmeticEdge");
// return nullptr;
// }
TechDraw::CosmeticEdgePy* geompy = static_cast<TechDraw::CosmeticEdgePy*>(cpy);
// the PyMake function must have created the corresponding instance of the 'CosmeticEdge' subclass
// so delete it now to avoid a memory leak
if (geompy->_pcTwinPointer) {
TechDraw::CosmeticEdge* copy = static_cast<TechDraw::CosmeticEdge*>(geompy->_pcTwinPointer);
delete copy;
}
geompy->_pcTwinPointer = geom->copy();
return cpy;
}
// TechDraw::CosmeticEdgePy* geompy = static_cast<TechDraw::CosmeticEdgePy*>(cpy);
// // the PyMake function must have created the corresponding instance of the 'CosmeticEdge' subclass
// // so delete it now to avoid a memory leak
// if (geompy->_pcTwinPointer) {
// TechDraw::CosmeticEdge* copy = static_cast<TechDraw::CosmeticEdge*>(geompy->_pcTwinPointer);
// delete copy;
// }
// geompy->_pcTwinPointer = ce->copy();
// return cpy;
// }
void CosmeticEdgePy::setFormat(Py::Dict arg)
{
@@ -131,10 +131,10 @@ void CosmeticEdgePy::setFormat(Py::Dict arg)
}
TechDraw::LineFormat* format = &(this->getCosmeticEdgePtr()->m_format);
format->m_style = style;
format->m_weight = weight;
format->m_color = DrawUtil::pyTupleToColor(pColor);
format->m_visible = Base::asBoolean(visible);
format->setStyle(style);
format->setWidth(weight);
format->setColor(DrawUtil::pyTupleToColor(pColor));
format->setVisible(Base::asBoolean(visible));
}
Py::Dict CosmeticEdgePy::getFormat() const
@@ -142,10 +142,10 @@ Py::Dict CosmeticEdgePy::getFormat() const
TechDraw::LineFormat* format= &(this->getCosmeticEdgePtr()->m_format);
Py::Dict dict;
dict.setItem("style", Py::Long(format->m_style));
dict.setItem("weight", Py::Float(format->m_weight));
dict.setItem("color", Py::Tuple(DrawUtil::colorToPyTuple(format->m_color), true));
dict.setItem("visible", Py::Boolean(format->m_visible));
dict.setItem("style", Py::Long(format->getStyle()));
dict.setItem("weight", Py::Float(format->getWidth()));
dict.setItem("color", Py::Tuple(DrawUtil::colorToPyTuple(format->getColor()), true));
dict.setItem("visible", Py::Boolean(format->getVisible()));
return dict;
}

View File

@@ -62,6 +62,35 @@ TechDraw::DrawViewPart* CosmeticExtension::getOwner()
return static_cast<TechDraw::DrawViewPart*>(getExtendedObject());
}
//! remove cosmetic elements for a list of subelement names
void CosmeticExtension::deleteCosmeticElements(std::vector<std::string> removables)
{
// Base::Console().Message("CEx::deleteCosmeticElements(%d removables)\n", removables.size());
for (auto& name : removables) {
if (DU::getGeomTypeFromName(name) == "Vertex" &&
DU::isCosmeticVertex(getOwner(), name)) {
CosmeticVertex* vert = getCosmeticVertexBySelection(name);
removeCosmeticVertex(vert->getTagAsString());
continue;
}
if (DU::getGeomTypeFromName(name) == "Edge" &&
( DU::isCosmeticEdge(getOwner(), name) ||
DU::isCenterLine(getOwner(), name) ) ) {
CosmeticEdge* edge = getCosmeticEdgeBySelection(name);
if (edge) {
// if not edge, something has gone very wrong!
removeCosmeticEdge(edge->getTagAsString());
continue;
}
CenterLine* line = getCenterLineBySelection(name);
if (line) {
removeCenterLine(line->getTagAsString());
continue;
}
}
}
}
//==============================================================================
//CosmeticVertex x, y are stored as unscaled, but mirrored (inverted Y) values.
//if you are creating a CV based on calculations of scaled geometry, you need to
@@ -161,13 +190,18 @@ int CosmeticExtension::getCVIndex(const std::string& tag)
}
/// adds a cosmetic vertex to the property list. does not add to display geometry until dvp executes.
/// returns unique CV id
std::string CosmeticExtension::addCosmeticVertex(const Base::Vector3d& pos)
/// returns unique CV id. if the pos parameter is in real world coordinates, then invert should be true
/// (the default). if pos is in TD geometry or scene coordinates, then it is already inverted, and
/// invert should be set to false.
std::string CosmeticExtension::addCosmeticVertex(const Base::Vector3d& pos, bool invert)
{
// Base::Console().Message("CEx::addCosmeticVertex(%s)\n",
// DrawUtil::formatVector(pos).c_str());
std::vector<CosmeticVertex*> verts = CosmeticVertexes.getValues();
Base::Vector3d tempPos = DrawUtil::invertY(pos);
Base::Vector3d tempPos = pos;
if (invert) {
tempPos = DrawUtil::invertY(pos);
}
TechDraw::CosmeticVertex* cv = new TechDraw::CosmeticVertex(tempPos);
verts.push_back(cv);
CosmeticVertexes.setValues(verts);
@@ -393,6 +427,8 @@ void CosmeticExtension::removeCosmeticEdge(const std::string& delTag)
/// remove the cosmetic edges with the given tags from the list property
void CosmeticExtension::removeCosmeticEdge(const std::vector<std::string>& delTags)
{
// Base::Console().Message("DVP::removeCE(%d tages)\n", delTags.size());
std::vector<CosmeticEdge*> cEdges = CosmeticEdges.getValues();
for (auto& t: delTags) {
removeCosmeticEdge(t);
}

View File

@@ -56,7 +56,7 @@ public:
virtual CosmeticVertex* getCosmeticVertex(const std::string& tag) const;
virtual int add1CVToGV(const std::string& tag);
virtual int getCVIndex(const std::string& tag);
virtual std::string addCosmeticVertex(const Base::Vector3d& pos);
virtual std::string addCosmeticVertex(const Base::Vector3d& pos, bool invert = true);
virtual void addCosmeticVertexesToGeom();
virtual void clearCosmeticVertexes();
virtual void refreshCVGeoms();
@@ -95,6 +95,8 @@ public:
virtual void removeGeomFormat(const std::string& tag);
virtual void clearGeomFormats();
void deleteCosmeticElements(std::vector<std::string> removables);
TechDraw::DrawViewPart* getOwner();
PyObject* getExtensionPyObject() override;

View File

@@ -21,6 +21,8 @@
* *
***************************************************************************/
//! CosmeticVertex point is stored in unscaled, unrotated form
#include "PreCompiled.h"
#ifndef _PreComp_
#include <boost/uuid/uuid_generators.hpp>
@@ -46,14 +48,9 @@ TYPESYSTEM_SOURCE(TechDraw::CosmeticVertex, Base::Persistence)
CosmeticVertex::CosmeticVertex() : TechDraw::Vertex()
{
point(Base::Vector3d(0.0, 0.0, 0.0));
permaPoint = Base::Vector3d(0.0, 0.0, 0.0);
linkGeom = -1;
color = Preferences::vertexColor();
size = Preferences::vertexScale() *
LineGroup::getDefaultWidth("Thin");
style = 1;
visible = true;
hlrVisible = true;
cosmetic = true;
@@ -76,7 +73,6 @@ CosmeticVertex::CosmeticVertex(const TechDraw::CosmeticVertex* cv) : TechDraw::V
CosmeticVertex::CosmeticVertex(const Base::Vector3d& loc) : TechDraw::Vertex(loc)
{
// Base::Console().Message("CV::CV(%s)\n", DU::formatVector(loc).c_str());
permaPoint = loc;
linkGeom = -1;
color = Preferences::vertexColor();
@@ -93,21 +89,17 @@ CosmeticVertex::CosmeticVertex(const Base::Vector3d& loc) : TechDraw::Vertex(loc
void CosmeticVertex::move(const Base::Vector3d& newPos)
{
permaPoint = newPos;
point(newPos);
}
void CosmeticVertex::moveRelative(const Base::Vector3d& movement)
{
permaPoint += movement;
point( point() += movement);
}
std::string CosmeticVertex::toString() const
{
std::stringstream ss;
ss << permaPoint.x << ", " <<
permaPoint.y << ", " <<
permaPoint.z << ", " <<
" / ";
ss << point().x << ", " <<
point().y << ", " <<
point().z << ", " <<
@@ -181,13 +173,15 @@ Base::Vector3d CosmeticVertex::scaled(const double factor)
return permaPoint * factor;
}
//! returns a transformed version of our coordinates (permaPoint)
Base::Vector3d CosmeticVertex::rotatedAndScaled(const double scale, const double rotDegrees)
{
Base::Vector3d scaledPoint = scaled(scale);
if (rotDegrees != 0.0) {
// invert the Y coordinate so the rotation math works out
// the stored point is inverted
scaledPoint = DU::invertY(scaledPoint);
scaledPoint.RotateZ(rotDegrees * M_PI / 180.0);
scaledPoint.RotateZ(rotDegrees * M_PI / DegreesHalfCircle);
scaledPoint = DU::invertY(scaledPoint);
}
return scaledPoint;
@@ -198,13 +192,12 @@ Base::Vector3d CosmeticVertex::rotatedAndScaled(const double scale, const double
//! inverted back on return.
Base::Vector3d CosmeticVertex::makeCanonicalPoint(DrawViewPart* dvp, Base::Vector3d point, bool unscale)
{
// Base::Console().Message("CV::makeCanonicalPoint(%s)\n", DU::formatVector(point).c_str());
double rotDeg = dvp->Rotation.getValue();
Base::Vector3d result = point;
if (rotDeg != 0.0) {
// unrotate the point
double rotRad = rotDeg * M_PI / 180.0;
double rotRad = rotDeg * M_PI / DegreesHalfCircle;
// we always rotate around the origin.
result.RotateZ(-rotRad);
}
@@ -219,6 +212,16 @@ Base::Vector3d CosmeticVertex::makeCanonicalPoint(DrawViewPart* dvp, Base::Vecto
return result;
}
//! a version of makeCanonicalPoint that accepts and returns an invertedPoint.
Base::Vector3d CosmeticVertex::makeCanonicalPointInverted(DrawViewPart* dvp, Base::Vector3d invertedPoint, bool unscale)
{
Base::Vector3d result = makeCanonicalPoint(dvp,
DU::invertY(invertedPoint),
unscale);
return DU::invertY(result);
}
boost::uuids::uuid CosmeticVertex::getTag() const
{
return tag;

View File

@@ -47,6 +47,8 @@ public:
CosmeticVertex(const Base::Vector3d& loc);
~CosmeticVertex() override = default;
Base::Vector3d point() const { return permaPoint; };
void point(Base::Vector3d newPoint) { permaPoint = newPoint; }
void move(const Base::Vector3d& newPos);
void moveRelative(const Base::Vector3d& movement);
@@ -56,6 +58,7 @@ public:
Base::Vector3d rotatedAndScaled(const double scale, const double rotDegrees);
static Base::Vector3d makeCanonicalPoint(DrawViewPart* dvp, Base::Vector3d point, bool unscale = true);
static Base::Vector3d makeCanonicalPointInverted(DrawViewPart* dvp, Base::Vector3d invertedPoint, bool unscale = true);
static bool restoreCosmetic();
// Persistence implementer ---------------------
@@ -67,13 +70,13 @@ public:
CosmeticVertex* copy() const;
CosmeticVertex* clone() const;
Base::Vector3d permaPoint; //permanent, unscaled value
int linkGeom; //connection to corresponding "geom" Vertex (fragile - index based!)
Base::Vector3d permaPoint{Base::Vector3d()}; //permanent, unscaled value
int linkGeom{-1}; //connection to corresponding "geom" Vertex (fragile - index based!)
//better to do reverse search for CosmeticTag in vertex geometry
App::Color color;
double size;
int style;
bool visible; //base class vertex also has visible property
App::Color color{App::Color()};
double size{1.0};
int style{1};
bool visible{true}; //base class vertex also has visible property
boost::uuids::uuid getTag() const;
std::string getTagAsString() const override;

View File

@@ -20,19 +20,29 @@
* *
***************************************************************************/
//! DrawLeaderLine - a class for storing leader line attributes and providing methods to apply transformations on leader geometry.
//! Waypoints are to be stored as displacements from the first Waypoint in printed page coordinates (mm, conventional
//! X and Y axes, (0, 0) at lower left). The first Waypoint is set to (0,0) after the displacements are calculated.
//! The leader's X,Y position is relative to the parent's origin. The X,Y position is unrotated and unscaled.
#include "PreCompiled.h"
#include <App/Document.h>
#include <Base/Console.h>
#include <Base/Parameter.h>
#include "DrawViewPart.h"
#include "DrawPage.h"
#include "DrawLeaderLine.h"
#include "DrawLeaderLinePy.h" // generated from DrawLeaderLinePy.xml
#include "ArrowPropEnum.h"
#include "DrawView.h"
#include "Preferences.h"
#include "DrawUtil.h"
using namespace TechDraw;
using DU = DrawUtil;
//===========================================================================
// DrawLeaderLine - Base class for drawing leader based features
@@ -66,26 +76,26 @@ DrawLeaderLine::DrawLeaderLine()
{
static const char *group = "Leader";
constexpr long int FilledArrow{0l};
constexpr long int NoEnd{7l};
ADD_PROPERTY_TYPE(LeaderParent, (nullptr), group, (App::PropertyType)(App::Prop_None),
"View to which this leader is attached");
LeaderParent.setScope(App::LinkScope::Global);
ADD_PROPERTY_TYPE(WayPoints, (Base::Vector3d()) ,group, App::Prop_None,
"Intermediate points for Leader line");
// EndType.setEnums(ArrowTypeEnums);
// ADD_PROPERTY(EndType, (prefEnd()));
StartSymbol.setEnums(ArrowPropEnum::ArrowTypeEnums);
ADD_PROPERTY(StartSymbol, (0l)); //filled arrow
ADD_PROPERTY(StartSymbol, (FilledArrow)); //filled arrow
// ADD_PROPERTY_TYPE(StartSymbol, (0), group, App::Prop_None, "Symbol (arrowhead) for start of line");
EndSymbol.setEnums(ArrowPropEnum::ArrowTypeEnums);
ADD_PROPERTY(EndSymbol, (7l)); //no symbol
// ADD_PROPERTY_TYPE(EndSymbol, (0), group, App::Prop_None, "Symbol (arrowhead) for end of line");
ADD_PROPERTY(EndSymbol, (NoEnd)); //no symbol
ADD_PROPERTY_TYPE(Scalable ,(false), group, App::Prop_None, "Scale line with LeaderParent");
ADD_PROPERTY_TYPE(AutoHorizontal ,(getDefAuto()), group, App::Prop_None, "Forces last line segment to be horizontal");
ADD_PROPERTY_TYPE(RotatesWithParent ,(true), group, App::Prop_None,
"If true, leader rotates around parent. If false, only first segment of leader changes with parent rotation.");
//hide the DrawView properties that don't apply to Leader
ScaleType.setStatus(App::Property::ReadOnly, true);
@@ -108,12 +118,16 @@ void DrawLeaderLine::onChanged(const App::Property* prop)
short DrawLeaderLine::mustExecute() const
{
if (!isRestoring() && LeaderParent.isTouched()) {
return true; // Property changed
return 1; // Property changed
}
const App::DocumentObject* docObj = getBaseObject();
if (docObj && docObj->isTouched()) {
return true; // Object property points to is touched
return 1; // Object property points to is touched
}
if (WayPoints.isTouched()) {
return 1;
}
return DrawView::mustExecute();
@@ -121,11 +135,13 @@ short DrawLeaderLine::mustExecute() const
App::DocumentObjectExecReturn *DrawLeaderLine::execute()
{
// Base::Console().Message("DLL::execute()\n");
// Base::Console().Message("DLL::execute()\n");
if (!keepUpdated()) {
return App::DocumentObject::StdReturn;
}
adjustLastSegment();
// is horizLastSegment something that should be done only at draw time?
horizLastSegment();
overrideKeepUpdated(false);
return DrawView::execute();
}
@@ -137,7 +153,7 @@ DrawView* DrawLeaderLine::getBaseView() const
return nullptr;
}
DrawView* cast = dynamic_cast<DrawView*>(baseObj);
auto cast = dynamic_cast<DrawView*>(baseObj);
return cast;
}
@@ -155,8 +171,6 @@ bool DrawLeaderLine::keepUpdated()
return view->keepUpdated();
}
//need separate getParentScale()???
double DrawLeaderLine::getBaseScale() const
{
// Base::Console().Message("DLL::getBaseScale()\n");
@@ -174,11 +188,7 @@ double DrawLeaderLine::getScale() const
return 1.0;
}
DrawView* parent = getBaseView();
if (!parent) {
return 1.0;
}
return parent->getScale();
return getBaseScale();
}
Base::Vector3d DrawLeaderLine::getAttachPoint()
@@ -190,23 +200,37 @@ Base::Vector3d DrawLeaderLine::getAttachPoint()
);
}
void DrawLeaderLine::adjustLastSegment()
//! unit agnostic conversion of last segment to horizontal. need to do this at drawing time otherwise
//! we just realign the canonical form.
void DrawLeaderLine::horizLastSegment()
{
// Base::Console().Message("DLL::adjustLastSegment()\n");
bool adjust = AutoHorizontal.getValue();
std::vector<Base::Vector3d> wp = WayPoints.getValues();
if (adjust && wp.size() > 1) {
int iLast = wp.size() - 1;
int iPen = wp.size() - 2;
// Base::Console().Message("DLL::horizLastSegment() - auto: %d\n", AutoHorizontal.getValue());
bool adjust = AutoHorizontal.getValue();
if (!adjust) {
return;
}
auto temp = horizLastSegment(WayPoints.getValues());
WayPoints.setValues(temp);
}
std::vector<Base::Vector3d> DrawLeaderLine::horizLastSegment(const std::vector<Base::Vector3d>& inDeltas)
{
// Base::Console().Message("DLL::horizLastSegment(in: %d)\n", inDeltas.size());
std::vector<Base::Vector3d> wp = inDeltas;
if (wp.size() > 1) {
size_t iLast = wp.size() - 1;
size_t iPen = wp.size() - 2;
Base::Vector3d last = wp.at(iLast);
Base::Vector3d penUlt = wp.at(iPen);
last.y = penUlt.y;
wp.at(iLast) = last;
}
WayPoints.setValues(wp);
return wp;
}
//middle of last line segment
//! returns the mid point of last segment. used by leader decorators like weld symbol.
Base::Vector3d DrawLeaderLine::getTileOrigin() const
{
std::vector<Base::Vector3d> wp = WayPoints.getValues();
@@ -215,17 +239,17 @@ Base::Vector3d DrawLeaderLine::getTileOrigin() const
Base::Vector3d second = wp.rbegin()[1];
return (last + second) / 2.0;
}
Base::Console().Warning("DLL::getTileOrigin - no waypoints\n");
return Base::Vector3d();
}
//start of last line segment
//! returns start of last line segment
Base::Vector3d DrawLeaderLine::getKinkPoint() const
{
std::vector<Base::Vector3d> wp = WayPoints.getValues();
if (wp.size() > 1) {
return wp.rbegin()[1]; // Second
return wp.rbegin()[1]; // second point from end
}
Base::Console().Warning("DLL::getKinkPoint - no waypoints\n");
@@ -239,12 +263,180 @@ Base::Vector3d DrawLeaderLine::getTailPoint() const
if (!wp.empty()) {
return wp.rbegin()[0]; // Last
}
Base::Console().Warning("DLL::getTailPoint - no waypoints\n");
return Base::Vector3d();
}
//! create a new leader feature from parameters. Used by python method makeLeader.
//! pagePoints are in mm from bottom left of page.
DrawLeaderLine* DrawLeaderLine::makeLeader(DrawViewPart* parent, std::vector<Base::Vector3d> pagePoints, int iStartSymbol, int iEndSymbol)
{
// Base::Console().Message("DLL::makeLeader(%s, %d, %d, %d)\n", parent->getNameInDocument(), pagePoints.size(), iStartSymbol, iEndSymbol);
if (pagePoints.size() < 2) {
Base::Console().Message("DLL::makeLeader - not enough pagePoints\n");
return {};
}
// this is +/- the same code as in TaskLeaderLine::createLeaderFeature()
const std::string objectName{"LeaderLine"};
const std::string leaderType = "TechDraw::DrawLeaderLine";
std::string leaderName = parent->getDocument()->getUniqueObjectName(objectName.c_str());
std::string pageName = parent->findParentPage()->getNameInDocument();
std::string parentName = parent->getNameInDocument();
Base::Interpreter().runStringArg("App.activeDocument().addObject('%s', '%s')",
leaderType.c_str(), leaderName.c_str());
Base::Interpreter().runStringArg("App.activeDocument().%s.translateLabel('DrawLeaderLine', 'LeaderLine', '%s')",
leaderName.c_str(), leaderName.c_str());
Base::Interpreter().runStringArg("App.activeDocument().%s.addView(App.activeDocument().%s)",
pageName.c_str(), leaderName.c_str());
Base::Interpreter().runStringArg("App.activeDocument().%s.LeaderParent = App.activeDocument().%s",
leaderName.c_str(), parentName.c_str());
// we assume here that the caller will handle AutoHorizontal, Scalable and Rotatable as required
App::DocumentObject* obj = parent->getDocument()->getObject(leaderName.c_str());
if (!obj || !obj->isDerivedFrom(TechDraw::DrawLeaderLine::getClassTypeId())) {
throw Base::RuntimeError("DrawLeaderLine::makeLeader - new object not found");
}
// set leader x,y position
auto leaderFeature = static_cast<TechDraw::DrawLeaderLine*>(obj);
Base::Vector3d parentPagePos{ parent->X.getValue(), parent->Y.getValue(), 0.0};
Base::Vector3d leaderPagePos = pagePoints.front() - parentPagePos;
bool force = true; // update position even though leaders default to locked.
leaderFeature->setPosition(leaderPagePos.x, leaderPagePos.y, force);
// page positions to deltas
std::vector<Base::Vector3d> pageDeltas;
for (auto& point : pagePoints) {
auto temp = point - pagePoints.front();
pageDeltas.emplace_back(temp);
}
// deltas to unscaled, unrotated form
auto leaderPoints = leaderFeature->makeCanonicalPoints(pageDeltas);
// invert the canonical points
std::vector<Base::Vector3d> inverted;
inverted.reserve(leaderPoints.size());
for (auto& point : leaderPoints) {
inverted.push_back(DU::invertY(point));
}
leaderFeature->WayPoints.setValues(inverted);
leaderFeature->StartSymbol.setValue(iStartSymbol);
leaderFeature->EndSymbol.setValue(iEndSymbol);
parent->touch();
return leaderFeature;
}
//! return scaled and rotated copies of the WayPoints (page position deltas from 1st point)
//! used by QGILL.
std::vector<Base::Vector3d> DrawLeaderLine::getScaledAndRotatedPoints(bool doScale, bool doRotate) const
{
// Base::Console().Message("DLL::getScaledAndRotatedPoints(%d, %d)\n", doScale, doRotate);
auto dvp = getBaseView();
if (!dvp) {
// document is restoring?
// Base::Console().Message("DLL::getScaledAndRotatedPoints - no DV\n");
return {};
}
double scale{1.0};
if (Scalable.getValue() && doScale) {
scale = dvp->getScale();
}
double rotationRad{0.0};
if (doRotate) {
rotationRad = dvp->Rotation.getValue() * M_PI / DegreesHalfCircle;
}
std::vector<Base::Vector3d> pointsAll = WayPoints.getValues();
std::vector<Base::Vector3d> result;
for (auto& point : pointsAll) {
Base::Vector3d newPoint = DU::invertY(point * scale);
if (rotationRad != 0.0) {
// the waypoints use conventional coords
newPoint.RotateZ(rotationRad);
}
result.push_back(DU::invertY(newPoint));
}
return result;
}
//! return unscaled and unrotated versions of the input points. input is expected to in mm (Rez::appX()),
//! and conventional Y axis (+ up)
//! used by QGILL.
std::vector<Base::Vector3d>
DrawLeaderLine::makeCanonicalPoints(const std::vector<Base::Vector3d>& inPoints,
bool doScale,
bool doRotate) const
{
// Base::Console().Message("DLL::makeCanonicalPoints(%d, %d, %d)\n", inPoints.size(), doScale, doRotate);
auto dvp = getBaseView();
double scale{1.0};
if (Scalable.getValue() && doScale) {
scale = dvp->getScale();
}
double rotationRad{0.0};
if (doRotate) {
rotationRad = - dvp->Rotation.getValue() * M_PI / DegreesHalfCircle;
}
std::vector<Base::Vector3d> result;
for (auto& point : inPoints) {
Base::Vector3d newPoint = point / scale;
if (rotationRad != 0.0) {
newPoint.RotateZ(rotationRad);
}
result.push_back(newPoint);
}
return result;
}
//! as makeCanonicalPoints, but accepts and returns inverted points
std::vector<Base::Vector3d>
DrawLeaderLine::makeCanonicalPointsInverted(const std::vector<Base::Vector3d>& inPoints,
bool doScale,
bool doRotate) const
{
std::vector<Base::Vector3d> conventionalPoints;
conventionalPoints.reserve(inPoints.size());
for (auto& point : inPoints) {
conventionalPoints.push_back(DU::invertY(point));
}
auto conventionalCanon = makeCanonicalPoints(inPoints, doScale, doRotate);
std::vector<Base::Vector3d> invertedPoints;
invertedPoints.reserve(inPoints.size());
for (auto& point : conventionalCanon) {
invertedPoints.push_back(DU::invertY(point));
}
return invertedPoints;
}
//! returns true if parent exists. if parent is a DVP it must have geometry.
bool DrawLeaderLine::isParentReady() const
{
TechDraw::DrawView* parent = getBaseView();
auto dvp = dynamic_cast<TechDraw::DrawViewPart*>(parent);
if (!parent || (dvp && !dvp->hasGeometry())) {
// still restoring or
// we are attached to a dvp that has no geometry, so don't bother trying to draw yet
Base::Console().Message("DLL:: - no parent or geometry\n");
return false;
}
return true;
}
bool DrawLeaderLine::getDefAuto() const
{
return Preferences::getPreferenceGroup("LeaderLine")->GetBool("AutoHorizontal", true);

View File

@@ -33,6 +33,7 @@
namespace TechDraw
{
class DrawViewPart;
class TechDrawExport DrawLeaderLine : public TechDraw::DrawView
{
@@ -47,14 +48,13 @@ public:
App::PropertyEnumeration StartSymbol;
App::PropertyEnumeration EndSymbol;
/* App::PropertyInteger StartSymbol; //see Gui/QGIArrow for values*/
/* App::PropertyInteger EndSymbol;*/
App::PropertyBool Scalable;
App::PropertyBool AutoHorizontal;
App::PropertyBool RotatesWithParent;
short mustExecute() const override;
App::DocumentObjectExecReturn *execute() override;
App::PropertyLink *getOwnerProperty() override { return &LeaderParent; }
const char* getViewProviderName() const override {
return "TechDrawGui::ViewProviderLeader";
@@ -65,18 +65,29 @@ public:
Base::Vector3d getAttachPoint();
DrawView* getBaseView() const;
virtual App::DocumentObject* getBaseObject() const;
App::PropertyLink *getOwnerProperty() override { return &LeaderParent; }
bool keepUpdated() override;
double getScale() const override;
double getBaseScale() const;
void adjustLastSegment();
void horizLastSegment();
static std::vector<Base::Vector3d> horizLastSegment(const std::vector<Base::Vector3d>& inDeltas);
bool getDefAuto() const;
Base::Vector3d getTileOrigin() const;
Base::Vector3d getKinkPoint() const;
Base::Vector3d getTailPoint() const;
static DrawLeaderLine* makeLeader(DrawViewPart* parent, std::vector<Base::Vector3d> points, int iStartSymbol = 0, int iEndSymbol = 0);
std::vector<Base::Vector3d> getScaledAndRotatedPoints(bool doScale = true, bool doRotate = true) const;
std::vector<Base::Vector3d> makeCanonicalPoints(const std::vector<Base::Vector3d>& inPoints,
bool doScale = true,
bool doRotate = true) const;
std::vector<Base::Vector3d> makeCanonicalPointsInverted(const std::vector<Base::Vector3d>& inPoints,
bool doScale = true,
bool doRotate = true) const;
bool isParentReady() const;
protected:
void onChanged(const App::Property* prop) override;

View File

@@ -52,6 +52,8 @@
#define M_2PI ((M_PI)*2.0)
#endif
constexpr double DegreesHalfCircle{180.0};
#define VERTEXTOLERANCE (2.0 * Precision::Confusion())
#define VECTORTOLERANCE (Precision::Confusion())

View File

@@ -52,7 +52,7 @@
using namespace TechDraw;
using DU = DrawUtil;
// returns a string which represents the object e.g. when printed in python
std::string DrawViewPartPy::representation() const
{
@@ -229,6 +229,7 @@ PyObject* DrawViewPartPy::makeCosmeticVertex(PyObject *args)
return PyUnicode_FromString(id.c_str()); //return tag for new CV
}
//! make a cosmetic vertex from a 3d point
PyObject* DrawViewPartPy::makeCosmeticVertex3d(PyObject *args)
{
PyObject* pPnt1 = nullptr;
@@ -239,9 +240,12 @@ PyObject* DrawViewPartPy::makeCosmeticVertex3d(PyObject *args)
DrawViewPart* dvp = getDrawViewPartPtr();
Base::Vector3d pnt1 = static_cast<Base::VectorPy*>(pPnt1)->value();
Base::Vector3d centroid = dvp->getOriginalCentroid();
// center the point
pnt1 = pnt1 - centroid;
Base::Vector3d projected = DrawUtil::invertY(dvp->projectPoint(pnt1));
projected = CosmeticVertex::makeCanonicalPoint(dvp, projected);
// project but do not invert
Base::Vector3d projected = dvp->projectPoint(pnt1);
// this is a real world point, it is not scaled or rotated, so so it is in canonical form
// add and invert the point.
std::string id = dvp->addCosmeticVertex(projected);
//int link =
dvp->add1CVToGV(id);
@@ -341,6 +345,8 @@ PyObject* DrawViewPartPy::removeCosmeticVertex(PyObject *args)
PyObject* DrawViewPartPy::makeCosmeticLine(PyObject *args)
{
// the input points are expected to use conventional coordinates (Y up) and need to be inverted
// before building the line
PyObject* pPnt1 = nullptr;
PyObject* pPnt2 = nullptr;
int style = LineFormat::getDefEdgeStyle();
@@ -358,12 +364,12 @@ PyObject* DrawViewPartPy::makeCosmeticLine(PyObject *args)
DrawViewPart* dvp = getDrawViewPartPtr();
Base::Vector3d pnt1 = static_cast<Base::VectorPy*>(pPnt1)->value();
Base::Vector3d pnt2 = static_cast<Base::VectorPy*>(pPnt2)->value();
std::string newTag = dvp->addCosmeticEdge(pnt1, pnt2);
std::string newTag = dvp->addCosmeticEdge(DU::invertY(pnt1), DU::invertY(pnt2));
TechDraw::CosmeticEdge* ce = dvp->getCosmeticEdge(newTag);
if (ce) {
ce->m_format.m_style = style;
ce->m_format.m_weight = weight;
ce->m_format.m_color = pColor ? DrawUtil::pyTupleToColor(pColor) : defCol;
ce->m_format.setStyle(style);
ce->m_format.setWidth(weight);
ce->m_format.setColor(pColor ? DrawUtil::pyTupleToColor(pColor) : defCol);
}
else {
PyErr_SetString(PyExc_RuntimeError, "DVPPI:makeCosmeticLine - line creation failed");
@@ -378,6 +384,7 @@ PyObject* DrawViewPartPy::makeCosmeticLine(PyObject *args)
PyObject* DrawViewPartPy::makeCosmeticLine3D(PyObject *args)
{
// input points are expected to be conventional 3d points
PyObject* pPnt1 = nullptr;
PyObject* pPnt2 = nullptr;
int style = LineFormat::getDefEdgeStyle();
@@ -397,18 +404,18 @@ PyObject* DrawViewPartPy::makeCosmeticLine3D(PyObject *args)
Base::Vector3d pnt1 = static_cast<Base::VectorPy*>(pPnt1)->value();
pnt1 = pnt1 - centroid;
pnt1 = DrawUtil::invertY(dvp->projectPoint(pnt1));
pnt1 = dvp->projectPoint(pnt1);
Base::Vector3d pnt2 = static_cast<Base::VectorPy*>(pPnt2)->value();
pnt2 = pnt2 - centroid;
pnt2 = DrawUtil::invertY(dvp->projectPoint(pnt2));
pnt2 = dvp->projectPoint(pnt2);
std::string newTag = dvp->addCosmeticEdge(pnt1, pnt2);
TechDraw::CosmeticEdge* ce = dvp->getCosmeticEdge(newTag);
if (ce) {
ce->m_format.m_style = style;
ce->m_format.m_weight = weight;
ce->m_format.m_color = pColor ? DrawUtil::pyTupleToColor(pColor) : defCol;
ce->m_format.setStyle(style);
ce->m_format.setWidth(weight);
ce->m_format.setColor(pColor ? DrawUtil::pyTupleToColor(pColor) : defCol);
}
else {
PyErr_SetString(PyExc_RuntimeError, "DVPPI:makeCosmeticLine - line creation failed");
@@ -444,9 +451,9 @@ PyObject* DrawViewPartPy::makeCosmeticCircle(PyObject *args)
TechDraw::CosmeticEdge* ce = dvp->getCosmeticEdge(newTag);
if (ce) {
ce->permaRadius = radius;
ce->m_format.m_style = style;
ce->m_format.m_weight = weight;
ce->m_format.m_color = pColor ? DrawUtil::pyTupleToColor(pColor) : defCol;
ce->m_format.setStyle(style);
ce->m_format.setWidth(weight);
ce->m_format.setColor(pColor ? DrawUtil::pyTupleToColor(pColor) : defCol);
}
else {
PyErr_SetString(PyExc_RuntimeError, "DVPPI:makeCosmeticCircle - circle creation failed");
@@ -484,12 +491,12 @@ PyObject* DrawViewPartPy::makeCosmeticCircleArc(PyObject *args)
TechDraw::CosmeticEdge* ce = dvp->getCosmeticEdge(newTag);
if (ce) {
ce->permaRadius = radius;
ce->m_format.m_style = style;
ce->m_format.m_weight = weight;
ce->m_format.setStyle(style);
ce->m_format.setWidth(weight);
if (!pColor)
ce->m_format.m_color = defCol;
ce->m_format.setColor(defCol);
else
ce->m_format.m_color = DrawUtil::pyTupleToColor(pColor);
ce->m_format.setColor(DrawUtil::pyTupleToColor(pColor));
}
else {
PyErr_SetString(PyExc_RuntimeError, "DVPPI:makeCosmeticCircleArc - arc creation failed");
@@ -529,9 +536,9 @@ PyObject* DrawViewPartPy::makeCosmeticCircle3d(PyObject *args)
TechDraw::CosmeticEdge* ce = dvp->getCosmeticEdge(newTag);
if (ce) {
ce->permaRadius = radius;
ce->m_format.m_style = style;
ce->m_format.m_weight = weight;
ce->m_format.m_color = pColor ? DrawUtil::pyTupleToColor(pColor) : defCol;
ce->m_format.setStyle(style);
ce->m_format.setWidth(weight);
ce->m_format.setColor(pColor ? DrawUtil::pyTupleToColor(pColor) : defCol);
}
else {
PyErr_SetString(PyExc_RuntimeError, "DVPPI:makeCosmeticCircle - circle creation failed");
@@ -572,12 +579,12 @@ PyObject* DrawViewPartPy::makeCosmeticCircleArc3d(PyObject *args)
TechDraw::CosmeticEdge* ce = dvp->getCosmeticEdge(newTag);
if (ce) {
ce->permaRadius = radius;
ce->m_format.m_style = style;
ce->m_format.m_weight = weight;
ce->m_format.setStyle(style);
ce->m_format.setWidth(weight);
if (!pColor)
ce->m_format.m_color = defCol;
ce->m_format.setColor(defCol);
else
ce->m_format.m_color = DrawUtil::pyTupleToColor(pColor);
ce->m_format.setColor(DrawUtil::pyTupleToColor(pColor));
}
else {
PyErr_SetString(PyExc_RuntimeError, "DVPPI:makeCosmeticCircleArc - arc creation failed");
@@ -763,10 +770,10 @@ PyObject* DrawViewPartPy::formatGeometricEdge(PyObject *args)
DrawViewPart* dvp = getDrawViewPartPtr();
TechDraw::GeomFormat* gf = dvp->getGeomFormatBySelection(idx);
if (gf) {
gf->m_format.m_style = style;
gf->m_format.m_color = color;
gf->m_format.m_weight = weight;
gf->m_format.m_visible = visible;
gf->m_format.setStyle(style);
gf->m_format.setColor(color);
gf->m_format.setWidth(weight);
gf->m_format.setVisible(visible);
}
else {
TechDraw::LineFormat fmt(style, weight, color, visible);

View File

@@ -621,7 +621,7 @@ std::vector<Base::Vector3d> BaseGeom::intersection(TechDraw::BaseGeomPtr geom2)
TopExp_Explorer explorer(sectionShape, TopAbs_VERTEX);
while (explorer.More()) {
Base::Vector3d pt(DrawUtil::toVector3d(BRep_Tool::Pnt(TopoDS::Vertex(explorer.Current()))));
interPoints.push_back(DrawUtil::invertY(pt));
interPoints.push_back(pt);
explorer.Next();
}
}
@@ -802,16 +802,20 @@ AOC::AOC(const TopoDS_Edge &e) : Circle(e)
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
// this is the wrong determination of cw/ccw. needs to be determined by edge.
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());
startPnt = DU::toVector3d(s);
endPnt = DU::toVector3d(ePt);
midPnt = DU::toVector3d(m);
if (e.Orientation() == TopAbs_REVERSED) {
reversed = true;
}
@@ -845,6 +849,11 @@ AOC::AOC(Base::Vector3d c, double r, double sAng, double eAng) : Circle()
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
// this is a bit of an arcane method of determining if v2 is clockwise from v1 or counter clockwise from v1.
// The v1 x v2 points up if v2 is ccw from v1 and points down if v2 is cw from v1. Taking (v1 x v2) * stdZ
// gives 1 for parallel with stdZ (v2 is ccw from v1) or -1 for antiparallel with stdZ (v2 is clockwise from v1).
// this cw flag is a problem. we should just declare that arcs are always ccw and flip the start and end angles.
double a = v3.DotCross(v1, v2); //error if v1 = v2?
startAngle = fmod(f, 2.0*M_PI);
@@ -852,9 +861,9 @@ AOC::AOC(Base::Vector3d c, double r, double sAng, double eAng) : Circle()
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());
startPnt = DU::toVector3d(s);
endPnt = DU::toVector3d(ePt);
midPnt = DU::toVector3d(m);
if (edge.Orientation() == TopAbs_REVERSED) {
reversed = true;
}
@@ -890,6 +899,22 @@ bool AOC::isOnArc(Base::Vector3d p)
return false;
}
BaseGeomPtr AOC::copy()
{
auto base = BaseGeom::copy();
TechDraw::CirclePtr circle = std::static_pointer_cast<TechDraw::Circle>(base);
TechDraw::AOCPtr aoc = std::static_pointer_cast<TechDraw::AOC>(circle);
if (aoc) {
aoc->clockwiseAngle(clockwiseAngle());
aoc->startPnt = startPnt;
aoc->startAngle = startAngle;
aoc->endPnt = endPnt;
aoc->endAngle = endAngle;
aoc->largeArc = largeArc;
}
return base;
}
double AOC::distToArc(Base::Vector3d p)
{
return minDist(p);

View File

@@ -113,7 +113,7 @@ class TechDrawExport BaseGeom : public std::enable_shared_from_this<BaseGeom>
static bool validateEdge(TopoDS_Edge edge);
static TopoDS_Edge completeEdge(const TopoDS_Edge &edge);
bool closed();
BaseGeomPtr copy();
virtual BaseGeomPtr copy();
std::string dump();
virtual std::string toString() const;
std::vector<Base::Vector3d> intersection(TechDraw::BaseGeomPtr geom2);
@@ -241,6 +241,7 @@ class TechDrawExport AOC: public Circle
~AOC() override = default;
public:
BaseGeomPtr copy() override;
double getStartAngle() override { return startAngle; }
double getEndAngle() override { return endAngle; }
bool clockwiseAngle() override { return cw; }

View File

@@ -624,14 +624,13 @@ void GeometryObject::addEdge(TechDraw::BaseGeomPtr bg) { edgeGeom.push_back(bg);
//adds a new GeomVert surrogate for CV
//returns GeomVert selection index ("Vertex3")
// insertGeomForCV(cv)
// is this ever used?
int GeometryObject::addCosmeticVertex(CosmeticVertex* cv)
{
// Base::Console().Message("GO::addCosmeticVertex(%X)\n", cv);
double scale = m_parent->getScale();
Base::Vector3d pos = cv->scaled(scale);
TechDraw::VertexPtr v(std::make_shared<TechDraw::Vertex>(pos.x, pos.y));
v->setCosmetic(true);
// v->setCosmeticLink = -1;//obs??
v->setCosmeticTag(cv->getTagAsString());
v->setHlrVisible(true);
int idx = vertexGeom.size();
@@ -643,7 +642,6 @@ int GeometryObject::addCosmeticVertex(CosmeticVertex* cv)
//should probably be called addVertex since not connect to CV by tag
int GeometryObject::addCosmeticVertex(Base::Vector3d pos)
{
Base::Console().Message("GO::addCosmeticVertex() 1 - deprec?\n");
TechDraw::VertexPtr v(std::make_shared<TechDraw::Vertex>(pos.x, pos.y));
v->setCosmetic(true);
v->setCosmeticTag("tbi");//not connected to CV
@@ -655,7 +653,6 @@ int GeometryObject::addCosmeticVertex(Base::Vector3d pos)
int GeometryObject::addCosmeticVertex(Base::Vector3d pos, std::string tagString)
{
// Base::Console().Message("GO::addCosmeticVertex() 2\n");
TechDraw::VertexPtr v(std::make_shared<TechDraw::Vertex>(pos.x, pos.y));
v->setCosmetic(true);
v->setCosmeticTag(tagString);//connected to CV

View File

@@ -0,0 +1,117 @@
// SPDX-License-Identifier: LGPL-2.0-or-later
/***************************************************************************
* Copyright (c) 2024 wandererfan <wandererfan at gmail dot com> *
* *
* 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 "PreCompiled.h"
#ifndef _PreComp_
#endif
#include "LineGroup.h"
#include "LineGenerator.h"
#include "Preferences.h"
#include "LineFormat.h"
using namespace TechDraw;
//! general purpose line format specifier
LineFormat::LineFormat()
{
m_style = getDefEdgeStyle();
m_weight = getDefEdgeWidth();
m_color= getDefEdgeColor();
m_visible = true;
m_lineNumber = LineGenerator::fromQtStyle((Qt::PenStyle)m_style);
}
// static loader of default format
void LineFormat::initCurrentLineFormat()
{
getCurrentLineFormat().setStyle(getDefEdgeStyle());
getCurrentLineFormat().setWidth(getDefEdgeWidth());
getCurrentLineFormat().setColor(getDefEdgeColor());
getCurrentLineFormat().setVisible(true);
getCurrentLineFormat().setLineNumber(LineGenerator::fromQtStyle((Qt::PenStyle)getCurrentLineFormat().getStyle()));
}
LineFormat& LineFormat::getCurrentLineFormat()
{
static TechDraw::LineFormat currentLineFormat;
return currentLineFormat;
}
void LineFormat::setCurrentLineFormat(LineFormat& newFormat)
{
getCurrentLineFormat().setStyle(newFormat.getStyle());
getCurrentLineFormat().setWidth(newFormat.getWidth());
getCurrentLineFormat().setColor(newFormat.getColor());
getCurrentLineFormat().setVisible(newFormat.getVisible());
getCurrentLineFormat().setLineNumber(newFormat.getLineNumber());
}
LineFormat::LineFormat(const int style,
const double weight,
const App::Color& color,
const bool visible) :
m_style(style),
m_weight(weight),
m_color(color),
m_visible(visible),
m_lineNumber(LineGenerator::fromQtStyle((Qt::PenStyle)m_style))
{
}
void LineFormat::dump(const char* title)
{
Base::Console().Message("LF::dump - %s \n", title);
Base::Console().Message("LF::dump - %s \n", toString().c_str());
}
std::string LineFormat::toString() const
{
std::stringstream ss;
ss << m_style << ", " <<
m_weight << ", " <<
m_color.asHexString() << ", " <<
m_visible;
return ss.str();
}
//static preference getters.
double LineFormat::getDefEdgeWidth()
{
return TechDraw::LineGroup::getDefaultWidth("Graphic");
}
App::Color LineFormat::getDefEdgeColor()
{
return Preferences::normalColor();
}
int LineFormat::getDefEdgeStyle()
{
return Preferences::getPreferenceGroup("Decorations")->GetInt("CenterLineStyle", 2); //dashed
}

View File

@@ -0,0 +1,96 @@
// SPDX-License-Identifier: LGPL-2.0-or-later
/***************************************************************************
* Copyright (c) 2024 wandererfan <wandererfan at gmail dot com> *
* *
* 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 *
* *
***************************************************************************/
#ifndef TECHDRAW_LINEFORMAT_H
#define TECHDRAW_LINEFORMAT_H
#include <Mod/TechDraw/TechDrawGlobal.h>
#include <QColor>
#include <App/Color.h>
namespace TechDraw {
//! general purpose line format specifier
class TechDrawExport LineFormat
{
public:
static constexpr size_t InvalidLine{0};
LineFormat();
LineFormat(const int style,
const double weight,
const App::Color& color,
const bool visible,
const int lineNumber);
// TODO: phase out the old 4 parameter constructor
LineFormat(const int style,
const double weight,
const App::Color& color,
const bool visible);
~LineFormat() = default;
// style was used to specify QPen styles. line number (from LineGenerator) should be used now.
int getStyle() const { return m_style; }
void setStyle(int style) { m_style = style; }
double getWidth() const { return m_weight; }
void setWidth(double width) {m_weight = width; }
App::Color getColor() const { return m_color; }
void setColor(App::Color color) { m_color = color; }
QColor getQColor() const { return m_color.asValue<QColor>(); }
void setQColor(QColor qColor) { m_color.set(qColor.redF(), qColor.greenF(), qColor.blueF(), 1.0 - qColor.alphaF()); }
bool getVisible() const { return m_visible; }
void setVisible(bool viz) { m_visible = viz; }
int getLineNumber() const { return m_lineNumber; }
void setLineNumber(int number) { m_lineNumber = number; }
static double getDefEdgeWidth();
static App::Color getDefEdgeColor();
static int getDefEdgeStyle();
void dump(const char* title);
std::string toString() const;
static void initCurrentLineFormat();
static LineFormat& getCurrentLineFormat();
static void setCurrentLineFormat(LineFormat& newformat);
private:
int m_style;
double m_weight;
App::Color m_color;
bool m_visible;
int m_lineNumber {1};
};
} //end namespace TechDraw
#endif //TECHDRAW_LINEFORMAT_H

View File

@@ -27,6 +27,8 @@
#include <Mod/TechDraw/TechDrawGlobal.h>
#include <string>
#include <vector>
#include <string>
namespace TechDraw

View File

@@ -0,0 +1,77 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# **************************************************************************
# Copyright (c) 2018 WandererFan <wandererfan@gmail.com> *
# *
# This file is part of the FreeCAD CAx development system. *
# *
# This program is free software; you can redistribute it and/or modify *
# it under the terms of the GNU Lesser General Public License (LGPL) *
# as published by the Free Software Foundation; either version 2 of *
# the License, or (at your option) any later version. *
# for detail see the LICENCE text file. *
# *
# FreeCAD 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 FreeCAD; if not, write to the Free Software *
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# USA *
# **************************************************************************
# Name: moveView macro
# About: move Views from Drawing Page to TechDraw Page in the current doc
# Usage: select 1 Drawing Page and 1 TechDraw Page, run moveViews macro
# Outcome: Content of Drawing Page will be inserted into TechDraw Page as
# DrawViewSymbol (ie an SVG symbol)
import FreeCAD
import FreeCADGui
svgHead = (
"<svg\n"
+ ' xmlns="http://www.w3.org/2000/svg" version="1.1"\n'
+ ' xmlns:freecad="https://www.freecad.org/wiki/index.php?title=Svg_Namespace">\n'
)
svgTail = "\n</svg>"
def moveViews():
s = FreeCADGui.Selection.getSelection()
if len(s) != 2:
print("Please select 1 Drawing Page and 1 TechDraw Page")
return
print("First object in selection is a: ", s[0].TypeId)
print("Second object in selection is a: ", s[1].TypeId)
if s[0].isDerivedFrom("Drawing::FeaturePage") and s[1].isDerivedFrom(
"TechDraw::DrawPage"
):
dPage = s[0]
tPage = s[1]
elif s[0].isDerivedFrom("TechDraw::DrawPage") and s[1].isDerivedFrom(
"Drawing::FeaturePage"
):
tPage = s[0]
dPage = s[1]
else:
print("Please select 1 Drawing Page and 1 TechDraw Page")
return
for o in dPage.OutList:
newName = "DraftView" + str(i).zfill(3)
print("moving " + o.Name + " to " + newName)
svg = svgHead + o.ViewResult + svgTail
no = FreeCAD.ActiveDocument.addObject("TechDraw::DrawViewSymbol", newName)
no.Symbol = svg
tPage.addView(no)
print("moveViews moved " + str(len(dPage.OutList)) + " views")
if __name__ == "__main__":
moveViews()

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ***************************************************************************
# * Copyright (c) 2024 Wanderer Fan <wandererfan@gmail.com> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * This program 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 program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
#
# updates any leader lines in the current document from pre-v0.22 coordinates
# to v0.22+ coordinates.
# usage: open the document to be converted in FreeCAD then run this macro and
# save the result.
import TechDraw
RezFactor = 10.0
for obj in FreeCAD.ActiveDocument.Objects:
print("obj: {}".format(obj.Name))
if obj.isDerivedFrom("TechDraw::DrawLeaderLine"):
pointsAll = obj.WayPoints
newPoints = list()
for point in pointsAll:
point = point / RezFactor
newPoints.append(point)
obj.WayPoints = newPoints
print("conversion complete")

View File

@@ -1262,7 +1262,7 @@ void execCosmeticCircle(Gui::Command* cmd)
}
Gui::Control().showDialog(new TaskDlgCosmeticCircle(baseFeat,
points.front(),
points,
centerIs3d));
}

View File

@@ -49,6 +49,7 @@
# include <Mod/TechDraw/App/DrawUtil.h>
# include <Mod/TechDraw/App/DrawViewPart.h>
# include <Mod/TechDraw/App/Preferences.h>
# include <Mod/TechDraw/App/LineGroup.h>
#include "DlgTemplateField.h"
#include "DrawGuiUtil.h"
@@ -1447,14 +1448,13 @@ std::vector<DrawViewDimension*> TechDrawGui::makeObliqueChainDimension(std::vect
Base::Vector3d delta = DrawUtil::getTrianglePoint(pMaster, dirMaster, origin);
float dimDistance = activeDimAttributes.getCascadeSpacing();
delta = delta.Normalize() * dimDistance;
double scale = objFeat->getScale();
for (dimVertex oldVertex : allVertexes) {
for (dimVertex& oldVertex : allVertexes) {
Base::Vector3d nextPoint = DrawUtil::getTrianglePoint(pMaster, dirMaster, oldVertex.point);
nextPoint.y = -nextPoint.y;
oldVertex.point.y = -oldVertex.point.y;
// nextPoint.y = -nextPoint.y;
// oldVertex.point.y = -oldVertex.point.y;
if ((oldVertex.point - nextPoint).Length() > 0.01) {
Base::Vector3d cvPoint = CosmeticVertex::makeCanonicalPoint(objFeat, nextPoint);
std::string vertTag = objFeat->addCosmeticVertex(cvPoint);
Base::Vector3d cvPoint = CosmeticVertex::makeCanonicalPointInverted(objFeat, nextPoint);
std::string vertTag = objFeat->addCosmeticVertex(cvPoint, false);
int vertNumber = objFeat->add1CVToGV(vertTag);
std::stringstream ss;
ss << "Vertex" << vertNumber;
@@ -1462,12 +1462,13 @@ std::vector<DrawViewDimension*> TechDrawGui::makeObliqueChainDimension(std::vect
newVertex.name = ss.str();
newVertex.point = nextPoint;
carrierVertexes.push_back(newVertex);
std::string edgeTag = objFeat->addCosmeticEdge(oldVertex.point / scale, nextPoint / scale);
Base::Vector3d oldCanon = CosmeticVertex::makeCanonicalPointInverted(objFeat, oldVertex.point);
std::string edgeTag = objFeat->addCosmeticEdge(oldCanon, cvPoint);
auto edge = objFeat->getCosmeticEdge(edgeTag);
edge->m_format.m_style = 1;
edge->m_format.m_lineNumber = 1;
edge->m_format.m_weight = 0.15;
edge->m_format.m_color = App::Color(0.0f, 0.0f, 0.0f);
edge->m_format.setStyle(1);
edge->m_format.setLineNumber(1);
edge->m_format.setWidth(TechDraw::LineGroup::getDefaultWidth("Thin"));
edge->m_format.setColor(App::Color(0.0f, 0.0f, 0.0f));
}
else
carrierVertexes.push_back(oldVertex);
@@ -1786,7 +1787,7 @@ bool CmdTechDrawExtensionCreateVertCoordDimension::isActive()
void execCreateObliqueCoordDimension(Gui::Command* cmd) {
//create oblique coordinate dimensions
std::vector<Gui::SelectionObject> selection;
TechDraw::DrawViewPart* objFeat;
TechDraw::DrawViewPart* objFeat{nullptr};
if (!_checkSelObjAndSubs(cmd, selection, objFeat, QT_TRANSLATE_NOOP("QObject","TechDraw Create Oblique Coord Dimension"))) {
return;
}
@@ -1832,14 +1833,11 @@ std::vector<DrawViewDimension*> TechDrawGui::makeObliqueCoordDimension(std::vect
Base::Vector3d delta = DrawUtil::getTrianglePoint(pMaster, dirMaster, origin);
float dimDistance = activeDimAttributes.getCascadeSpacing();
delta = delta.Normalize() * dimDistance;
double scale = objFeat->getScale();
for (dimVertex oldVertex : allVertexes) {
for (dimVertex& oldVertex : allVertexes) {
Base::Vector3d nextPoint = DrawUtil::getTrianglePoint(pMaster, dirMaster, oldVertex.point);
nextPoint.y = -nextPoint.y;
oldVertex.point.y = -oldVertex.point.y;
if ((oldVertex.point - nextPoint).Length() > 0.01) {
Base::Vector3d cvPoint = CosmeticVertex::makeCanonicalPoint(objFeat, nextPoint);
std::string vertTag = objFeat->addCosmeticVertex(cvPoint);
Base::Vector3d cvPoint = CosmeticVertex::makeCanonicalPointInverted(objFeat, nextPoint);
std::string vertTag = objFeat->addCosmeticVertex(cvPoint, false);
int vertNumber = objFeat->add1CVToGV(vertTag);
std::stringstream ss;
ss << "Vertex" << vertNumber;
@@ -1847,15 +1845,17 @@ std::vector<DrawViewDimension*> TechDrawGui::makeObliqueCoordDimension(std::vect
newVertex.name = ss.str();
newVertex.point = nextPoint;
carrierVertexes.push_back(newVertex);
std::string edgeTag = objFeat->addCosmeticEdge(oldVertex.point / scale, nextPoint / scale);
Base::Vector3d oldCanon = CosmeticVertex::makeCanonicalPointInverted(objFeat, oldVertex.point);
std::string edgeTag = objFeat->addCosmeticEdge(oldCanon, cvPoint);
auto edge = objFeat->getCosmeticEdge(edgeTag);
edge->m_format.m_style = 1;
edge->m_format.m_lineNumber = 1;
edge->m_format.m_weight = 0.15;
edge->m_format.m_color = App::Color(0.0f, 0.0f, 0.0f);
edge->m_format.setStyle(1);
edge->m_format.setLineNumber(1);
edge->m_format.setWidth(TechDraw::LineGroup::getDefaultWidth("Thin"));
edge->m_format.setColor(App::Color(0.0, 0.0, 0.0));
}
else
else {
carrierVertexes.push_back(oldVertex);
}
}
dimVertex firstVertex = carrierVertexes[0];
dimVertex secondVertex = carrierVertexes[1];
@@ -2301,7 +2301,6 @@ void CmdTechDrawExtensionCreateLengthArc::activated(int iMsg) {
}
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create Arc Length Dim"));
ReferenceEntry ref(objFeat, selection[0].getSubNames()[0]);
TechDraw::DrawViewDimension* dim = makeArcLengthDimension(ref);

View File

@@ -24,7 +24,6 @@
#ifndef _PreComp_
#include <QApplication>
#include <QMessageBox>
#include <sstream>
#include <BRepGProp.hxx>
#include <GProp_GProps.hxx>
#include <BRepAdaptor_Curve.hxx>
@@ -58,6 +57,9 @@
#include <Mod/TechDraw/App/DrawViewPart.h>
#include <Mod/TechDraw/App/DrawViewSection.h>
#include <Mod/TechDraw/App/Preferences.h>
#include <Mod/TechDraw/App/LineFormat.h>
#include <Mod/TechDraw/App/LineGenerator.h>
#include <Mod/TechDraw/App/LineGroup.h>
#include "DrawGuiUtil.h"
#include "QGSPage.h"
@@ -79,18 +81,18 @@ namespace TechDrawGui
//internal helper functions
TechDraw::LineFormat& _getActiveLineAttributes();
Base::Vector3d _circleCenter(Base::Vector3d p1, Base::Vector3d p2, Base::Vector3d p3);
void _createThreadCircle(std::string Name, TechDraw::DrawViewPart* objFeat, float factor);
void _createThreadLines(std::vector<std::string> SubNames, TechDraw::DrawViewPart* objFeat,
void _createThreadCircle(const std::string Name, TechDraw::DrawViewPart* objFeat, float factor);
void _createThreadLines(const std::vector<std::string>& SubNames, TechDraw::DrawViewPart* objFeat,
float factor);
void _setLineAttributes(TechDraw::CosmeticEdge* cosEdge);
void _setLineAttributes(TechDraw::CenterLine* cosEdge);
void _setLineAttributes(TechDraw::CosmeticEdge* cosEdge, int style, float weight, App::Color color);
void _setLineAttributes(TechDraw::CenterLine* cosEdge, int style, float weight, App::Color color);
float _getAngle(Base::Vector3d center, Base::Vector3d point);
std::vector<Base::Vector3d> _getVertexPoints(std::vector<std::string> SubNames,
double _getAngle(Base::Vector3d center, Base::Vector3d point);
std::vector<Base::Vector3d> _getVertexPoints(const std::vector<std::string>& SubNames,
TechDraw::DrawViewPart* objFeat);
bool _checkSel(Gui::Command* cmd, std::vector<Gui::SelectionObject>& selection,
TechDraw::DrawViewPart*& objFeat, std::string message);
TechDraw::DrawViewPart*& objFeat, const std::string& message);
std::string _createBalloon(Gui::Command* cmd, TechDraw::DrawViewPart* objFeat);
//===========================================================================
@@ -101,9 +103,10 @@ void execHoleCircle(Gui::Command* cmd)
{
//create centerlines of a hole/bolt circle
std::vector<Gui::SelectionObject> selection;
TechDraw::DrawViewPart* objFeat;
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Hole Circle")))
TechDraw::DrawViewPart* objFeat{nullptr};
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Hole Circle"))) {
return;
}
const std::vector<std::string> SubNames = selection[0].getSubNames();
std::vector<TechDraw::CirclePtr> Circles;
for (const std::string& Name : SubNames) {
@@ -129,9 +132,7 @@ void execHoleCircle(Gui::Command* cmd)
_circleCenter(Circles[0]->center, Circles[1]->center, Circles[2]->center);
double bigRadius = (Circles[0]->center - bigCenter).Length();
// now convert the center & radius to canonical form
bigCenter = DU::invertY(bigCenter);
bigCenter = CosmeticVertex::makeCanonicalPoint(objFeat, bigCenter);
bigCenter = DU::invertY(bigCenter);
bigCenter = CosmeticVertex::makeCanonicalPointInverted(objFeat, bigCenter);
bigRadius = bigRadius / objFeat->getScale();
TechDraw::BaseGeomPtr bigCircle =
std::make_shared<TechDraw::Circle>(bigCenter, bigRadius);
@@ -143,18 +144,14 @@ void execHoleCircle(Gui::Command* cmd)
constexpr double ExtendFactor{1.1};
for (const TechDraw::CirclePtr& oneCircle : Circles) {
// convert the center to canonical form
Base::Vector3d oneCircleCenter = DU::invertY(oneCircle->center);
oneCircleCenter = CosmeticVertex::makeCanonicalPoint(objFeat, oneCircleCenter);
oneCircleCenter = DU::invertY(oneCircleCenter);
Base::Vector3d oneCircleCenter = CosmeticVertex::makeCanonicalPointInverted(objFeat, oneCircle->center);
// oneCircle->radius is scaled.
float oneRadius = oneCircle->radius / objFeat->getScale();
double oneRadius = oneCircle->radius / objFeat->getScale();
// what is magic number 2 (now ExtendFactor)? just a fudge factor to extend the line beyond the bolt
// hole circle? should it be a function of hole diameter? maybe 110% of oneRadius?
Base::Vector3d delta = (oneCircleCenter - bigCenter).Normalize() * (oneRadius * ExtendFactor);
Base::Vector3d startPt = oneCircleCenter + delta;
Base::Vector3d endPt = oneCircleCenter - delta;
startPt = DU::invertY(startPt);
endPt = DU::invertY(endPt);
std::string oneLineTag = objFeat->addCosmeticEdge(startPt, endPt);
TechDraw::CosmeticEdge* ceLine = objFeat->getCosmeticEdge(oneLineTag);
_setLineAttributes(ceLine);
@@ -205,9 +202,10 @@ void execCircleCenterLines(Gui::Command* cmd)
{
// create circle centerlines
std::vector<Gui::SelectionObject> selection;
TechDraw::DrawViewPart* objFeat;
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Circle Centerlines")))
TechDraw::DrawViewPart* objFeat{nullptr};
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Circle Centerlines"))) {
return;
}
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Circle Centerlines"));
const std::vector<std::string> SubNames = selection[0].getSubNames();
for (const std::string& Name : SubNames) {
@@ -217,10 +215,8 @@ void execCircleCenterLines(Gui::Command* cmd)
if (GeoType == "Edge") {
if (geom->getGeomType() == TechDraw::CIRCLE || geom->getGeomType() == TechDraw::ARCOFCIRCLE) {
TechDraw::CirclePtr cgen = std::static_pointer_cast<TechDraw::Circle>(geom);
// center is a scaled and rotated point
Base::Vector3d center = cgen->center;
center.y = -center.y;
center = CosmeticVertex::makeCanonicalPoint(objFeat, center);
// cgen->center is a scaled, rotated and inverted point
Base::Vector3d center = CosmeticVertex::makeCanonicalPointInverted(objFeat, cgen->center);
double radius = cgen->radius / objFeat->getScale();
// right, left, top, bottom are formed from a canonical point (center)
// so they do not need to be changed to canonical form.
@@ -302,7 +298,7 @@ void CmdTechDrawExtensionCircleCenterLinesGroup::activated(int iMsg)
return;
}
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
auto pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
pcAction->setIcon(pcAction->actions().at(iMsg)->icon());
switch (iMsg) {
case 0://circle centerlines
@@ -345,12 +341,13 @@ void CmdTechDrawExtensionCircleCenterLinesGroup::languageChange()
{
Command::languageChange();
if (!_pcAction)
if (!_pcAction) {
return;
}
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
QList<QAction*> a = pcAction->actions();
QList<QAction*> action = pcAction->actions();
QAction* arc1 = a[0];
QAction* arc1 = action[0];
arc1->setText(
QApplication::translate("CmdTechDrawExtensionCircleCenterLines", "Add Circle Centerlines"));
arc1->setToolTip(QApplication::translate("CmdTechDrawExtensionCircleCenterLines",
@@ -359,7 +356,7 @@ void CmdTechDrawExtensionCircleCenterLinesGroup::languageChange()
- Select one or more circles or arcs<br>\
- Click this tool"));
arc1->setStatusTip(arc1->text());
QAction* arc2 = a[1];
QAction* arc2 = action[1];
arc2->setText(
QApplication::translate("CmdTechDrawExtensionHoleCircle", "Add Bolt Circle Centerlines"));
arc2->setToolTip(QApplication::translate("CmdTechDrawExtensionHoleCircle",
@@ -383,15 +380,17 @@ bool CmdTechDrawExtensionCircleCenterLinesGroup::isActive()
void execThreadHoleSide(Gui::Command* cmd)
{
constexpr double ThreadFactor{1.176};
// add cosmetic thread to side view of hole
std::vector<Gui::SelectionObject> selection;
TechDraw::DrawViewPart* objFeat;
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Thread Hole Side")))
TechDraw::DrawViewPart* objFeat{nullptr};
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Thread Hole Side"))) {
return;
}
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cosmetic Thread Hole Side"));
const std::vector<std::string> SubNames = selection[0].getSubNames();
if (SubNames.size() >= 2) {
_createThreadLines(SubNames, objFeat, 1.176f);
_createThreadLines(SubNames, objFeat, ThreadFactor);
}
cmd->getSelection().clearSelection();
objFeat->refreshCEGeoms();
@@ -435,15 +434,17 @@ bool CmdTechDrawExtensionThreadHoleSide::isActive()
void execThreadBoltSide(Gui::Command* cmd)
{
constexpr double ThreadFactor{0.85};
// add cosmetic thread to side view of bolt
std::vector<Gui::SelectionObject> selection;
TechDraw::DrawViewPart* objFeat;
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Thread Bolt Side")))
TechDraw::DrawViewPart* objFeat{nullptr};
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Thread Bolt Side"))) {
return;
}
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cosmetic Thread Bolt Side"));
const std::vector<std::string> SubNames = selection[0].getSubNames();
if (SubNames.size() >= 2) {
_createThreadLines(SubNames, objFeat, 0.85f);
_createThreadLines(SubNames, objFeat, ThreadFactor);
}
cmd->getSelection().clearSelection();
objFeat->refreshCEGeoms();
@@ -487,15 +488,17 @@ bool CmdTechDrawExtensionThreadBoltSide::isActive()
void execThreadHoleBottom(Gui::Command* cmd)
{
constexpr double ThreadFactor{1.177}; // factor above is 1.176. should they be the same?
// add cosmetic thread to bottom view of hole
std::vector<Gui::SelectionObject> selection;
TechDraw::DrawViewPart* objFeat;
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Thread Hole Bottom")))
TechDraw::DrawViewPart* objFeat{nullptr};
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Thread Hole Bottom"))) {
return;
}
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cosmetic Thread Hole Bottom"));
const std::vector<std::string> SubNames = selection[0].getSubNames();
for (const std::string& Name : SubNames) {
_createThreadCircle(Name, objFeat, 1.177f);
_createThreadCircle(Name, objFeat, ThreadFactor);
}
cmd->getSelection().clearSelection();
objFeat->refreshCEGeoms();
@@ -539,15 +542,17 @@ bool CmdTechDrawExtensionThreadHoleBottom::isActive()
void execThreadBoltBottom(Gui::Command* cmd)
{
constexpr double ThreadFactor{0.85};
// add cosmetic thread to bottom view of bolt
std::vector<Gui::SelectionObject> selection;
TechDraw::DrawViewPart* objFeat;
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Thread Bolt Bottom")))
TechDraw::DrawViewPart* objFeat{nullptr};
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Thread Bolt Bottom"))) {
return;
}
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cosmetic Thread Bolt Bottom"));
const std::vector<std::string> SubNames = selection[0].getSubNames();
for (const std::string& Name : SubNames) {
_createThreadCircle(Name, objFeat, 0.85f);
_createThreadCircle(Name, objFeat, ThreadFactor);
}
cmd->getSelection().clearSelection();
objFeat->refreshCEGeoms();
@@ -616,7 +621,7 @@ void CmdTechDrawExtensionThreadsGroup::activated(int iMsg)
return;
}
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
auto pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
pcAction->setIcon(pcAction->actions().at(iMsg)->icon());
switch (iMsg) {
case 0://thread hole side view
@@ -673,12 +678,13 @@ void CmdTechDrawExtensionThreadsGroup::languageChange()
{
Command::languageChange();
if (!_pcAction)
if (!_pcAction) {
return;
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
QList<QAction*> a = pcAction->actions();
}
auto pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
QList<QAction*> action = pcAction->actions();
QAction* arc1 = a[0];
QAction* arc1 = action[0];
arc1->setText(QApplication::translate("CmdTechDrawExtensionThreadHoleSide",
"Add Cosmetic Thread Hole Side View"));
arc1->setToolTip(QApplication::translate("CmdTechDrawExtensionThreadHoleSide",
@@ -687,7 +693,7 @@ void CmdTechDrawExtensionThreadsGroup::languageChange()
- Select two parallel lines<br>\
- Click this tool"));
arc1->setStatusTip(arc1->text());
QAction* arc2 = a[1];
QAction* arc2 = action[1];
arc2->setText(QApplication::translate("CmdTechDrawExtensionThreadHoleBottom",
"Add Cosmetic Thread Hole Bottom View"));
arc2->setToolTip(
@@ -697,7 +703,7 @@ void CmdTechDrawExtensionThreadsGroup::languageChange()
- Select one or more circles<br>\
- Click this tool"));
arc2->setStatusTip(arc2->text());
QAction* arc3 = a[2];
QAction* arc3 = action[2];
arc3->setText(QApplication::translate("CmdTechDrawExtensionThreadBoltSide",
"Add Cosmetic Thread Bolt Side View"));
arc3->setToolTip(
@@ -707,7 +713,7 @@ void CmdTechDrawExtensionThreadsGroup::languageChange()
- Select two parallel lines<br>\
- Click this tool"));
arc3->setStatusTip(arc3->text());
QAction* arc4 = a[3];
QAction* arc4 = action[3];
arc4->setText(QApplication::translate("CmdTechDrawExtensionThreadBoltBottom",
"Add Cosmetic Thread Bolt Bottom View"));
arc4->setToolTip(QApplication::translate(
@@ -751,7 +757,7 @@ CmdTechDrawExtensionSelectLineAttributes::CmdTechDrawExtensionSelectLineAttribut
void CmdTechDrawExtensionSelectLineAttributes::activated(int iMsg)
{
Q_UNUSED(iMsg);
Gui::Control().showDialog(new TaskDlgSelectLineAttributes(&_getActiveLineAttributes()));
Gui::Control().showDialog(new TaskDlgSelectLineAttributes());
}
bool CmdTechDrawExtensionSelectLineAttributes::isActive()
@@ -787,9 +793,10 @@ void CmdTechDrawExtensionChangeLineAttributes::activated(int iMsg)
// change attributes (type, width, color) of a cosmetic or centerline
Q_UNUSED(iMsg);
std::vector<Gui::SelectionObject> selection;
TechDraw::DrawViewPart* objFeat;
if (!_checkSel(this, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Change Line Attributes")))
TechDraw::DrawViewPart* objFeat{nullptr};
if (!_checkSel(this, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Change Line Attributes"))) {
return;
}
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Change Line Attributes"));
const std::vector<std::string> subNames = selection[0].getSubNames();
for (const std::string& name : subNames) {
@@ -847,9 +854,10 @@ void CmdTechDrawExtensionVertexAtIntersection::activated(int iMsg)
Q_UNUSED(iMsg);
//Base::Console().Message("VertexAtIntersection started\n");
std::vector<Gui::SelectionObject> selection;
TechDraw::DrawViewPart* objFeat;
if (!_checkSel(this, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Cosmetic Intersection Vertex(es)")))
TechDraw::DrawViewPart* objFeat{nullptr};
if (!_checkSel(this, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Cosmetic Intersection Vertex(es)"))) {
return;
}
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cosmetic Intersection Vertex(es)"));
const std::vector<std::string> SubNames = selection[0].getSubNames();
if (SubNames.size() >= 2) {
@@ -861,14 +869,11 @@ void CmdTechDrawExtensionVertexAtIntersection::activated(int iMsg)
int GeoId2 = TechDraw::DrawUtil::getIndexFromName(SubNames[1]);
TechDraw::BaseGeomPtr geom2 = objFeat->getGeomByIndex(GeoId2);
// double scale = objFeat->getScale();
std::vector<Base::Vector3d> interPoints = geom1->intersection(geom2);
for (auto pt : interPoints) {
// std::string ptId = objFeat->addCosmeticVertex(pt/scale);
// objFeat->add1CVToGV(ptId);
// invert the point so the math works correctly
Base::Vector3d temp = CosmeticVertex::makeCanonicalPoint(objFeat, pt);
objFeat->addCosmeticVertex(temp);
// geometry points are inverted
Base::Vector3d temp = CosmeticVertex::makeCanonicalPointInverted(objFeat, pt);
objFeat->addCosmeticVertex(temp, false);
}
}
}
@@ -889,23 +894,34 @@ bool CmdTechDrawExtensionVertexAtIntersection::isActive()
// TechDraw_ExtensionDrawCosmArc
//===========================================================================
//! adds an anti-clockwise arc based on a center point, a radius/start angle point and an end angle
//! point. Selection order is significant - center, start end.
void execDrawCosmArc(Gui::Command* cmd)
{
//draw a cosmetic arc of circle
std::vector<Gui::SelectionObject> selection;
TechDraw::DrawViewPart* objFeat;
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Cosmetic Arc")))
TechDraw::DrawViewPart* objFeat{nullptr};
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Cosmetic Arc"))) {
return;
}
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cosmetic Arc"));
const std::vector<std::string> SubNames = selection[0].getSubNames();
std::vector<Base::Vector3d> vertexPoints;
vertexPoints = _getVertexPoints(SubNames, objFeat);
if (vertexPoints.size() >= 3) {
float arcRadius = (vertexPoints[1] - vertexPoints[0]).Length();
float angle1 = _getAngle(vertexPoints[0], vertexPoints[1]);
float angle2 = _getAngle(vertexPoints[0], vertexPoints[2]);
// vertexPoints come from stored geometry, so are centered, scaled, rotated and inverted (CSRIz).
// because the points are inverted, the start and end angles will be mirrored unless we invert the points
// before calculating the angle.
Base::Vector3d center = CosmeticVertex::makeCanonicalPoint(objFeat, DU::invertY(vertexPoints[0]));
Base::Vector3d end1 = CosmeticVertex::makeCanonicalPoint(objFeat, DU::invertY(vertexPoints[1]));
Base::Vector3d end2 = CosmeticVertex::makeCanonicalPoint(objFeat, DU::invertY(vertexPoints[2]));
double arcRadius = (end1 - center).Length();
double angle1 = _getAngle(center, end1);
double angle2 = _getAngle(center, end2);
TechDraw::BaseGeomPtr baseGeo = std::make_shared<TechDraw::AOC>(
vertexPoints[0], arcRadius, angle1, angle2);
center, arcRadius, angle1, angle2);
TechDraw::AOCPtr aoc = std::static_pointer_cast<TechDraw::AOC>(baseGeo);
// having done our calculations in sensible coordinates, we convert to inverted coords
std::string arcTag = objFeat->addCosmeticEdge(baseGeo->inverted());
TechDraw::CosmeticEdge* arcEdge = objFeat->getCosmeticEdge(arcTag);
_setLineAttributes(arcEdge);
@@ -957,18 +973,20 @@ void execDrawCosmCircle(Gui::Command* cmd)
{
//draw a cosmetic circle
std::vector<Gui::SelectionObject> selection;
TechDraw::DrawViewPart* objFeat;
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Cosmetic Circle")))
TechDraw::DrawViewPart* objFeat{nullptr};
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Cosmetic Circle"))) {
return;
}
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cosmetic Circle"));
const std::vector<std::string> SubNames = selection[0].getSubNames();
std::vector<Base::Vector3d> vertexPoints;
vertexPoints = _getVertexPoints(SubNames, objFeat);
if (vertexPoints.size() >= 2) {
float circleRadius = (vertexPoints[1] - vertexPoints[0]).Length();
double circleRadius = (vertexPoints[1] - vertexPoints[0]).Length() / objFeat->getScale();
auto center = CosmeticVertex::makeCanonicalPointInverted(objFeat, vertexPoints[0]);
TechDraw::BaseGeomPtr baseGeo =
std::make_shared<TechDraw::Circle>(vertexPoints[0], circleRadius);
std::string circleTag = objFeat->addCosmeticEdge(baseGeo->inverted());
std::make_shared<TechDraw::Circle>(center, circleRadius);
std::string circleTag = objFeat->addCosmeticEdge(baseGeo);
TechDraw::CosmeticEdge* circleEdge = objFeat->getCosmeticEdge(circleTag);
_setLineAttributes(circleEdge);
objFeat->refreshCEGeoms();
@@ -1018,9 +1036,10 @@ void execDrawCosmCircle3Points(Gui::Command* cmd)
{
//draw a cosmetic circle through 3 points
std::vector<Gui::SelectionObject> selection;
TechDraw::DrawViewPart* objFeat;
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Cosmetic Circle 3 Points")))
TechDraw::DrawViewPart* objFeat{nullptr};
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Cosmetic Circle 3 Points"))) {
return;
}
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cosmetic Circle 3 Points"));
const std::vector<std::string> SubNames = selection[0].getSubNames();
std::vector<Base::Vector3d> vertexPoints;
@@ -1029,10 +1048,11 @@ void execDrawCosmCircle3Points(Gui::Command* cmd)
Base::Vector3d circleCenter = _circleCenter(vertexPoints[0],
vertexPoints[1],
vertexPoints[2]);
float circleRadius = (vertexPoints[0] - circleCenter).Length();
double circleRadius = (vertexPoints[0] - circleCenter).Length() / objFeat->getScale();
circleCenter = CosmeticVertex::makeCanonicalPointInverted(objFeat, circleCenter);
TechDraw::BaseGeomPtr theCircle =
std::make_shared<TechDraw::Circle>(circleCenter, circleRadius);
std::string circleTag = objFeat->addCosmeticEdge(theCircle->inverted());
std::string circleTag = objFeat->addCosmeticEdge(theCircle);
TechDraw::CosmeticEdge* circleEdge = objFeat->getCosmeticEdge(circleTag);
_setLineAttributes(circleEdge);
objFeat->refreshCEGeoms();
@@ -1104,7 +1124,7 @@ void CmdTechDrawExtensionDrawCirclesGroup::activated(int iMsg)
return;
}
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
auto pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
pcAction->setIcon(pcAction->actions().at(iMsg)->icon());
switch (iMsg) {
case 0://draw cosmetic circle
@@ -1154,12 +1174,13 @@ void CmdTechDrawExtensionDrawCirclesGroup::languageChange()
{
Command::languageChange();
if (!_pcAction)
if (!_pcAction) {
return;
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
QList<QAction*> a = pcAction->actions();
}
auto pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
QList<QAction*> action = pcAction->actions();
QAction* arc1 = a[0];
QAction* arc1 = action[0];
arc1->setText(
QApplication::translate("CmdTechDrawExtensionDrawCosmCircle", "Add Cosmetic Circle"));
arc1->setToolTip(QApplication::translate("CmdTechDrawExtensionDrawCosmCircle",
@@ -1169,7 +1190,7 @@ void CmdTechDrawExtensionDrawCirclesGroup::languageChange()
- Select vertex 2 (radius)<br>\
- Click this tool"));
arc1->setStatusTip(arc1->text());
QAction* arc2 = a[1];
QAction* arc2 = action[1];
arc2->setText(QApplication::translate("CmdTechDrawExtensionDrawCosmArc", "Add Cosmetic Arc"));
arc2->setToolTip(
QApplication::translate("CmdTechDrawExtensionDrawCosmArc",
@@ -1180,7 +1201,7 @@ void CmdTechDrawExtensionDrawCirclesGroup::languageChange()
- Select vertex 3 (end angle)<br>\
- Click this tool"));
arc2->setStatusTip(arc2->text());
QAction* arc3 = a[2];
QAction* arc3 = action[2];
arc3->setText(QApplication::translate("CmdTechDrawExtensionDrawCosmCircle3Points",
"Add Cosmetic Circle 3 Points"));
arc3->setToolTip(QApplication::translate("CmdTechDrawExtensionDrawCosmCircle3Points",
@@ -1206,16 +1227,17 @@ void execLineParallelPerpendicular(Gui::Command* cmd, bool isParallel)
{
// create a line parallel or perpendicular to another line
std::vector<Gui::SelectionObject> selection;
TechDraw::DrawViewPart* objFeat;
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Cosmetic Line Parallel/Perpendicular")))
TechDraw::DrawViewPart* objFeat{nullptr};
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Cosmetic Line Parallel/Perpendicular"))) {
return;
}
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cosmetic Line Parallel/Perpendicular"));
const std::vector<std::string> SubNames = selection[0].getSubNames();
if (SubNames.size() >= 2) {
std::string GeoType1 = TechDraw::DrawUtil::getGeomTypeFromName(SubNames[0]);
std::string GeoType2 = TechDraw::DrawUtil::getGeomTypeFromName(SubNames[1]);
int EdgeId;
int VertId;
int EdgeId{-1};
int VertId{-1};
if (GeoType1 == "Edge" && GeoType2 == "Vertex") {
EdgeId = TechDraw::DrawUtil::getIndexFromName(SubNames[0]);
VertId = TechDraw::DrawUtil::getIndexFromName(SubNames[1]);
@@ -1228,10 +1250,15 @@ void execLineParallelPerpendicular(Gui::Command* cmd, bool isParallel)
}
TechDraw::BaseGeomPtr geom1 = objFeat->getGeomByIndex(EdgeId);
TechDraw::GenericPtr lineGen = std::static_pointer_cast<TechDraw::Generic>(geom1);
// ends are scaled and rotated
Base::Vector3d lineStart = lineGen->points.at(0);
lineStart = CosmeticVertex::makeCanonicalPointInverted(objFeat, lineStart);
Base::Vector3d lineEnd = lineGen->points.at(1);
lineEnd = CosmeticVertex::makeCanonicalPointInverted(objFeat, lineEnd);
TechDraw::VertexPtr vert = objFeat->getProjVertexByIndex(VertId);
Base::Vector3d vertexPoint(vert->point().x, vert->point().y, 0.0);
vertexPoint = CosmeticVertex::makeCanonicalPointInverted(objFeat, vertexPoint);
Base::Vector3d halfVector = (lineEnd - lineStart) / 2.0;
if (!isParallel) {
float dummy = halfVector.x;
@@ -1240,9 +1267,7 @@ void execLineParallelPerpendicular(Gui::Command* cmd, bool isParallel)
}
Base::Vector3d startPoint = vertexPoint + halfVector;
Base::Vector3d endPoint = vertexPoint - halfVector;
startPoint.y = -startPoint.y;
endPoint.y = -endPoint.y;
TechDraw::BaseGeomPtr cLine = CosmeticEdge::makeCanonicalLine(objFeat, startPoint, endPoint);
TechDraw::BaseGeomPtr cLine = CosmeticEdge::makeLineFromCanonicalPoints(startPoint, endPoint);
std::string lineTag = objFeat->addCosmeticEdge(cLine);
TechDraw::CosmeticEdge* lineEdge = objFeat->getCosmeticEdge(lineTag);
_setLineAttributes(lineEdge);
@@ -1348,7 +1373,7 @@ void CmdTechDrawExtensionLinePPGroup::activated(int iMsg)
return;
}
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
auto pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
pcAction->setIcon(pcAction->actions().at(iMsg)->icon());
switch (iMsg) {
case 0://create parallel line
@@ -1391,12 +1416,13 @@ void CmdTechDrawExtensionLinePPGroup::languageChange()
{
Command::languageChange();
if (!_pcAction)
if (!_pcAction) {
return;
}
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
QList<QAction*> a = pcAction->actions();
QList<QAction*> action = pcAction->actions();
QAction* arc1 = a[0];
QAction* arc1 = action[0];
arc1->setText(
QApplication::translate("CmdTechDrawExtensionLineParallel", "Add Cosmetic Parallel Line"));
arc1->setToolTip(
@@ -1406,7 +1432,7 @@ void CmdTechDrawExtensionLinePPGroup::languageChange()
- Select a vertex<br>\
- Click this tool"));
arc1->setStatusTip(arc1->text());
QAction* arc2 = a[1];
QAction* arc2 = action[1];
arc2->setText(QApplication::translate("CmdTechDrawExtensionLinePerpendicular",
"Add Cosmetic Perpendicular Line"));
arc2->setToolTip(QApplication::translate(
@@ -1450,9 +1476,10 @@ void CmdTechDrawExtensionLockUnlockView::activated(int iMsg)
// lock/unlock a selected view
Q_UNUSED(iMsg);
std::vector<Gui::SelectionObject> selection;
TechDraw::DrawViewPart* objFeat;
if (!_checkSel(this, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Lock/Unlock View")))
TechDraw::DrawViewPart* objFeat{nullptr};
if (!_checkSel(this, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Lock/Unlock View"))) {
return;
}
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Lock/Unlock View"));
if (objFeat->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) {
bool lockPosition = objFeat->LockPosition.getValue();
@@ -1477,9 +1504,10 @@ void execExtendShortenLine(Gui::Command* cmd, bool extend)
{
// extend or shorten a cosmetic line or a centerline
std::vector<Gui::SelectionObject> selection;
TechDraw::DrawViewPart* objFeat;
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Extend/Shorten Line")))
TechDraw::DrawViewPart* objFeat{nullptr};
if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Extend/Shorten Line"))) {
return;
}
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Extend/Shorten Line"));
const std::vector<std::string> subNames = selection[0].getSubNames();
if (!subNames.empty()) {
@@ -1490,33 +1518,29 @@ void execExtendShortenLine(Gui::Command* cmd, bool extend)
TechDraw::BaseGeomPtr baseGeo = objFeat->getGeomByIndex(num);
if (baseGeo) {
if (baseGeo->getGeomType() == TechDraw::GENERIC) {
// start and end points are scaled and rotated. invert the points
// so the canonicalPoint math works correctly.
Base::Vector3d P0 = DU::invertY(baseGeo->getStartPoint());
Base::Vector3d P1 = DU::invertY(baseGeo->getEndPoint());
// start and end points are geometry points and are scaled, rotated and inverted
// convert start and end to unscaled, unrotated.
P0 = CosmeticVertex::makeCanonicalPoint(objFeat, P0);
P1 = CosmeticVertex::makeCanonicalPoint(objFeat, P1);
// put the points back into weird Qt coord system.
P0 = DU::invertY(P0);
P1 = DU::invertY(P1);
Base::Vector3d P0 = CosmeticVertex::makeCanonicalPointInverted(objFeat, baseGeo->getStartPoint());
Base::Vector3d P1 = CosmeticVertex::makeCanonicalPointInverted(objFeat, baseGeo->getEndPoint());
bool isCenterLine = false;
TechDraw::CenterLine* centerEdge = nullptr;
if (baseGeo->getCosmetic()) {
std::string uniTag = baseGeo->getCosmeticTag();
int oldStyle = 1;
float oldWeight = 1.0f;
float oldWeight = 1.0;
App::Color oldColor;
std::vector<std::string> toDelete;
toDelete.push_back(uniTag);
if (baseGeo->source() == 1) {
// cosmetic edge
auto cosEdge = objFeat->getCosmeticEdge(uniTag);
oldStyle = cosEdge->m_format.m_lineNumber;
oldWeight = cosEdge->m_format.m_weight;
oldColor = cosEdge->m_format.m_color;
oldStyle = cosEdge->m_format.getLineNumber();
oldWeight = cosEdge->m_format.getWidth();
oldColor = cosEdge->m_format.getColor();
objFeat->removeCosmeticEdge(toDelete);
}
else if (baseGeo->source() == 2) {
// centerline
isCenterLine = true;
centerEdge = objFeat->getCenterLine(uniTag);
}
@@ -1524,17 +1548,23 @@ void execExtendShortenLine(Gui::Command* cmd, bool extend)
Base::Vector3d delta = direction * activeDimAttributes.getLineStretch();
Base::Vector3d startPt, endPt;
if (extend) {
// make it longer
startPt = P0 - delta;
endPt = P1 + delta;
}
else {
// make it shorter
startPt = P0 + delta;
endPt = P1 - delta;
}
startPt.y = -startPt.y;
endPt.y = -endPt.y;
// startPt.y = -startPt.y;
// endPt.y = -endPt.y;
if (isCenterLine) {
centerEdge->m_extendBy += activeDimAttributes.getLineStretch();
if (extend) {
centerEdge->m_extendBy += activeDimAttributes.getLineStretch();
} else {
centerEdge->m_extendBy -= activeDimAttributes.getLineStretch();
}
objFeat->refreshCLGeoms();
}
else {
@@ -1649,7 +1679,7 @@ void CmdTechDrawExtendShortenLineGroup::activated(int iMsg)
return;
}
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
auto pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
pcAction->setIcon(pcAction->actions().at(iMsg)->icon());
switch (iMsg) {
case 0://extend a line
@@ -1692,12 +1722,13 @@ void CmdTechDrawExtendShortenLineGroup::languageChange()
{
Command::languageChange();
if (!_pcAction)
if (!_pcAction) {
return;
}
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
QList<QAction*> a = pcAction->actions();
QList<QAction*> action = pcAction->actions();
QAction* arc1 = a[0];
QAction* arc1 = action[0];
arc1->setText(QApplication::translate("CmdTechDrawExtensionExtendLine", "Extend Line"));
arc1->setToolTip(QApplication::translate(
"CmdTechDrawExtensionExtendLine", "Extend a cosmetic line or centerline at both ends:<br>\
@@ -1705,7 +1736,7 @@ void CmdTechDrawExtendShortenLineGroup::languageChange()
- Select a single line<br>\
- Click this tool"));
arc1->setStatusTip(arc1->text());
QAction* arc2 = a[1];
QAction* arc2 = action[1];
arc2->setText(QApplication::translate("CmdTechDrawExtensionShortenLine", "Shorten Line"));
arc2->setToolTip(QApplication::translate(
"CmdTechDrawExtensionShortenLine", "Shorten a cosmetic line or centerline at both ends:<br>\
@@ -1746,9 +1777,10 @@ void CmdTechDrawExtensionAreaAnnotation::activated(int iMsg)
{
Q_UNUSED(iMsg);
std::vector<Gui::SelectionObject> selection;
TechDraw::DrawViewPart* objFeat;
if (!_checkSel(this, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw calculate selected area")))
TechDraw::DrawViewPart* objFeat{nullptr};
if (!_checkSel(this, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw calculate selected area"))) {
return;
}
// we must have at least 1 face in the selection
const std::vector<std::string> subNamesAll = selection[0].getSubNames();
@@ -1794,8 +1826,9 @@ void CmdTechDrawExtensionAreaAnnotation::activated(int iMsg)
TechDraw::DrawViewBalloon* balloon = nullptr;
balloon = dynamic_cast<TechDraw::DrawViewBalloon*>(
this->getDocument()->getObject(balloonName.c_str()));
if (!balloon)
if (!balloon) {
throw Base::TypeError("CmdTechDrawNewBalloon - balloon not found\n");
}
// the balloon has been created successfully
// calculate needed variables
@@ -1835,9 +1868,9 @@ void CmdTechDrawExtensionAreaAnnotation::activated(int iMsg)
// view provider successfully found,
// set the attributes in the view tab's fields
viewProvider->Fontsize.setValue(2.0);
viewProvider->LineWidth.setValue(0.75);
viewProvider->LineWidth.setValue(TechDraw::LineGroup::getDefaultWidth("Graphic"));
viewProvider->LineVisible.setValue(false);
viewProvider->Color.setValue(App::Color(1.0f, 0.0f, 0.0f));
viewProvider->Color.setValue(App::Color(1.0, 0.0, 0.0));
}
Gui::Command::commitCommand();
objFeat->touch(true);
@@ -1876,7 +1909,7 @@ void CmdTechDrawExtensionArcLengthAnnotation::activated(int iMsg)
Q_UNUSED(iMsg);
std::vector<Gui::SelectionObject> selection;
TechDraw::DrawViewPart *objFeat;
TechDraw::DrawViewPart *objFeat{nullptr};
if (!_checkSel(this, selection, objFeat, QT_TRANSLATE_NOOP("Command", "TechDraw calculate selected arc length"))) {
return;
}
@@ -1899,10 +1932,9 @@ void CmdTechDrawExtensionArcLengthAnnotation::activated(int iMsg)
// Now we have at least one edge
std::vector<double> lengths(subNames.size());
double totalLength = 0.0;
size_t i;
for (i = 0; i < subNames.size(); ++i) {
lengths[i] = totalLength;
TechDraw::BaseGeomPtr edge = objFeat->getEdge(subNames[i]);
for (size_t iName = 0; iName < subNames.size(); ++iName) {
lengths[iName] = totalLength;
TechDraw::BaseGeomPtr edge = objFeat->getEdge(subNames[iName]);
if (!edge) {
continue;
}
@@ -1911,7 +1943,7 @@ void CmdTechDrawExtensionArcLengthAnnotation::activated(int iMsg)
BRepGProp::LinearProperties(edge->getOCCEdge(), edgeProps);
totalLength += edgeProps.Mass();
lengths[i] = totalLength;
lengths[iName] = totalLength;
}
// We have calculated the length, let's start the command
@@ -1926,16 +1958,16 @@ void CmdTechDrawExtensionArcLengthAnnotation::activated(int iMsg)
// Find the edge halving the selected path and the offset from its starting point
double anchorLength = totalLength*0.5;
i = 0;
while (i < lengths.size() && lengths[i] < anchorLength) {
++i;
size_t iLength = 0;
while (iLength < lengths.size() && lengths[iLength] < anchorLength) {
++iLength;
}
if (i) {
anchorLength -= lengths[i - 1];
if (iLength > 0) {
anchorLength -= lengths[iLength - 1];
}
// As reasonable anchor base point seems the "halving" edge endpoint
BRepAdaptor_Curve curve(objFeat->getEdge(subNames[i])->getOCCEdge());
BRepAdaptor_Curve curve(objFeat->getEdge(subNames[iLength])->getOCCEdge());
gp_Pnt midPoint;
curve.D0(curve.LastParameter(), midPoint);
@@ -1998,8 +2030,7 @@ namespace TechDrawGui
LineFormat& _getActiveLineAttributes()
{
static TechDraw::LineFormat attributes;
return attributes;
return LineFormat::getCurrentLineFormat();
}
std::string _createBalloon(Gui::Command* cmd, TechDraw::DrawViewPart* objFeat)
@@ -2008,7 +2039,7 @@ std::string _createBalloon(Gui::Command* cmd, TechDraw::DrawViewPart* objFeat)
std::string featName;
TechDraw::DrawPage* page = objFeat->findParentPage();
Gui::Document* guiDoc = Gui::Application::Instance->getDocument(page->getDocument());
ViewProviderPage* pageVP = dynamic_cast<ViewProviderPage*>(guiDoc->getViewProvider(page));
auto pageVP = dynamic_cast<ViewProviderPage*>(guiDoc->getViewProvider(page));
if (pageVP) {
QGSPage* scenePage = pageVP->getQGSPage();
featName = scenePage->getDrawPage()->getDocument()->getUniqueObjectName("Balloon");
@@ -2026,7 +2057,7 @@ std::string _createBalloon(Gui::Command* cmd, TechDraw::DrawViewPart* objFeat)
}
bool _checkSel(Gui::Command* cmd, std::vector<Gui::SelectionObject>& selection,
TechDraw::DrawViewPart*& objFeat, std::string message)
TechDraw::DrawViewPart*& objFeat, const std::string& message)
{
// check selection of getSelectionEx() and selection[0].getObject()
selection = cmd->getSelection().getSelectionEx();
@@ -2047,9 +2078,8 @@ bool _checkSel(Gui::Command* cmd, std::vector<Gui::SelectionObject>& selection,
return true;
}
//! return the vertices in the selection as [Base::Vector3d] in App coords -
//! inverted, unrotated and unscaled
std::vector<Base::Vector3d> _getVertexPoints(std::vector<std::string> SubNames,
//! return the vertices in the selection as [Base::Vector3d]
std::vector<Base::Vector3d> _getVertexPoints(const std::vector<std::string>& SubNames,
TechDraw::DrawViewPart* objFeat)
{
std::vector<Base::Vector3d> vertexPoints;
@@ -2058,8 +2088,7 @@ std::vector<Base::Vector3d> _getVertexPoints(std::vector<std::string> SubNames,
if (GeoType == "Vertex") {
int GeoId = TechDraw::DrawUtil::getIndexFromName(Name);
TechDraw::VertexPtr vert = objFeat->getProjVertexByIndex(GeoId);
Base::Vector3d onePoint = DU::toAppSpace(*objFeat, vert->point());
vertexPoints.push_back(onePoint);
vertexPoints.push_back(vert->point());
}
}
return vertexPoints;
@@ -2067,10 +2096,11 @@ std::vector<Base::Vector3d> _getVertexPoints(std::vector<std::string> SubNames,
//! get angle between x-axis and the vector from center to point.
//! result is [0, 360]
float _getAngle(Base::Vector3d center, Base::Vector3d point)
double _getAngle(Base::Vector3d center, Base::Vector3d point)
{
constexpr double DegreesHalfCircle{180.0};
Base::Vector3d vecCP = point - center;
double angle = DU::angleWithX(vecCP) * 180.0 / M_PI;
double angle = DU::angleWithX(vecCP) * DegreesHalfCircle / M_PI;
return angle;
}
@@ -2079,12 +2109,14 @@ Base::Vector3d _circleCenter(Base::Vector3d p1, Base::Vector3d p2, Base::Vector3
Base::Vector2d v1(p1.x, p1.y);
Base::Vector2d v2(p2.x, p2.y);
Base::Vector2d v3(p3.x, p3.y);
Base::Vector2d c = Part::Geom2dCircle::getCircleCenter(v1, v2, v3);
return Base::Vector3d(c.x, c.y, 0.0);
Base::Vector2d center = Part::Geom2dCircle::getCircleCenter(v1, v2, v3);
return Base::Vector3d(center.x, center.y, 0.0);
}
void _createThreadCircle(std::string Name, TechDraw::DrawViewPart* objFeat, float factor)
void _createThreadCircle(const std::string Name, TechDraw::DrawViewPart* objFeat, float factor)
{
constexpr double ArcStartDegree{255.0};
constexpr double ArcEndDegree{165.0};
// create the 3/4 arc symbolizing a thread from top seen
double scale = objFeat->getScale();
int GeoId = TechDraw::DrawUtil::getIndexFromName(Name);
@@ -2093,17 +2125,19 @@ void _createThreadCircle(std::string Name, TechDraw::DrawViewPart* objFeat, floa
if (GeoType == "Edge" && geom->getGeomType() == TechDraw::CIRCLE) {
TechDraw::CirclePtr cgen = std::static_pointer_cast<TechDraw::Circle>(geom);
Base::Vector3d center = cgen->center;
float radius = cgen->radius;
// center is rotated and scaled
Base::Vector3d center = CosmeticVertex::makeCanonicalPointInverted(objFeat, cgen->center);
// radius is scaled
float radius = cgen->radius * factor / scale;
TechDraw::BaseGeomPtr threadArc =
std::make_shared<TechDraw::AOC>(center / scale, radius * factor / scale, 255.0, 165.0);
std::make_shared<TechDraw::AOC>(center, radius, ArcStartDegree, ArcEndDegree);
std::string arcTag = objFeat->addCosmeticEdge(threadArc);
TechDraw::CosmeticEdge* arc = objFeat->getCosmeticEdge(arcTag);
_setLineAttributes(arc);
}
}
void _createThreadLines(std::vector<std::string> SubNames, TechDraw::DrawViewPart* objFeat,
void _createThreadLines(const std::vector<std::string>& SubNames, TechDraw::DrawViewPart* objFeat,
float factor)
{
// create symbolizing lines of a thread from the side seen
@@ -2122,17 +2156,12 @@ void _createThreadLines(std::vector<std::string> SubNames, TechDraw::DrawViewPar
TechDraw::GenericPtr line0 = std::static_pointer_cast<TechDraw::Generic>(geom0);
TechDraw::GenericPtr line1 = std::static_pointer_cast<TechDraw::Generic>(geom1);
// start and end points are scaled,rotated and inverted (CSRIx). We need to
// uninvert the points so the canonicalPoint math works correctly.
Base::Vector3d start0 = DU::invertY(line0->getStartPoint());
Base::Vector3d end0 = DU::invertY(line0->getEndPoint());
Base::Vector3d start1 = DU::invertY(line1->getStartPoint());
Base::Vector3d end1 = DU::invertY(line1->getEndPoint());
// start and end points are scaled,rotated and inverted (CSRIx).
// convert start and end to unscaled, unrotated.
start0 = CosmeticVertex::makeCanonicalPoint(objFeat, start0);
start1 = CosmeticVertex::makeCanonicalPoint(objFeat, start1);
end0 = CosmeticVertex::makeCanonicalPoint(objFeat, end0);
end1 = CosmeticVertex::makeCanonicalPoint(objFeat, end1);
Base::Vector3d start0 = CosmeticVertex::makeCanonicalPointInverted(objFeat, line0->getStartPoint());
Base::Vector3d start1 = CosmeticVertex::makeCanonicalPointInverted(objFeat, line1->getStartPoint());
Base::Vector3d end0 = CosmeticVertex::makeCanonicalPointInverted(objFeat, line0->getEndPoint());
Base::Vector3d end1 = CosmeticVertex::makeCanonicalPointInverted(objFeat, line1->getEndPoint());
if (DrawUtil::circulation(start0, end0, start1)
!= DrawUtil::circulation(end0, end1, start1)) {
Base::Vector3d help1 = start1;
@@ -2143,7 +2172,6 @@ void _createThreadLines(std::vector<std::string> SubNames, TechDraw::DrawViewPar
float kernelDiam = (start1 - start0).Length();
float kernelFactor = (kernelDiam * factor - kernelDiam) / 2;
Base::Vector3d delta = (start1 - start0).Normalize() * kernelFactor;
// addCosmeticEdge(pt1, pt2) inverts the points before creating the edge
std::string line0Tag =
objFeat->addCosmeticEdge(start0 - delta, end0 - delta);
std::string line1Tag =
@@ -2161,35 +2189,38 @@ void _setLineAttributes(TechDraw::CosmeticEdge* cosEdge)
cosEdge->m_format.setStyle(_getActiveLineAttributes().getStyle());
cosEdge->m_format.setWidth(_getActiveLineAttributes().getWidth());
cosEdge->m_format.setColor(_getActiveLineAttributes().getColor());
cosEdge->m_format.setVisible(_getActiveLineAttributes().getVisible());
cosEdge->m_format.setLineNumber(_getActiveLineAttributes().getLineNumber());
}
void _setLineAttributes(TechDraw::CenterLine* cosEdge)
{
// set line attributes of a cosmetic edge
cosEdge->m_format.m_style = _getActiveLineAttributes().getStyle();
cosEdge->m_format.m_weight = _getActiveLineAttributes().getWidth();
cosEdge->m_format.m_color = _getActiveLineAttributes().getColor();
cosEdge->m_format.setStyle(_getActiveLineAttributes().getStyle());
cosEdge->m_format.setWidth(_getActiveLineAttributes().getWidth());
cosEdge->m_format.setColor(_getActiveLineAttributes().getColor());
cosEdge->m_format.setVisible(_getActiveLineAttributes().getVisible());
cosEdge->m_format.setLineNumber(_getActiveLineAttributes().getLineNumber());
}
void _setLineAttributes(TechDraw::CosmeticEdge* cosEdge, int style, float weight, App::Color color)
{
// set line attributes of a cosmetic edge
cosEdge->m_format.m_style = _getActiveLineAttributes().getStyle();
cosEdge->m_format.m_weight = weight;
cosEdge->m_format.m_color = color;
cosEdge->m_format.setLineNumber(style);
cosEdge->m_format.setStyle(style);
cosEdge->m_format.setWidth(weight);
cosEdge->m_format.setColor(color);
cosEdge->m_format.setVisible(_getActiveLineAttributes().getVisible());
cosEdge->m_format.setLineNumber(LineGenerator::fromQtStyle((Qt::PenStyle)style));
}
void _setLineAttributes(TechDraw::CenterLine* cosEdge, int style, float weight, App::Color color)
{
// set line attributes of a centerline
cosEdge->m_format.m_style = _getActiveLineAttributes().getStyle();
cosEdge->m_format.m_weight = weight;
cosEdge->m_format.m_color = color;
cosEdge->m_format.setLineNumber(style);
}
cosEdge->m_format.setStyle(style);
cosEdge->m_format.setWidth(weight);
cosEdge->m_format.setColor(color);
cosEdge->m_format.setVisible(_getActiveLineAttributes().getVisible());
cosEdge->m_format.setLineNumber(style);}
}// namespace TechDrawGui
//------------------------------------------------------------------------------

View File

@@ -69,9 +69,11 @@
#include "MDIViewPage.h"
#include "QGSPage.h"
#include "ViewProviderPage.h"
#include "Rez.h"
using namespace TechDrawGui;
using namespace TechDraw;
using DU = DrawUtil;
void DrawGuiUtil::loadArrowBox(QComboBox* qcb)
{
@@ -569,3 +571,44 @@ void DrawGuiUtil::setSelectedTree(QGraphicsItem *item, bool selected)
}
}
}
//! convert point from scene coords to mm and conventional Y axis (page coords).
Base::Vector3d DrawGuiUtil::fromSceneCoords(const Base::Vector3d& sceneCoord, bool invert)
{
Base::Vector3d result;
if (invert) {
result = Rez::appX(DU::invertY(sceneCoord));
} else {
result = Rez::appX(sceneCoord);
}
return Rez::appX(DU::invertY(sceneCoord));
}
//! convert point from printed page coords to scene units (Rez(mm) and inverted Y axis (scene coords)
Base::Vector3d DrawGuiUtil::toSceneCoords(const Base::Vector3d& pageCoord, bool invert)
{
Base::Vector3d result;
if (invert) {
result = Rez::guiX(DU::invertY(pageCoord));
} else {
result = Rez::guiX(pageCoord);
}
return result;
}
//! convert unscaled, unrotated point to scaled, rotated view coordinates
Base::Vector3d DrawGuiUtil::toGuiPoint(DrawView* obj, const Base::Vector3d& toConvert)
{
Base::Vector3d result{toConvert};
auto rotDegrees = obj->Rotation.getValue();
if (rotDegrees != 0.0) {
result.RotateZ(Base::toRadians(rotDegrees));
}
result *= obj->getScale();
result = DU::invertY(result);
result = Rez::guiX(result);
return result;
}

View File

@@ -45,6 +45,7 @@ class Feature;
namespace TechDraw {
class DrawPage;
class DrawView;
class LineGenerator;
}
namespace Gui {
@@ -81,6 +82,9 @@ class TechDrawGuiExport DrawGuiUtil {
static bool isSelectedInTree(QGraphicsItem *item);
static void setSelectedTree(QGraphicsItem *item, bool selected);
static Base::Vector3d fromSceneCoords(const Base::Vector3d& sceneCoord, bool invert = true);
static Base::Vector3d toSceneCoords(const Base::Vector3d& pageCoord, bool invert = true);
static Base::Vector3d toGuiPoint(TechDraw::DrawView* obj, const Base::Vector3d& toConvert);
};
} //end namespace TechDrawGui

View File

@@ -54,10 +54,12 @@ QPainterPath PathBuilder::geomToPainterPath(BaseGeomPtr baseGeom, double rot) co
} break;
case ARCOFCIRCLE: {
TechDraw::AOCPtr geom = std::static_pointer_cast<TechDraw::AOC>(baseGeom);
if (baseGeom->getReversed()) {
if (baseGeom->getReversed()) { // OCC reversed flag
path.moveTo(Rez::guiX(geom->endPnt.x), Rez::guiX(geom->endPnt.y));
pathArc(path, Rez::guiX(geom->radius), Rez::guiX(geom->radius), 0., geom->largeArc,
!geom->cw, Rez::guiX(geom->startPnt.x), Rez::guiX(geom->startPnt.y),
pathArc(path, Rez::guiX(geom->radius), Rez::guiX(geom->radius), 0.,
geom->largeArc, // >180?
!geom->cw, // calculated from start and end angle not occ edge
Rez::guiX(geom->startPnt.x), Rez::guiX(geom->startPnt.y),
Rez::guiX(geom->endPnt.x), Rez::guiX(geom->endPnt.y));
}
else {

View File

@@ -296,3 +296,11 @@ QColor PreferencesGui::templateClickBoxColor()
fcColor.setPackedValue(Preferences::getPreferenceGroup("Colors")->GetUnsigned("TemplateUnderlineColor", 0x0000FFFF)); //#0000FF blue
return fcColor.asValue<QColor>();
}
int PreferencesGui::get3dMarkerSize()
{
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath
("User parameter:BaseApp/Preferences/View");
return hGrp->GetInt("MarkerSize", 9L);
}

View File

@@ -88,6 +88,9 @@ static QColor lightenColor(QColor orig);
static double templateClickBoxSize();
static QColor templateClickBoxColor();
static int get3dMarkerSize();
};
} //end namespace TechDrawGui

View File

@@ -41,10 +41,13 @@
#include "QGIView.h"
#include "Rez.h"
#include "ZVALUE.h"
#include "DrawGuiUtil.h"
using namespace TechDrawGui;
using namespace TechDraw;
using DU = DrawUtil;
using DGU = DrawGuiUtil;
QGMarker::QGMarker(int idx) : QGIVertex(idx),
m_dragging(false)
@@ -62,7 +65,9 @@ void QGMarker::mousePressEvent(QGraphicsSceneMouseEvent * event)
Q_EMIT endEdit();
event->accept();
return;
} else if(scene() && this == scene()->mouseGrabberItem()) {
}
if(scene() && this == scene()->mouseGrabberItem()) {
//start dragging
m_dragging = true;
Q_EMIT dragging(pos(), getProjIndex()); //pass center of marker[i] to epath
@@ -72,7 +77,8 @@ void QGMarker::mousePressEvent(QGraphicsSceneMouseEvent * event)
void QGMarker::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
{
if (event->button() == Qt::RightButton) { //we're done
if (event->button() == Qt::RightButton) {
// we are finished our edit session
Q_EMIT endEdit();
m_dragging = false;
return;
@@ -82,6 +88,7 @@ void QGMarker::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
if (m_dragging) {
m_dragging = false;
setSelected(false);
// send this marker's new position to QGEPath
Q_EMIT dragFinished(pos(), getProjIndex()); //pass center of marker[i] to epath
}
}
@@ -92,7 +99,9 @@ void QGMarker::mouseDoubleClickEvent(QGraphicsSceneMouseEvent * event)
{
// Base::Console().Message("QGMarker::mouseDoubleClickEvent(%d)\n", getProjIndex());
if (event->button() == Qt::RightButton) { //we're done
// we are finished our edit session
Q_EMIT endEdit();
m_dragging = false;
return;
}
QGIVertex::mouseDoubleClickEvent(event);
@@ -102,28 +111,34 @@ void QGMarker::keyPressEvent(QKeyEvent * event)
{
// Base::Console().Message("QGMarker::keyPressEvent(%d)\n", getProjIndex());
if (event->key() == Qt::Key_Escape) {
m_dragging = false;
Q_EMIT endEdit();
}
QGIVertex::keyPressEvent(event);
}
//! adjust the size of this marker
void QGMarker::setRadius(float radius)
{
//TODO:: implement different marker shapes. circle, square, triangle, ???
//if (m_markerShape == Circle) { ...
//setRect(QRectF) for rectangular markers
m_radius = radius;
QPainterPath p;
p.addRect(-radius/2.0, -radius/2.0, radius, radius);
setPath(p);
QPainterPath pPath;
pPath.addRect(-radius/2.0, -radius/2.0, radius, radius);
setPath(pPath);
}
//******************************************************************************
QGEPath::QGEPath(QGILeaderLine* leader) :
//! QGEPath is an editable version of QGIPrimPath. Points along the path can be dragged to new
//! positions that are returned to the caller on completion of the edit session. The points are in
//! scene coordinates and are relative to the scene position of the caller.
QGEPath::QGEPath() :
m_scale(1.0),
m_inEdit(false),
m_parentLeader(leader),
m_startAdj(0.0),
m_endAdj(0.0)
{
@@ -169,7 +184,7 @@ void QGEPath::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
void QGEPath::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
QGIView *view = dynamic_cast<QGIView *> (parentItem());
auto view = dynamic_cast<QGIView *> (parentItem());
assert(view);
Q_UNUSED(view);
@@ -186,7 +201,9 @@ void QGEPath::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
// QGIPrimPath::hoverLeaveEvent(event); //QGIPP::hoverleave will reset pretty to normal
}
void QGEPath::startPathEdit(std::vector<QPointF> pathPoints)
//! this begins an edit session for a path described by pathPoints.
void QGEPath::startPathEdit(const std::vector<QPointF>& pathPoints)
{
// Base::Console().Message("QGEPath::startPathEdit()\n");
inEdit(true);
@@ -194,7 +211,7 @@ void QGEPath::startPathEdit(std::vector<QPointF> pathPoints)
showMarkers(m_ghostPoints);
}
void QGEPath::showMarkers(std::vector<QPointF> points)
void QGEPath::showMarkers(const std::vector<QPointF>& points)
{
// Base::Console().Message("QGEPath::showMarkers()\n");
if (!inEdit()) {
@@ -231,9 +248,8 @@ void QGEPath::showMarkers(std::vector<QPointF> points)
v, &QGMarker::endEdit,
this, &QGEPath::onEndEdit
);
//TODO: double r = getMarkerSize();
// v->setRadius(r);
v->setRadius(50.0);
v->setRadius(PreferencesGui::get3dMarkerSize());
// v->setRadius(50.0); // this make a huge marker
v->setNormalColor(PreferencesGui::getAccessibleQColor(QColor(Qt::black)));
v->setZValue(ZVALUE::VERTEX);
v->setPos(p);
@@ -304,31 +320,6 @@ void QGEPath::onEndEdit()
clearMarkers();
}
std::vector<QPointF> QGEPath::getDeltasFromLeader()
{
std::vector<QPointF> qDeltas;
if (!m_parentLeader) {
Base::Console().Message("QGEP::getDeltasFromLeader - m_parentLeader is nullptr\n");
return qDeltas;
}
DrawLeaderLine* featLeader = m_parentLeader->getFeature();
if (!featLeader) {
Base::Console().Message("QGEP::getDeltasFromLeader - featLeader is nullptr\n");
return qDeltas;
}
std::vector<Base::Vector3d> vDeltas = featLeader->WayPoints.getValues();
for (auto& d: vDeltas) {
Base::Vector3d vTemp = Rez::guiX(d);
QPointF temp(vTemp.x, -vTemp.y);
qDeltas.push_back(temp);
}
if (qDeltas.empty()) {
Base::Console().Warning("QGEPath::getDeltasFromLeader - no points\n");
}
return qDeltas;
}
//announce points editing is finished
void QGEPath::updateParent()
@@ -341,7 +332,7 @@ void QGEPath::updateParent()
}
}
//the ghost is the red line drawn when creating or editing the Leader points
//! the ghost is the red line drawn when creating or editing the points
void QGEPath::drawGhost()
{
// Base::Console().Message("QGEPath::drawGhost()\n");

View File

@@ -40,6 +40,7 @@ class QGIVertex;
class QGIView;
class QGILeaderLine;
//! QGMarker provides movable symbols
class TechDrawGuiExport QGMarker : public QObject, public QGIVertex
{
Q_OBJECT
@@ -73,12 +74,14 @@ private:
//******************************************************************************
class TechDrawGuiExport QGEPath : public QObject, public QGIPrimPath
{
Q_OBJECT
public:
explicit QGEPath(QGILeaderLine* leader);
explicit QGEPath();
~QGEPath() override = default;
enum {Type = QGraphicsItem::UserType + 301};
@@ -88,18 +91,14 @@ public:
void inEdit(bool isInEdit) { m_inEdit = isInEdit; }
bool inEdit() const { return m_inEdit; }
void startPathEdit(std::vector<QPointF> pathPoints);
void startPathEdit(const std::vector<QPointF>& pathPoints);
void showMarkers(std::vector<QPointF> points);
void showMarkers(const std::vector<QPointF>& points);
void clearMarkers();
std::vector<QPointF> getDeltasFromLeader();
void setScale(double scale) { m_scale = scale; }
double getScale() const { return m_scale; }
void setPoints(std::vector<QPointF>& pts) { m_ghostPoints = pts; }
void updateParent();
void drawGhost();
@@ -133,7 +132,6 @@ private:
double m_scale;
bool m_inEdit;
QGILeaderLine* m_parentLeader;
QGIPrimPath* m_ghost;
double m_startAdj;

View File

@@ -31,11 +31,13 @@
# include <QVector2D>
#endif
#include <App/Document.h>
#include <Base/Console.h>
#include <Mod/TechDraw/App/ArrowPropEnum.h>
#include <Mod/TechDraw/App/DrawLeaderLine.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include <Mod/TechDraw/App/LineGroup.h>
#include <Mod/TechDraw/App/DrawViewPart.h>
#include "QGILeaderLine.h"
#include "PreferencesGui.h"
@@ -45,10 +47,14 @@
#include "Rez.h"
#include "ViewProviderLeader.h"
#include "ZVALUE.h"
#include "DrawGuiUtil.h"
using namespace TechDrawGui;
using namespace TechDraw;
using DU = DrawUtil;
using DGU = DrawGuiUtil;
//**************************************************************
QGILeaderLine::QGILeaderLine()
@@ -75,7 +81,7 @@ QGILeaderLine::QGILeaderLine()
m_line->setAcceptHoverEvents(false);
m_line->setPos(0.0, 0.0);
m_editPath = new QGEPath(this);
m_editPath = new QGEPath();
addToGroup(m_editPath);
m_editPath->setPos(0.0, 0.0);
m_editPath->setFlag(QGraphicsItem::ItemIsSelectable, false);
@@ -148,6 +154,21 @@ void QGILeaderLine::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
QGraphicsItem::mouseReleaseEvent(event);
}
//! start editor on double click
void QGILeaderLine::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
{
// Base::Console().Message("QGILL::mouseDoubleClickEvent() - %s\n", getViewName());
auto ViewProvider = dynamic_cast<ViewProviderLeader*>(getViewProvider(getLeaderFeature()));
if (!ViewProvider) {
qWarning() << "QGILeaderLine::mouseDoubleClickEvent: No valid view provider";
return;
}
ViewProvider->startDefaultEditMode();
QGraphicsItem::mouseDoubleClickEvent(event);
}
void QGILeaderLine::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
{
// Base::Console().Message("QGILL::hoverEnter() - selected; %d\n", isSelected());
@@ -213,14 +234,17 @@ void QGILeaderLine::closeEdit()
}
}
//signaled from QEPath
void QGILeaderLine::onLineEditFinished(QPointF tipDisplace, std::vector<QPointF> points)
//! scene coordinates of leaderline points are converted to real page coordinates as deltas from first point.
//! line start point (X,Y of leader feature) is recomputed as displacement from parent's (0,0).
//! signaled from QEPath
void QGILeaderLine::onLineEditFinished(QPointF tipDisplace, std::vector<QPointF> scenePoints)
{
// Base::Console().Message("QGILL::onLineEditFinished(%s, %d)\n",
// TechDraw::DrawUtil::formatVector(tipDisplace).c_str(),
// points.size());
// Base::Console().Message("QGILL::onLineEditFinished(%s, %d)\n",
// TechDraw::DrawUtil::formatVector(tipDisplace).c_str(),
// scenePoints.size());
m_blockDraw = true;
auto featLeader = getFeature();
auto featLeader = getLeaderFeature();
if (!featLeader) {
return;
}
@@ -234,18 +258,18 @@ void QGILeaderLine::onLineEditFinished(QPointF tipDisplace, std::vector<QPointF>
featLeader->setPosition(Rez::appX(newAttach.x()), Rez::appX(-newAttach.y()), true);
}
std::vector<Base::Vector3d> waypoints;
for (auto& p : points) {
QPointF moved = p - tipDisplace;
Base::Vector3d v(moved.x(), moved.y(), 0.0);
waypoints.push_back(v);
std::vector<Base::Vector3d> pageDeltas;
for (auto& pt : scenePoints) {
QPointF distFromP0 = pt - scenePoints.front();
// convert deltas to mm and conventional Y axis from scene coords
Base::Vector3d deltaInPageCoords = DGU::fromSceneCoords(DU::toVector3d(distFromP0));
pageDeltas.push_back(deltaInPageCoords);
}
waypoints.at(0) = Base::Vector3d(0.0, 0.0, 0.0);
pageDeltas.at(0) = Base::Vector3d(0.0, 0.0, 0.0);
featLeader->WayPoints.setValues(waypoints);
if (featLeader->AutoHorizontal.getValue()) {
featLeader->adjustLastSegment();
}
// to canonical form here
auto temp = featLeader->makeCanonicalPointsInverted(pageDeltas);
featLeader->WayPoints.setValues(temp);
Q_EMIT editComplete();//tell task editing is complete
@@ -272,7 +296,7 @@ void QGILeaderLine::startPathEdit()
void QGILeaderLine::saveState()
{
// Base::Console().Message("QGILL::saveState()\n");
auto featLeader = getFeature();
auto featLeader = getLeaderFeature();
if (featLeader) {
m_savePoints = featLeader->WayPoints.getValues();
m_saveX = featLeader->X.getValue();
@@ -283,7 +307,7 @@ void QGILeaderLine::saveState()
void QGILeaderLine::restoreState()
{
// Base::Console().Message("QGILL::restoreState()\n");
auto featLeader = getFeature();
auto featLeader = getLeaderFeature();
if (featLeader) {
featLeader->WayPoints.setValues(m_savePoints);
featLeader->X.setValue(m_saveX);
@@ -296,7 +320,7 @@ void QGILeaderLine::restoreState()
void QGILeaderLine::updateView(bool update)
{
// Base::Console().Message("QGIL::updateView() %s\n", getViewObject()->getNameInDocument());
// Base::Console().Message("QGILL::updateView()\n");
Q_UNUSED(update);
auto featLeader(dynamic_cast<TechDraw::DrawLeaderLine*>(getViewObject()));
if (!featLeader) {
@@ -313,14 +337,14 @@ void QGILeaderLine::updateView(bool update)
void QGILeaderLine::draw()
{
// Base::Console().Message("QGILL::draw()- %s\n", getViewObject()->getNameInDocument());
// Base::Console().Message("QGILL::draw()- %s\n", getViewObject()->getNameInDocument());
if (m_blockDraw) {
return;
}
if (!isVisible()) {
return;
}
TechDraw::DrawLeaderLine* featLeader = getFeature();
TechDraw::DrawLeaderLine* featLeader = getLeaderFeature();
if (!featLeader) {
return;
}
@@ -329,10 +353,10 @@ void QGILeaderLine::draw()
return;
}
double scale = 1.0;
TechDraw::DrawView* parent = featLeader->getBaseView();
if (parent) {
scale = parent->getScale();
if (!parent) {
return;
}
if (m_editPath->inEdit()) {
@@ -347,25 +371,34 @@ void QGILeaderLine::draw()
setFlag(QGraphicsItem::ItemIsMovable, true);
}
// set the leader's Qt position from feature's X,Y and scale.
// the feature's x,y is unscaled, unrotated and conventional Y
// line style is standing in for line number here?
m_lineStyle = static_cast<Qt::PenStyle>(vp->LineStyle.getValue());
double baseScale = featLeader->getBaseScale();
double x = Rez::guiX(featLeader->X.getValue());
double y = -Rez::guiX(featLeader->Y.getValue());
QPointF aPoint(x, y);
aPoint *= baseScale;
setPos(aPoint);
double xPos = Rez::guiX(featLeader->X.getValue());
double yPos = Rez::guiX(featLeader->Y.getValue());
Base::Vector3d vAttachPoint{xPos, yPos};
vAttachPoint = vAttachPoint * baseScale;
double rotationRad = parent->Rotation.getValue() * M_PI / DegreesHalfCircle;
if (rotationRad != 0.0) {
vAttachPoint.RotateZ(rotationRad);
}
vAttachPoint = DU::invertY(vAttachPoint);
QPointF qPoint = DU::toQPointF(vAttachPoint);
// ???? why does the attach point not need Rez applied?
setPos(qPoint);
m_line->setFillStyle(Qt::NoBrush);
m_line->setStyle(m_lineStyle);
m_line->setWidth(getLineWidth());
m_line->setPos(0, 0);//make m_line coords == leader coords
m_line->setPos(0, 0); //make m_line coords == leader coords
std::vector<QPointF> qPoints = getWayPointsFromFeature();
if (featLeader->Scalable.getValue()) {
for (auto& p : qPoints) {
p = p * scale;
}
if (qPoints.empty() ) {
Base::Console().Message("QGILL::draw - no points\n");
return;
}
setNormalColorAll();
@@ -388,9 +421,9 @@ QPainterPath QGILeaderLine::makeLeaderPath(std::vector<QPointF> qPoints)
{
// Base::Console().Message("QGILeaderLine::makeLeaderPath()\n");
QPainterPath result;
DrawLeaderLine* featLeader = getFeature();
DrawLeaderLine* featLeader = getLeaderFeature();
if (!featLeader) {
Base::Console().Message("QGILL::makeLeaderPath - featLeader is nullptr\n");
// Base::Console().Message("QGILL::makeLeaderPath - featLeader is nullptr\n");
return result;
}
@@ -431,37 +464,54 @@ QPainterPath QGILeaderLine::makeLeaderPath(std::vector<QPointF> qPoints)
return result;
}
//! returns the point (on the parent) to which the leader is attached.
//! result is relative to the center of the unscaled, unrotated parent.
//! result is is not inverted (Y grows upwards).
QPointF QGILeaderLine::getAttachFromFeature()
{
// Base::Console().Message("QGILL::getAttachFromFeature()\n");
TechDraw::DrawLeaderLine* featLeader = getFeature();
// Base::Console().Message("QGILL::getAttachFromFeature()\n");
TechDraw::DrawLeaderLine* featLeader = getLeaderFeature();
if (!featLeader) {
Base::Console().Message("QGIL::getAttachFromLeader - no feature\n");
return QPointF();
// Base::Console().Message("QGIL::getAttachFromLeader - no feature\n");
return {};
}
double x = Rez::guiX(featLeader->X.getValue());
double y = -Rez::guiX(featLeader->Y.getValue());
return QPointF(x, y);
// this is unrotated point. is it scaled?
return {x, y};
}
std::vector<QPointF> QGILeaderLine::getWayPointsFromFeature()
{
std::vector<QPointF> qPoints;
DrawLeaderLine* featLeader = getFeature();
// Base::Console().Message("QGILL::getWayPointsFromFeature()\n");
DrawLeaderLine* featLeader = getLeaderFeature();
if (!featLeader) {
Base::Console().Message("QGILL::getWayPointsFromFeature - featLeader is nullptr\n");
return qPoints;
// Base::Console().Message("QGILL::getWayPointsFromFeature - featLeader is nullptr\n");
return {};
}
std::vector<Base::Vector3d> vPoints = featLeader->WayPoints.getValues();
for (auto& d : vPoints) {
QPointF temp(d.x, d.y);
qPoints.push_back(temp);
// vPoints are in mm with conventional Y axis
auto doScale = featLeader->Scalable.getValue();
auto doRotate = featLeader->RotatesWithParent.getValue();
auto vPoints = featLeader->getScaledAndRotatedPoints(doScale, doRotate);
std::vector<QPointF> qPoints;
qPoints.reserve(vPoints.size());
// now convert to sceneUnits and Qt Y axis
for (auto& entry : vPoints) {
if (useOldCoords()) {
// use points as saved in <= v0.21 (in Qt form, Rez'd and
qPoints.push_back(DU::toQPointF(entry));
} else {
// use points as saved in >= v0.22
qPoints.push_back(DU::toQPointF(DGU::toSceneCoords(entry, false)));
}
}
if (qPoints.empty()) {
Base::Console().Warning("QGILeaderLine::getWayPointsFromFeature - no points\n");
}
return qPoints;
}
@@ -469,7 +519,7 @@ void QGILeaderLine::setArrows(std::vector<QPointF> pathPoints)
{
// Base::Console().Message("QGILL::setArrows()\n");
Base::Vector3d stdX(1.0, 0.0, 0.0);
TechDraw::DrawLeaderLine* featLeader = getFeature();
TechDraw::DrawLeaderLine* featLeader = getLeaderFeature();
QPointF lastOffset = (pathPoints.back() - pathPoints.front());
@@ -544,7 +594,7 @@ double QGILeaderLine::getLineWidth()
return Rez::guiX(vp->LineWidth.getValue());
}
TechDraw::DrawLeaderLine* QGILeaderLine::getFeature()
TechDraw::DrawLeaderLine* QGILeaderLine::getLeaderFeature()
{
TechDraw::DrawLeaderLine* result = static_cast<TechDraw::DrawLeaderLine*>(getViewObject());
return result;
@@ -585,4 +635,15 @@ void QGILeaderLine::paint(QPainter* painter, const QStyleOptionGraphicsItem* opt
QGIView::paint(painter, &myOption, widget);
}
bool QGILeaderLine::useOldCoords() const
{
bool result = false;
auto vp = dynamic_cast<ViewProviderLeader*>(getViewProvider(getViewObject()));
if (vp) {
result = vp->UseOldCoords.getValue();
}
return result;
}
#include <Mod/TechDraw/Gui/moc_QGILeaderLine.cpp>

View File

@@ -75,7 +75,7 @@ public:
void drawBorder() override;
void updateView(bool update = false) override;
virtual TechDraw::DrawLeaderLine* getFeature();
virtual TechDraw::DrawLeaderLine* getLeaderFeature();
void startPathEdit();
void setArrows(std::vector<QPointF> pathPoints);
@@ -88,6 +88,7 @@ public:
void mousePressEvent(QGraphicsSceneMouseEvent* event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override;
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event) override;
void hoverEnterEvent(QGraphicsSceneHoverEvent* event) override;
void hoverLeaveEvent(QGraphicsSceneHoverEvent* event) override;
@@ -97,6 +98,9 @@ public:
void setLeaderFeature(TechDraw::DrawLeaderLine* feat);
bool useOldCoords() const;
public Q_SLOTS:
void onLineEditFinished(QPointF tipDisplace,
std::vector<QPointF> points);//QGEPath is finished editing points

View File

@@ -53,12 +53,15 @@
#include "ViewProviderBalloon.h"
#include "ViewProviderViewPart.h"
#include "ZVALUE.h"
#include "DrawGuiUtil.h"
//TODO: hide the Qt coord system (+y down).
using namespace TechDraw;
using namespace TechDrawGui;
using DU = DrawUtil;
using DGU = DrawGuiUtil;
QGIBalloonLabel::QGIBalloonLabel()
{
@@ -593,7 +596,7 @@ void QGIViewBalloon::drawBalloon(bool dragged)
return;
}
const TechDraw::DrawView* refObj = balloon->getParentView();
TechDraw::DrawView* refObj = balloon->getParentView();
auto vp = static_cast<ViewProviderBalloon*>(getViewProvider(getViewObject()));
if (!refObj || !vp) {
// can't draw this. probably restoring.
@@ -605,6 +608,7 @@ void QGIViewBalloon::drawBalloon(bool dragged)
double textWidth = balloonLabel->getDimText()->boundingRect().width();
double textHeight = balloonLabel->getDimText()->boundingRect().height();
float x, y, arrowTipX, arrowTipY;
Base::Vector3d arrowTip{balloon->OriginX.getValue(), balloon->OriginY.getValue(), 0.0};
// when not dragging take the X/Y properties otherwise the current label position
if (!dragged) {
x = Rez::guiX(balloon->X.getValue() * refObj->getScale());
@@ -619,6 +623,7 @@ void QGIViewBalloon::drawBalloon(bool dragged)
double scale = Rez::guiX(refObj->getScale());
Base::Vector3d pos(x / scale, y / scale, 0.0);
Base::Vector3d newOrg = pos - m_saveOffset;
arrowTip = newOrg;
arrowTipX = newOrg.x * scale;
arrowTipY = -newOrg.y * scale;
}
@@ -782,17 +787,19 @@ void QGIViewBalloon::drawBalloon(bool dragged)
arrow->draw();
Base::Vector3d arrowTipPos(arrowTipX, arrowTipY, 0.0);
// arrowTip set above is unscaled, uninverted, unrotated and unRez'd.
arrowTip = DGU::toGuiPoint(refObj, arrowTip);
Base::Vector3d dirballoonLinesLine;
if (!DrawUtil::fpCompare(kinkLength, 0.0)) {
dirballoonLinesLine = (arrowTipPos - kinkPoint).Normalize();
dirballoonLinesLine = (arrowTip - kinkPoint).Normalize();
}
else {
dirballoonLinesLine = (arrowTipPos - dLineStart).Normalize();
dirballoonLinesLine = (arrowTip - dLineStart).Normalize();
}
float arAngle = atan2(dirballoonLinesLine.y, dirballoonLinesLine.x) * 180 / M_PI;
arrow->setPos(arrowTipX, arrowTipY);
arrow->setPos(DU::toQPointF(arrowTip));
if ((endType == ArrowType::FILLED_TRIANGLE) && (prefOrthoPyramid())) {
if (arAngle < 0.0) {
arAngle += 360.0;
@@ -819,7 +826,7 @@ void QGIViewBalloon::drawBalloon(bool dragged)
arrow->setRotation(arAngle);
arrow->show();
}
dLinePath.lineTo(arrowTipX - xAdj, arrowTipY - yAdj);
dLinePath.lineTo(arrowTip.x - xAdj, arrowTip.y - yAdj);
balloonLines->setPath(dLinePath);
// This overwrites the previously created QPainterPath with empty one, in case it should be hidden. Should be refactored.

View File

@@ -22,7 +22,6 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#include <cmath>
#include <QPainterPath>
#include <QKeyEvent>
@@ -139,45 +138,25 @@ bool QGIViewPart::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
bool QGIViewPart::removeSelectedCosmetic() const
{
// Base::Console().Message("QGIVP::removeSelectedCosmetic()\n");
auto dvp(dynamic_cast<TechDraw::DrawViewPart*>(getViewObject()));
if (!dvp) {
throw Base::RuntimeError("Graphic has no feature!");
}
char* defaultDocument{nullptr};
std::vector<Gui::SelectionObject> selectionAll = Gui::Selection().getSelectionEx(
defaultDocument, TechDraw::DrawViewPart::getClassTypeId(), Gui::ResolveMode::NoResolve);
defaultDocument, TechDraw::DrawViewPart::getClassTypeId(), Gui::ResolveMode::OldStyleElement);
if (selectionAll.empty()) {
return false;
}
Gui::SelectionObject firstSelection = selectionAll.front();
App::DocumentObject* firstObject = selectionAll.front().getObject();
std::vector<std::string> subElements = selectionAll.front().getSubNames();
if (subElements.empty()) {
return false;
}
auto dvp = static_cast<TechDraw::DrawViewPart*>(firstObject);
auto subelement = subElements.front();
std::string geomName = DU::getGeomTypeFromName(subelement);
int index = DU::getIndexFromName(subelement);
if (geomName == "Edge") {
TechDraw::BaseGeomPtr base = dvp->getGeomByIndex(index);
if (!base || base->getCosmeticTag().empty()) {
return false;
}
if (base->source() == COSMETICEDGE) {
dvp->removeCosmeticEdge(base->getCosmeticTag());
dvp->refreshCEGeoms();
} else if (base->source() == CENTERLINE) {
dvp->removeCenterLine(base->getCosmeticTag());
dvp->refreshCLGeoms();
} else {
Base::Console().Message("QGIVP::removeSelectedCosmetic - not a CE or a CL\n");
return false;
}
} else if (geomName == "Vertex") {
VertexPtr vert = dvp->getProjVertexByIndex(index);
if (!vert || vert->getCosmeticTag().empty() ) {
return false;
}
dvp->removeCosmeticVertex(vert->getCosmeticTag());
dvp->refreshCVGeoms();
}
dvp->deleteCosmeticElements(subElements);
dvp->refreshCEGeoms();
dvp->refreshCLGeoms();
dvp->refreshCVGeoms();
return true;
}
@@ -403,15 +382,15 @@ void QGIViewPart::drawAllEdges()
// geometry edge - apply format if applicable
TechDraw::GeomFormat* gf = dvp->getGeomFormatBySelection(iEdge);
if (gf) {
App::Color color = Preferences::getAccessibleColor(gf->m_format.m_color);
App::Color color = Preferences::getAccessibleColor(gf->m_format.getColor());
item->setNormalColor(color.asValue<QColor>());
int lineNumber = gf->m_format.getLineNumber();
int qtStyle = gf->m_format.m_style;
int qtStyle = gf->m_format.getStyle();
item->setLinePen(m_dashedLineGenerator->getBestPen(lineNumber, (Qt::PenStyle)qtStyle,
gf->m_format.m_weight));
gf->m_format.getWidth()));
// but we need to actually draw the lines in QGScene coords (0.1 mm).
item->setWidth(Rez::guiX(gf->m_format.m_weight));
showItem = gf->m_format.m_visible;
item->setWidth(Rez::guiX(gf->m_format.getWidth()));
showItem = gf->m_format.getVisible();
} else {
if (!(*itGeom)->getHlrVisible()) {
// hidden line without a format
@@ -566,13 +545,13 @@ bool QGIViewPart::formatGeomFromCosmetic(std::string cTag, QGIEdge* item)
auto partFeat(dynamic_cast<TechDraw::DrawViewPart*>(getViewObject()));
TechDraw::CosmeticEdge* ce = partFeat ? partFeat->getCosmeticEdge(cTag) : nullptr;
if (ce) {
App::Color color = Preferences::getAccessibleColor(ce->m_format.m_color);
App::Color color = Preferences::getAccessibleColor(ce->m_format.getColor());
item->setNormalColor(color.asValue<QColor>());
item->setLinePen(m_dashedLineGenerator->getBestPen(ce->m_format.getLineNumber(),
(Qt::PenStyle)ce->m_format.m_style,
ce->m_format.m_weight));
item->setWidth(Rez::guiX(ce->m_format.m_weight));
result = ce->m_format.m_visible;
(Qt::PenStyle)ce->m_format.getStyle(),
ce->m_format.getWidth()));
item->setWidth(Rez::guiX(ce->m_format.getWidth()));
result = ce->m_format.getVisible();
}
return result;
}
@@ -585,13 +564,13 @@ bool QGIViewPart::formatGeomFromCenterLine(std::string cTag, QGIEdge* item)
auto partFeat(dynamic_cast<TechDraw::DrawViewPart*>(getViewObject()));
TechDraw::CenterLine* cl = partFeat ? partFeat->getCenterLine(cTag) : nullptr;
if (cl) {
App::Color color = Preferences::getAccessibleColor(cl->m_format.m_color);
App::Color color = Preferences::getAccessibleColor(cl->m_format.getColor());
item->setNormalColor(color.asValue<QColor>());
item->setLinePen(m_dashedLineGenerator->getBestPen(cl->m_format.getLineNumber(),
(Qt::PenStyle)cl->m_format.m_style,
cl->m_format.m_weight));
item->setWidth(Rez::guiX(cl->m_format.m_weight));
result = cl->m_format.m_visible;
(Qt::PenStyle)cl->m_format.getStyle(),
cl->m_format.getWidth()));
item->setWidth(Rez::guiX(cl->m_format.getWidth()));
result = cl->m_format.getVisible();
}
return result;
}

View File

@@ -107,7 +107,7 @@ void QGTracker::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
QPointF myScenePos = event->scenePos();
if (!m_sleep) {
double someLimit = Rez::guiX(10.0);
double someLimit = Rez::guiX(1.0);
QPointF manhat = myScenePos - m_lastClick;
// Base::Console().Message("QGT::mousePressEvent - scenePos: (%.3f, %.3f) lastClick:(%.3f, %.3f)\n",
// myScenePos.x(), myScenePos.y(), m_lastClick.x(), m_lastClick.y());
@@ -170,6 +170,8 @@ void QGTracker::keyPressEvent(QKeyEvent * event)
QGIPrimPath::keyPressEvent(event);
}
// ?? why does this method exist? and why isn't it called changeCursor?
void QGTracker::sleep(bool b)
{
m_sleep = b;

View File

@@ -216,12 +216,12 @@ void TaskCenterLine::setUiEdit()
QString listItem = Base::Tools::fromStdString(m_edgeName);
ui->lstSubList->addItem(listItem);
}
ui->cpLineColor->setColor(m_cl->m_format.m_color.asValue<QColor>());
ui->dsbWeight->setValue(m_cl->m_format.m_weight);
ui->cpLineColor->setColor(m_cl->m_format.getColor().asValue<QColor>());
ui->dsbWeight->setValue(m_cl->m_format.getWidth());
DrawGuiUtil::loadLineStyleChoices(ui->cboxStyle);
if (ui->cboxStyle->count() >= m_cl->m_format.m_style ) {
ui->cboxStyle->setCurrentIndex(m_cl->m_format.m_style - 1);
if (ui->cboxStyle->count() >= m_cl->m_format.getStyle() ) {
ui->cboxStyle->setCurrentIndex(m_cl->m_format.getStyle() - 1);
}
ui->rbVertical->setChecked(false);
@@ -318,7 +318,7 @@ void TaskCenterLine::onColorChanged()
App::Color ac;
ac.setValue<QColor>(ui->cpLineColor->color());
m_cl->m_format.m_color.setValue<QColor>(ui->cpLineColor->color());
m_cl->m_format.getColor().setValue<QColor>(ui->cpLineColor->color());
m_partFeat->recomputeFeature();
}
@@ -328,7 +328,7 @@ void TaskCenterLine::onWeightChanged()
return;
}
m_cl->m_format.m_weight = ui->dsbWeight->value().getValue();
m_cl->m_format.setWidth(ui->dsbWeight->value().getValue());
m_partFeat->recomputeFeature();
}
@@ -431,10 +431,10 @@ void TaskCenterLine::createCenterLine()
cl->m_flip2Line = false;
App::Color ac;
ac.setValue<QColor>(ui->cpLineColor->color());
cl->m_format.m_color = ac;
cl->m_format.m_weight = ui->dsbWeight->value().getValue();
cl->m_format.setColor(ac);
cl->m_format.setWidth(ui->dsbWeight->value().getValue());
cl->m_format.setLineNumber(ui->cboxStyle->currentIndex() + 1);
cl->m_format.m_visible = true;
cl->m_format.setVisible(true);
m_partFeat->addCenterLine(cl);
m_partFeat->recomputeFeature();
@@ -556,10 +556,10 @@ bool TaskCenterLine::reject()
}
else if (!getCreateMode() && m_partFeat) {
// restore the initial centerline
m_cl->m_format.m_color = (&orig_cl)->m_format.m_color;
m_cl->m_format.m_weight = (&orig_cl)->m_format.m_weight;
m_cl->m_format.setColor((&orig_cl)->m_format.getColor());
m_cl->m_format.setWidth((&orig_cl)->m_format.getWidth());
m_cl->m_format.setLineNumber((&orig_cl)->m_format.getLineNumber());
m_cl->m_format.m_visible = (&orig_cl)->m_format.m_visible;
m_cl->m_format.setVisible((&orig_cl)->m_format.getVisible());
m_cl->m_mode = (&orig_cl)->m_mode;
m_cl->m_rotate = (&orig_cl)->m_rotate;
m_cl->m_vShift = (&orig_cl)->m_vShift;

View File

@@ -132,14 +132,14 @@ void TaskCosVertex::updateUi()
ui->dsbY->setValue(y);
}
//! create the cv at an unscaled, unrotated position
//! create the cv as entered, addCosmeticVertex will invert it
void TaskCosVertex::addCosVertex(QPointF qPos)
{
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Add Cosmetic Vertex"));
Base::Vector3d pos = DU::invertY(DU::toVector3d(qPos));
// Base::Vector3d pos = DU::invertY(DU::toVector3d(qPos));
// int idx =
(void) m_baseFeat->addCosmeticVertex(pos);
(void) m_baseFeat->addCosmeticVertex(DU::toVector3d(qPos));
m_baseFeat->requestPaint();
Gui::Command::commitCommand();
@@ -233,17 +233,16 @@ void TaskCosVertex::onTrackerFinished(std::vector<QPointF> pts, QGIView* qgParen
//x, y are scene pos of dvp/dpgi
QPointF basePosScene(x, -y); //base position in scene coords
QPointF displace = dragEnd - basePosScene;
QPointF scenePosCV = displace;
QPointF scenePosCV = dragEnd - basePosScene;
// Invert Y value so the math works.
// scenePosCV is effectively a scaled (and rotated) value
Base::Vector3d posToRotate = DU::invertY(DU::toVector3d(scenePosCV));
// Invert Y value so the math works.
// scenePosCV is effectively a scaled (and rotated), inverted value
// Base::Vector3d posToRotate = DU::invertY(DU::toVector3d(scenePosCV));
// unscale and rotate the picked point
posToRotate = CosmeticVertex::makeCanonicalPoint(m_baseFeat, posToRotate);
Base::Vector3d posToRotate = CosmeticVertex::makeCanonicalPointInverted(m_baseFeat, DU::toVector3d(scenePosCV));
// now put Y value back to display form
scenePosCV = DU::toQPointF(DU::invertY(posToRotate));
scenePosCV = DU::toQPointF(posToRotate);
m_savePoint = Rez::appX(scenePosCV);
updateUi();
@@ -309,11 +308,11 @@ bool TaskCosVertex::accept()
return false;
removeTracker();
// whatever is in the ui for x,y is treated as an unscaled, unrotated, invertedY position.
// whatever is in the ui for x,y is treated as an unscaled, unrotated, conventional Y position.
// the position from the tracker is unscaled & unrotated before updating the ui
double x = ui->dsbX->value().getValue();
double y = ui->dsbY->value().getValue();
QPointF uiPoint(x, -y);
QPointF uiPoint(x, y);
addCosVertex(uiPoint);

View File

@@ -22,14 +22,17 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cmath>
# include <BRepBuilderAPI_MakeEdge.hxx>
#endif
#include <QMessageBox>
#include <Base/Console.h>
#include <Base/Tools.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Command.h>
#include <Gui/Document.h>
#include <Gui/MainWindow.h>
#include <Gui/Selection.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include <Mod/TechDraw/App/DrawViewPart.h>
@@ -66,18 +69,22 @@ TaskCosmeticCircle::TaskCosmeticCircle(TechDraw::DrawViewPart* partFeat,
ui->setupUi(this);
setUiEdit();
connect(ui->qsbRadius, qOverload<double>(&QuantitySpinBox::valueChanged),
this, &TaskCosmeticCircle::radiusChanged);
}
//ctor for creation
TaskCosmeticCircle::TaskCosmeticCircle(TechDraw::DrawViewPart* partFeat,
Base::Vector3d center, bool is3d) :
std::vector<Base::Vector3d> points, bool is3d) :
ui(new Ui_TaskCosmeticCircle),
m_partFeat(partFeat),
m_ce(nullptr),
m_saveCE(nullptr),
m_center(center),
m_createMode(true),
m_is3d(is3d)
m_is3d(is3d),
m_points(points)
{
//existence of partFeat is checked in calling command
@@ -110,35 +117,45 @@ void TaskCosmeticCircle::changeEvent(QEvent *e)
void TaskCosmeticCircle::setUiPrimary()
{
setWindowTitle(QObject::tr("Create Cosmetic Circle"));
// Base::Console().Message("TCC::setUiPrimary() - m_center: %s is3d: %d\n",
// DU::formatVector(m_center).c_str(), m_is3d);
double rotDeg = m_partFeat->Rotation.getValue();
double rotRad = rotDeg * M_PI / 180.0;
Base::Vector3d centroid = m_partFeat->getCurrentCentroid();
Base::Vector3d p1;
std::vector<Base::Vector3d> displayPoints;
std::vector<Base::Vector3d> mathPoints;
for (auto& point : m_points) {
// use conventional coordinates for calculations
mathPoints.push_back(DU::invertY(point));
}
if (!m_points.empty()) {
m_center = m_points.front();
}
Base::Vector3d displayCenter;
if (m_is3d) {
// center, project and invert the 3d point
p1 = DrawUtil::invertY(m_partFeat->projectPoint(m_center - centroid));
ui->rb2d1->setChecked(false);
ui->rb3d1->setChecked(true);
// center, project and invert the 3d point
Base::Vector3d centroid = m_partFeat->getCurrentCentroid();
displayCenter = m_partFeat->projectPoint(mathPoints[0] - centroid, false);
} else {
// invert, unscale and unrotate the selected 2d point
// shift by centroid?
p1 = DU::invertY(m_center) / m_partFeat->getScale();
if (rotDeg != 0.0) {
// we always rotate around the origin.
p1.RotateZ(-rotRad);
}
ui->rb2d1->setChecked(true);
ui->rb3d1->setChecked(false);
// if the points are selected from 2d, they are already inverted
// unscale and unrotate the selected 2d point
displayCenter = CosmeticVertex::makeCanonicalPointInverted(m_partFeat, m_center);
displayCenter = DU::invertY(displayCenter);
}
ui->qsbCenterX->setUnit(Base::Unit::Length);
ui->qsbCenterX->setValue(p1.x);
ui->qsbCenterX->setValue(displayCenter.x);
ui->qsbCenterY->setUnit(Base::Unit::Length);
ui->qsbCenterY->setValue(p1.y);
ui->qsbCenterY->setValue(displayCenter.y);
ui->qsbCenterY->setUnit(Base::Unit::Length);
ui->qsbCenterZ->setValue(p1.z);
ui->qsbCenterZ->setValue(displayCenter.z);
double radius = (mathPoints[1] - mathPoints[0]).Length() / m_partFeat->getScale();
ui->qsbRadius->setValue(radius);
ui->qsbStartAngle->setValue(Base::toDegrees(DU::angleWithX(mathPoints[1] - mathPoints[0])));
ui->qsbEndAngle->setValue(Base::toDegrees(DU::angleWithX(mathPoints[2] - mathPoints[0])));
}
void TaskCosmeticCircle::setUiEdit()
@@ -155,44 +172,59 @@ void TaskCosmeticCircle::setUiEdit()
ui->qsbRadius->setValue(m_ce->permaRadius);
double angleDeg = m_ce->m_geometry->getStartAngle() * 180.0 / M_PI;
ui->qsbStartAngle->setValue(angleDeg);
angleDeg = m_ce->m_geometry->getEndAngle() * 180.0 / M_PI;
ui->qsbEndAngle->setValue(angleDeg);
ui->qsbStartAngle->setValue(Base::toDegrees(m_ce->m_geometry->getStartAngle()));
ui->qsbEndAngle->setValue(Base::toDegrees(m_ce->m_geometry->getEndAngle()));
}
void TaskCosmeticCircle::radiusChanged()
{
if (ui->qsbRadius->value().getValue() <= 0.0) {
QString msg = tr("Radius must be non-zero positive number");
QMessageBox::critical(Gui::getMainWindow(), QObject::tr("Parameter Error"), msg);
}
}
//******************************************************************************
void TaskCosmeticCircle::createCosmeticCircle(void)
{
// Base::Console().Message("TCL::createCosmeticCircle()\n");
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create Cosmetic Line"));
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create Cosmetic Circle"));
// point from Page/View is conventional coordinates (Y+ up), unscaled, unrotated, but centered (Csriz)
// this is Canonical form with out inversion.
// point from 3d is OXYZ and needs to be projected.
double x = ui->qsbCenterX->value().getValue();
double y = ui->qsbCenterY->value().getValue();
double z = ui->qsbCenterZ->value().getValue();
Base::Vector3d p0(x, y, z);
Base::Vector3d center(x, y, z);
if (ui->rb3d1->isChecked()) {
Base::Vector3d centroid = m_partFeat->getCurrentCentroid();
center = m_partFeat->projectPoint(center - centroid);
}
TechDraw::BaseGeomPtr bg;
if (ui->qsbStartAngle->value().getValue() == 0.0 &&
ui->qsbEndAngle->value().getValue() == 0.0) {
bg = std::make_shared<TechDraw::Circle> (p0, ui->qsbRadius->value().getValue());
bg = std::make_shared<TechDraw::Circle> (center, ui->qsbRadius->value().getValue());
} else {
bg = std::make_shared<TechDraw::AOC>(p0, ui->qsbRadius->value().getValue(),
ui->qsbStartAngle->value().getValue(),
ui->qsbEndAngle->value().getValue());
bg = std::make_shared<TechDraw::AOC>(center, ui->qsbRadius->value().getValue(),
ui->qsbStartAngle->value().getValue(),
ui->qsbEndAngle->value().getValue());
}
// note cEdges are inverted when added to the dvp geometry, so we need to
// invert them here
// after all the calculations are done, we invert the geometry
m_tag = m_partFeat->addCosmeticEdge(bg->inverted());
m_ce = m_partFeat->getCosmeticEdge(m_tag);
m_ce->setFormat(LineFormat::getCurrentLineFormat());
Gui::Command::commitCommand();
}
void TaskCosmeticCircle::updateCosmeticCircle(void)
{
// Base::Console().Message("TCL::updateCosmeticCircle()\n");
// Base::Console().Message("TCL::updateCosmeticCircle()\n");
double x = ui->qsbCenterX->value().getValue();
double y = ui->qsbCenterY->value().getValue();
double z = ui->qsbCenterZ->value().getValue();
@@ -211,7 +243,6 @@ void TaskCosmeticCircle::updateCosmeticCircle(void)
ui->qsbEndAngle->value().getValue());
}
m_ce->m_geometry = bg->inverted();
p0 = DU::invertY(p0);
m_ce->permaStart = p0;
m_ce->permaEnd = p0;
}
@@ -220,6 +251,12 @@ void TaskCosmeticCircle::updateCosmeticCircle(void)
bool TaskCosmeticCircle::accept()
{
if (ui->qsbRadius->value().getValue() <= 0.0) {
// this won't work!
Base::Console().Error("TaskCosmeticCircle - can not create a circle with radius: %.3f\n",
ui->qsbRadius->value().getValue());
return false;
}
if (m_createMode) {
createCosmeticCircle();
m_partFeat->add1CEToGE(m_tag);
@@ -248,11 +285,11 @@ bool TaskCosmeticCircle::reject()
}
////////////////////////////////////////////////////////////////////////////////
TaskDlgCosmeticCircle::TaskDlgCosmeticCircle(TechDraw::DrawViewPart* partFeat,
Base::Vector3d point,
std::vector<Base::Vector3d> points,
bool is3d)
: TaskDialog()
{
widget = new TaskCosmeticCircle(partFeat, point, is3d);
widget = new TaskCosmeticCircle(partFeat, points, is3d);
taskbox = new Gui::TaskView::TaskBox(Gui::BitmapFactory().pixmap("actions/TechDraw_CosmeticCircle"),
widget->windowTitle(), true, nullptr);
taskbox->groupLayout()->addWidget(widget);

View File

@@ -55,7 +55,7 @@ class TaskCosmeticCircle : public QWidget
public:
TaskCosmeticCircle(TechDraw::DrawViewPart* partFeat,
Base::Vector3d center, bool is3d);
std::vector<Base::Vector3d> points, bool is3d);
TaskCosmeticCircle(TechDraw::DrawViewPart* partFeat,
std::string circleName);
~TaskCosmeticCircle() override;
@@ -64,6 +64,9 @@ public:
virtual bool reject();
void updateTask();
protected Q_SLOTS:
void radiusChanged();
protected:
void changeEvent(QEvent *e) override;
@@ -85,6 +88,7 @@ private:
bool m_createMode;
std::string m_tag;
bool m_is3d;
std::vector<Base::Vector3d> m_points;
};
class TaskDlgCosmeticCircle : public Gui::TaskView::TaskDialog
@@ -93,7 +97,7 @@ class TaskDlgCosmeticCircle : public Gui::TaskView::TaskDialog
public:
TaskDlgCosmeticCircle(TechDraw::DrawViewPart* partFeat,
Base::Vector3d center, bool is3d);
std::vector<Base::Vector3d> points, bool is3d);
TaskDlgCosmeticCircle(TechDraw::DrawViewPart* partFeat,
std::string circleName)
; ~TaskDlgCosmeticCircle() override;

View File

@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>350</width>
<height>368</height>
<height>390</height>
</rect>
</property>
<property name="sizePolicy">
@@ -104,9 +104,6 @@
</item>
<item row="0" column="1">
<widget class="Gui::QuantitySpinBox" name="qsbCenterX">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="unit" stdset="0">
<string notr="true"/>
</property>
@@ -121,9 +118,6 @@
</item>
<item row="1" column="1">
<widget class="Gui::QuantitySpinBox" name="qsbCenterY">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="unit" stdset="0">
<string notr="true"/>
</property>
@@ -138,9 +132,6 @@
</item>
<item row="2" column="1">
<widget class="Gui::QuantitySpinBox" name="qsbCenterZ">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="unit" stdset="0">
<string notr="true"/>
</property>
@@ -159,12 +150,12 @@
</item>
<item row="0" column="1">
<widget class="Gui::QuantitySpinBox" name="qsbRadius">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="unit" stdset="0">
<string notr="true"/>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="value">
<double>10.000000000000000</double>
</property>
@@ -174,41 +165,11 @@
</item>
<item>
<layout class="QGridLayout" name="gridLayout_5" columnstretch="1,0">
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Start Angle:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Gui::QuantitySpinBox" name="qsbEndAngle">
<property name="toolTip">
<string>End angle (conventional) of arc in degrees.</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="unit" stdset="0">
<string notr="true"/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>End Angle:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Gui::QuantitySpinBox" name="qsbStartAngle">
<property name="toolTip">
<string>Start angle (conventional) of arc in degrees.</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="unit" stdset="0">
<string notr="true"/>
</property>
@@ -221,6 +182,40 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>End Angle:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Gui::QuantitySpinBox" name="qsbEndAngle">
<property name="toolTip">
<string>End angle (conventional) of arc in degrees.</string>
</property>
<property name="unit" stdset="0">
<string notr="true"/>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Start Angle:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="cbClockwise">
<property name="toolTip">
<string>Check this box to make an arc from atart angle to end angle in a clockwise direction.</string>
</property>
<property name="text">
<string>Clockwise Angle</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
@@ -245,8 +240,6 @@
<header>Gui/QuantitySpinBox.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="Resources/TechDraw.qrc"/>
</resources>
<resources/>
<connections/>
</ui>

View File

@@ -112,50 +112,40 @@ void TaskCosmeticLine::setUiPrimary()
{
setWindowTitle(QObject::tr("Create Cosmetic Line"));
double rotDeg = m_partFeat->Rotation.getValue();
double rotRad = rotDeg * M_PI / 180.0;
// double rotDeg = m_partFeat->Rotation.getValue();
// double rotRad = rotDeg * M_PI / 180.0;
Base::Vector3d centroid = m_partFeat->getCurrentCentroid();
Base::Vector3d p1, p2;
if (m_is3d.front()) {
// center, project and invert the 3d point
p1 = DrawUtil::invertY(m_partFeat->projectPoint(m_points.front() - centroid));
ui->rb2d1->setChecked(false);
ui->rb3d1->setChecked(true);
p1 = m_partFeat->projectPoint(m_points.front() - centroid);
} else {
// invert, unscale and unrotate the selected 2d point
p1 = DU::invertY(m_points.front()) / m_partFeat->getScale();
if (rotDeg != 0.0) {
// we always rotate around the origin.
p1.RotateZ(-rotRad);
}
ui->rb2d1->setChecked(true);
ui->rb3d1->setChecked(false);
// if the points are selected from 2d, they are already inverted
// unscale and unrotate the selected 2d point
p1 = CosmeticVertex::makeCanonicalPointInverted(m_partFeat, m_points.front());
}
if (m_is3d.back()) {
p2 = DrawUtil::invertY(m_partFeat->projectPoint(m_points.back() - centroid));
ui->rb2d2->setChecked(false);
ui->rb3d2->setChecked(true);
p2 = m_partFeat->projectPoint(m_points.back() - centroid);
} else {
p2 = DU::invertY(m_points.back()) / m_partFeat->getScale();
if (rotDeg != 0.0) {
p2.RotateZ(-rotRad);
}
ui->rb2d2->setChecked(true);
ui->rb3d2->setChecked(false);
p2 = CosmeticVertex::makeCanonicalPointInverted(m_partFeat, m_points.back());
}
// 3d points are projected above, so they are now 2d point and we need to set the radio buttons appropriately
ui->rb2d1->setChecked(true);
ui->rb3d1->setChecked(false);
ui->qsbx1->setUnit(Base::Unit::Length);
ui->qsbx1->setValue(p1.x);
ui->qsby1->setUnit(Base::Unit::Length);
ui->qsby1->setValue(p1.y);
ui->qsby1->setValue(-p1.y);
ui->qsby1->setUnit(Base::Unit::Length);
ui->qsbz1->setValue(p1.z);
ui->qsbx2->setUnit(Base::Unit::Length);
ui->qsbx2->setValue(p2.x);
ui->qsby2->setUnit(Base::Unit::Length);
ui->qsby2->setValue(p2.y);
ui->qsby2->setValue(-p2.y);
ui->qsbz2->setUnit(Base::Unit::Length);
ui->qsbz2->setValue(p2.z);
}
@@ -181,50 +171,72 @@ void TaskCosmeticLine::setUiEdit()
}
//******************************************************************************
void TaskCosmeticLine::createCosmeticLine(void)
void TaskCosmeticLine::createCosmeticLine()
{
// Base::Console().Message("TCL::createCosmeticLine()\n");
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create Cosmetic Line"));
// ui 2d points are interpreted as unscaled, unrotated, uninverted
double x = ui->qsbx1->value().getValue();
double y = ui->qsby1->value().getValue();
double z = ui->qsbz1->value().getValue();
Base::Vector3d p0(x, y, z);
if (ui->rb3d1->isChecked()) {
Base::Vector3d centroid = m_partFeat->getCurrentCentroid();
p0 = m_partFeat->projectPoint(p0 - centroid);
} else {
p0 = DU::invertY(p0);
}
x = ui->qsbx2->value().getValue();
y = ui->qsby2->value().getValue();
z = ui->qsbz2->value().getValue();
Base::Vector3d p1(x, y, z);
if (ui->rb3d2->isChecked()) {
Base::Vector3d centroid = m_partFeat->getCurrentCentroid();
p1 = m_partFeat->projectPoint(p1 - centroid);
} else {
p1 = DU::invertY(p1);
}
m_tag = m_partFeat->addCosmeticEdge(p0, p1);
m_ce = m_partFeat->getCosmeticEdge(m_tag);
m_ce->setFormat(LineFormat::getCurrentLineFormat());
Gui::Command::commitCommand();
}
void TaskCosmeticLine::updateCosmeticLine(void)
void TaskCosmeticLine::updateCosmeticLine()
{
// Base::Console().Message("TCL::updateCosmeticLine()\n");
double x = ui->qsbx1->value().getValue();
double y = ui->qsby1->value().getValue();
double z = ui->qsbz1->value().getValue();
Base::Vector3d p0(x, y, z);
p0 = DrawUtil::invertY(p0);
if (ui->rb3d1->isChecked()) {
Base::Vector3d centroid = m_partFeat->getCurrentCentroid();
p0 = m_partFeat->projectPoint(p0 - centroid);
} else {
p0 = DU::invertY(p0);
}
x = ui->qsbx2->value().getValue();
y = ui->qsby2->value().getValue();
z = ui->qsbz2->value().getValue();
Base::Vector3d p1(x, y, z);
p1 = DrawUtil::invertY(p1);
if (ui->rb3d2->isChecked()) {
Base::Vector3d centroid = m_partFeat->getCurrentCentroid();
p1 = m_partFeat->projectPoint(p1 - centroid);
} else {
p1 = DU::invertY(p1);
}
//replace the geometry
m_ce->permaStart = p0;
m_ce->permaEnd = p1;
gp_Pnt gp1(p0.x, p0.y, p0.z);
gp_Pnt gp2(p1.x, p1.y, p1.z);
TopoDS_Edge e = BRepBuilderAPI_MakeEdge(gp1, gp2);
m_ce->m_geometry = TechDraw::BaseGeom::baseFactory(e);
TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(gp1, gp2);
m_ce->m_geometry = TechDraw::BaseGeom::baseFactory(edge);
}
//******************************************************************************

View File

@@ -64,8 +64,11 @@
<bool>true</bool>
</property>
<property name="autoExclusive">
<bool>false</bool>
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item row="0" column="1">
@@ -74,8 +77,11 @@
<string>3d Point</string>
</property>
<property name="autoExclusive">
<bool>false</bool>
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
</layout>
@@ -90,7 +96,7 @@
</widget>
</item>
<item row="0" column="1">
<widget class="Gui::QuantitySpinBox" name="qsbx1">
<widget class="Gui::QuantitySpinBox" name="qsbx1" native="true">
<property name="unit" stdset="0">
<string notr="true"/>
</property>
@@ -104,7 +110,7 @@
</widget>
</item>
<item row="1" column="1">
<widget class="Gui::QuantitySpinBox" name="qsby1">
<widget class="Gui::QuantitySpinBox" name="qsby1" native="true">
<property name="unit" stdset="0">
<string notr="true"/>
</property>
@@ -118,7 +124,7 @@
</widget>
</item>
<item row="2" column="1">
<widget class="Gui::QuantitySpinBox" name="qsbz1">
<widget class="Gui::QuantitySpinBox" name="qsbz1" native="true">
<property name="unit" stdset="0">
<string notr="true"/>
</property>
@@ -137,8 +143,11 @@
<bool>true</bool>
</property>
<property name="autoExclusive">
<bool>false</bool>
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup_2</string>
</attribute>
</widget>
</item>
<item row="0" column="1">
@@ -147,8 +156,11 @@
<string>3d Point</string>
</property>
<property name="autoExclusive">
<bool>false</bool>
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup_2</string>
</attribute>
</widget>
</item>
</layout>
@@ -163,7 +175,7 @@
</widget>
</item>
<item row="0" column="1">
<widget class="Gui::QuantitySpinBox" name="qsbx2">
<widget class="Gui::QuantitySpinBox" name="qsbx2" native="true">
<property name="unit" stdset="0">
<string notr="true"/>
</property>
@@ -177,7 +189,7 @@
</widget>
</item>
<item row="1" column="1">
<widget class="Gui::QuantitySpinBox" name="qsby2">
<widget class="Gui::QuantitySpinBox" name="qsby2" native="true">
<property name="unit" stdset="0">
<string notr="true"/>
</property>
@@ -191,7 +203,7 @@
</widget>
</item>
<item row="2" column="1">
<widget class="Gui::QuantitySpinBox" name="qsbz2">
<widget class="Gui::QuantitySpinBox" name="qsbz2" native="true">
<property name="unit" stdset="0">
<string notr="true"/>
</property>
@@ -221,8 +233,10 @@
<header>Gui/QuantitySpinBox.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="Resources/TechDraw.qrc"/>
</resources>
<resources/>
<connections/>
<buttongroups>
<buttongroup name="buttonGroup"/>
<buttongroup name="buttonGroup_2"/>
</buttongroups>
</ui>

View File

@@ -22,7 +22,6 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cmath>
# include <QStatusBar>
#endif
@@ -40,6 +39,7 @@
#include <Mod/TechDraw/App/DrawPage.h>
#include <Mod/TechDraw/App/DrawView.h>
#include <Mod/TechDraw/App/LineGroup.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include "TaskLeaderLine.h"
#include "ui_TaskLeaderLine.h"
@@ -58,21 +58,24 @@
using namespace Gui;
using namespace TechDraw;
using namespace TechDrawGui;
using DU = DrawUtil;
using DGU = DrawGuiUtil;
constexpr int MessageDisplayTime{3000};
//ctor for edit
TaskLeaderLine::TaskLeaderLine(TechDrawGui::ViewProviderLeader* leadVP) :
ui(new Ui_TaskLeaderLine),
m_tracker(nullptr),
m_lineVP(leadVP),
m_baseFeat(nullptr),
m_basePage(nullptr),
m_lineFeat(nullptr),
m_lineFeat(m_lineVP->getFeature()),
m_qgParent(nullptr),
m_createMode(false),
m_trackerMode(QGTracker::None),
m_saveContextPolicy(Qt::DefaultContextMenu),
m_inProgressLock(false),
m_qgLine(nullptr),
m_qgLeader(nullptr),
m_btnOK(nullptr),
m_btnCancel(nullptr),
m_pbTrackerState(TrackerAction::EDIT),
@@ -81,7 +84,6 @@ TaskLeaderLine::TaskLeaderLine(TechDrawGui::ViewProviderLeader* leadVP) :
{
//existence of leadVP is guaranteed by caller being ViewProviderLeaderLine.setEdit
m_lineFeat = m_lineVP->getFeature();
m_basePage = m_lineFeat->findParentPage();
if (!m_basePage) {
@@ -127,8 +129,9 @@ TaskLeaderLine::TaskLeaderLine(TechDrawGui::ViewProviderLeader* leadVP) :
saveState();
m_trackerMode = QGTracker::TrackerMode::Line;
if (m_vpp->getMDIViewPage())
if (m_vpp->getMDIViewPage()) {
m_saveContextPolicy = m_vpp->getMDIViewPage()->contextMenuPolicy();
}
}
//ctor for creation
@@ -145,7 +148,7 @@ TaskLeaderLine::TaskLeaderLine(TechDraw::DrawView* baseFeat,
m_trackerMode(QGTracker::None),
m_saveContextPolicy(Qt::DefaultContextMenu),
m_inProgressLock(false),
m_qgLine(nullptr),
m_qgLeader(nullptr),
m_btnOK(nullptr),
m_btnCancel(nullptr),
m_pbTrackerState(TrackerAction::PICK),
@@ -158,7 +161,6 @@ TaskLeaderLine::TaskLeaderLine(TechDraw::DrawView* baseFeat,
Gui::ViewProvider* vp = activeGui->getViewProvider(m_basePage);
m_vpp = static_cast<ViewProviderPage*>(vp);
m_qgParent = nullptr;
if (m_baseFeat) {
m_qgParent = m_vpp->getQGSPage()->findQViewForDocObj(baseFeat);
}
@@ -174,8 +176,9 @@ TaskLeaderLine::TaskLeaderLine(TechDraw::DrawView* baseFeat,
ui->pbCancelEdit->setEnabled(false);
m_trackerMode = QGTracker::TrackerMode::Line;
if (m_vpp->getMDIViewPage())
if (m_vpp->getMDIViewPage()) {
m_saveContextPolicy = m_vpp->getMDIViewPage()->contextMenuPolicy();
}
}
void TaskLeaderLine::saveState()
@@ -231,7 +234,7 @@ void TaskLeaderLine::setUiPrimary()
}
DrawGuiUtil::loadArrowBox(ui->cboxStartSym);
int aStyle = getPrefArrowStyle();
int aStyle = PreferencesGui::dimArrowStyle();
ui->cboxStartSym->setCurrentIndex(aStyle);
DrawGuiUtil::loadArrowBox(ui->cboxEndSym);
@@ -239,9 +242,9 @@ void TaskLeaderLine::setUiPrimary()
ui->dsbWeight->setUnit(Base::Unit::Length);
ui->dsbWeight->setMinimum(0);
ui->dsbWeight->setValue(prefWeight());
ui->dsbWeight->setValue(TechDraw::LineGroup::getDefaultWidth("Graphic"));
ui->cpLineColor->setColor(prefLineColor().asValue<QColor>());
ui->cpLineColor->setColor(PreferencesGui::leaderColor().asValue<QColor>());
}
//switch widgets related to ViewProvider on/off
@@ -332,9 +335,11 @@ void TaskLeaderLine::onLineStyleChanged()
//******************************************************************************
void TaskLeaderLine::createLeaderFeature(std::vector<Base::Vector3d> converted)
//! sceneDeltas are vector from first picked scene point (0,0) to the ith point.
//! sceneDeltas are in Qt scene coords (Rez and inverted Y).
void TaskLeaderLine::createLeaderFeature(std::vector<Base::Vector3d> sceneDeltas)
{
// Base::Console().Message("TTL::createLeaderFeature()\n");
// Base::Console().Message("TTL::createLeaderFeature()\n");
const std::string objectName{"LeaderLine"};
std::string m_leaderName = m_basePage->getDocument()->getUniqueObjectName(objectName.c_str());
m_leaderType = "TechDraw::DrawLeaderLine";
@@ -355,16 +360,29 @@ void TaskLeaderLine::createLeaderFeature(std::vector<Base::Vector3d> converted)
}
App::DocumentObject* obj = m_basePage->getDocument()->getObject(m_leaderName.c_str());
if (!obj)
if (!obj) {
throw Base::RuntimeError("TaskLeaderLine - new markup object not found");
}
if (obj->isDerivedFrom(TechDraw::DrawLeaderLine::getClassTypeId())) {
m_lineFeat = static_cast<TechDraw::DrawLeaderLine*>(obj);
m_lineFeat->setPosition(Rez::appX(m_attachPoint.x), Rez::appX(- m_attachPoint.y), true);
if (!converted.empty()) {
m_lineFeat->WayPoints.setValues(converted);
if (m_lineFeat->AutoHorizontal.getValue()) {
m_lineFeat->adjustLastSegment();
if (!sceneDeltas.empty()) {
std::vector<Base::Vector3d> pageDeltas;
// convert deltas to mm. leader points are stored inverted, so we do not convert to conventional Y axis
for (auto& delta : sceneDeltas) {
Base::Vector3d deltaInPageCoords = DGU::fromSceneCoords(delta, false);
pageDeltas.push_back(deltaInPageCoords);
}
// should just do this in place.
if (m_lineFeat->AutoHorizontal.getValue()) {
pageDeltas = DrawLeaderLine::horizLastSegment(pageDeltas);
// m_lineFeat->horizLastSegment();
}
// convert to unscaled, unrotated but inverted
auto temp = m_lineFeat->makeCanonicalPointsInverted(pageDeltas);
m_lineFeat->WayPoints.setValues(temp);
}
commonFeatureUpdate();
}
@@ -396,6 +414,15 @@ void TaskLeaderLine::createLeaderFeature(std::vector<Base::Vector3d> converted)
}
}
void TaskLeaderLine::dumpTrackerPoints(std::vector<Base::Vector3d>& tPoints) const
{
Base::Console().Message("TTL::dumpTrackerPoints(%d)\n", tPoints.size());
Base::Console().Message("TTL::dumpTrackerPoints - attach point: %s\n", DU::formatVector(m_attachPoint).c_str());
for (auto& point : tPoints) {
Base::Console().Message("TTL::dumpTrackerPoints - a point: %s\n", DU::formatVector(point).c_str());
}
}
void TaskLeaderLine::updateLeaderFeature()
{
// Base::Console().Message("TTL::updateLeaderFeature()\n");
@@ -428,8 +455,9 @@ void TaskLeaderLine::commonFeatureUpdate()
void TaskLeaderLine::removeFeature()
{
// Base::Console().Message("TTL::removeFeature()\n");
if (!m_lineFeat)
if (!m_lineFeat) {
return;
}
if (m_createMode) {
try {
@@ -462,8 +490,8 @@ void TaskLeaderLine::onTrackerClicked(bool clicked)
return;
}
if ( (m_pbTrackerState == TrackerAction::SAVE) &&
(getCreateMode()) ){
if ( m_pbTrackerState == TrackerAction::SAVE &&
getCreateMode() ){
if (m_tracker) {
m_tracker->terminateDrawing();
}
@@ -474,10 +502,12 @@ void TaskLeaderLine::onTrackerClicked(bool clicked)
setEditCursor(Qt::ArrowCursor);
return;
} else if ( (m_pbTrackerState == TrackerAction::SAVE) &&
(!getCreateMode()) ) { //edit mode
if (m_qgLine) {
m_qgLine->closeEdit();
}
if ( m_pbTrackerState == TrackerAction::SAVE &&
!getCreateMode() ) { //edit mode
if (m_qgLeader) {
m_qgLeader->closeEdit();
}
m_pbTrackerState = TrackerAction::PICK;
ui->pbTracker->setText(tr("Edit Points"));
@@ -499,33 +529,42 @@ void TaskLeaderLine::onTrackerClicked(bool clicked)
QString msg = tr("Pick a starting point for leader line");
getMainWindow()->statusBar()->show();
Gui::getMainWindow()->showMessage(msg, 3000);
Gui::getMainWindow()->showMessage(msg, MessageDisplayTime);
ui->pbTracker->setText(tr("Save Points"));
ui->pbTracker->setEnabled(true);
ui->pbCancelEdit->setEnabled(true);
m_pbTrackerState = TrackerAction::SAVE;
enableTaskButtons(false);
} else { //edit mode
m_trackerPoints = m_lineFeat->WayPoints.getValues();
if (!m_trackerPoints.empty()) { //regular edit session
// pageDeltas are in mm with conventional Y axis
auto pageDeltas = m_lineFeat->getScaledAndRotatedPoints();
m_sceneDeltas.clear();
m_sceneDeltas.reserve(pageDeltas.size());
// now convert to sceneUnits and Qt Y axis
for (auto& entry : pageDeltas) {
m_sceneDeltas.push_back(DGU::toSceneCoords(entry, false));
}
if (!m_sceneDeltas.empty()) { //regular edit session
m_inProgressLock = true;
m_saveContextPolicy = m_vpp->getMDIViewPage()->contextMenuPolicy();
m_vpp->getMDIViewPage()->setContextMenuPolicy(Qt::PreventContextMenu);
QGIView* qgiv = m_vpp->getQGSPage()->findQViewForDocObj(m_lineFeat);
QGILeaderLine* qgLead = dynamic_cast<QGILeaderLine*>(qgiv);
auto qgLead = dynamic_cast<QGILeaderLine*>(qgiv);
if (!qgLead) {
//tarfu
Base::Console().Error("TaskLeaderLine - can't find leader graphic\n");
//now what? throw will generate "unknown unhandled exception"
} else {
m_qgLine = qgLead;
m_qgLeader = qgLead;
connect(qgLead, &QGILeaderLine::editComplete,
this, &TaskLeaderLine::onPointEditComplete);
this, &TaskLeaderLine::onPointEditComplete);
qgLead->startPathEdit();
QString msg = tr("Click and drag markers to adjust leader line");
getMainWindow()->statusBar()->show();
Gui::getMainWindow()->showMessage(msg, 3000);
Gui::getMainWindow()->showMessage(msg, MessageDisplayTime);
ui->pbTracker->setText(tr("Save changes"));
ui->pbTracker->setEnabled(true);
ui->pbCancelEdit->setEnabled(true);
@@ -542,7 +581,7 @@ void TaskLeaderLine::onTrackerClicked(bool clicked)
QString msg = tr("Pick a starting point for leader line");
getMainWindow()->statusBar()->show();
Gui::getMainWindow()->showMessage(msg, 3000);
Gui::getMainWindow()->showMessage(msg, MessageDisplayTime);
ui->pbTracker->setText(tr("Save changes"));
ui->pbTracker->setEnabled(true);
ui->pbCancelEdit->setEnabled(true);
@@ -555,10 +594,13 @@ void TaskLeaderLine::onTrackerClicked(bool clicked)
void TaskLeaderLine::startTracker()
{
// Base::Console().Message("TTL::startTracker()\n");
if (!m_vpp->getQGSPage())
if (!m_vpp->getQGSPage()) {
return;
if (m_trackerMode == QGTracker::TrackerMode::None)
}
if (m_trackerMode == QGTracker::TrackerMode::None) {
return;
}
if (!m_tracker) {
m_tracker = new QGTracker(m_vpp->getQGSPage(), m_trackerMode);
@@ -573,24 +615,24 @@ void TaskLeaderLine::startTracker()
setEditCursor(Qt::CrossCursor);
QString msg = tr("Left click to set a point");
Gui::getMainWindow()->statusBar()->show();
Gui::getMainWindow()->showMessage(msg, 3000);
Gui::getMainWindow()->showMessage(msg, MessageDisplayTime);
}
void TaskLeaderLine::onTrackerFinished(std::vector<QPointF> pts, QGIView* qgParent)
void TaskLeaderLine::onTrackerFinished(std::vector<QPointF> trackerScenePoints, QGIView* qgParent)
{
//in this case, we already know who the parent is. We don't need QGTracker to tell us.
(void) qgParent;
// Base::Console().Message("TTL::onTrackerFinished() - parent: %X\n", qgParent);
if (pts.empty()) {
// Base::Console().Message("TTL::onTrackerFinished() - parent: %X\n", qgParent);
if (trackerScenePoints.empty()) {
Base::Console().Error("TaskLeaderLine - no points available\n");
return;
}
if (m_qgParent) {
double scale = m_qgParent->getScale();
QPointF mapped = m_qgParent->mapFromScene(pts.front()) / scale;
QPointF mapped = m_qgParent->mapFromScene(trackerScenePoints.front()) / scale;
m_attachPoint = Base::Vector3d(mapped.x(), mapped.y(), 0.0);
trackerPointsFromQPoints(pts);
m_sceneDeltas = scenePointsToDeltas(trackerScenePoints);
} else {
Base::Console().Message("TTL::onTrackerFinished - can't find parent graphic!\n");
//blow up!?
@@ -599,22 +641,30 @@ void TaskLeaderLine::onTrackerFinished(std::vector<QPointF> pts, QGIView* qgPare
QString msg = tr("Press OK or Cancel to continue");
getMainWindow()->statusBar()->show();
Gui::getMainWindow()->showMessage(msg, 3000);
Gui::getMainWindow()->showMessage(msg, MessageDisplayTime);
enableTaskButtons(true);
// ??? why does the tracker go to sleep when we are finished with it? why not removeTracker
m_tracker->sleep(true);
m_inProgressLock = false;
// can not pick points any more?
ui->pbTracker->setEnabled(false);
ui->pbCancelEdit->setEnabled(false);
// only option available to user is accept/reject?
enableTaskButtons(true);
setEditCursor(Qt::ArrowCursor);
setEditCursor(Qt::ArrowCursor); // already done by m_tracker->sleep()?
}
// this is called at every possible exit path?
void TaskLeaderLine::removeTracker()
{
// Base::Console().Message("TTL::removeTracker()\n");
if (!m_vpp->getQGSPage())
if (!m_vpp->getQGSPage()) {
return;
}
if (m_tracker && m_tracker->scene()) {
m_vpp->getQGSPage()->removeItem(m_tracker);
delete m_tracker;
@@ -643,13 +693,15 @@ void TaskLeaderLine::onCancelEditClicked(bool clicked)
QGIView* TaskLeaderLine::findParentQGIV()
{
if (!m_baseFeat)
if (!m_baseFeat) {
return nullptr;
}
Gui::ViewProvider* gvp = QGIView::getViewProvider(m_baseFeat);
ViewProviderDrawingView* vpdv = dynamic_cast<ViewProviderDrawingView*>(gvp);
if (!vpdv)
if (!vpdv) {
return nullptr;
}
return vpdv->getQView();;
}
@@ -665,20 +717,23 @@ void TaskLeaderLine::setEditCursor(QCursor cursor)
}
}
//from 1:1 scale scene QPointF to zero origin Vector3d points
void TaskLeaderLine::trackerPointsFromQPoints(std::vector<QPointF> pts)
//from scene QPointF to zero origin (delta from p0) Vector3d points
std::vector<Base::Vector3d> TaskLeaderLine::scenePointsToDeltas(std::vector<QPointF> scenePoints)
{
// Base::Console().Message("TTL::trackerPointsFromQPoints(%d)\n", pts.size());
m_trackerPoints.clear();
for (auto& p: pts) {
QPointF mapped = p - pts.front();
Base::Vector3d convert(mapped.x(), mapped.y(), 0.0);
m_trackerPoints.push_back(convert);
// Base::Console().Message("TTL::scenePointsToDeltas(%d)\n", pts.size());
std::vector<Base::Vector3d> result;
result.reserve(scenePoints.size());
for (auto& point: scenePoints) {
QPointF delta = point - scenePoints.front();
result.push_back(DU::toVector3d(delta));
}
return result;
}
//******************************************************************************
//void TaskLeaderLine::onPointEditComplete(std::vector<QPointF> pts, QGIView* parent)
//! point edit session completed. reset ui to initial state.
void TaskLeaderLine::onPointEditComplete()
{
// Base::Console().Message("TTL::onPointEditComplete()\n");
@@ -691,15 +746,20 @@ void TaskLeaderLine::onPointEditComplete()
enableTaskButtons(true);
}
//! give up on the current point editing session. reset the ui so we are in a state to
//! start editing points again. leave the existing tracker instance in place.
void TaskLeaderLine::abandonEditSession()
{
// Base::Console().Message("TTL::abandonEditSession()\n");
if (m_qgLine) {
m_qgLine->abandonEdit();
constexpr int MessageDuration{4000};
if (m_qgLeader) {
// tell the graphics item that we are giving up so it should do any clean up it needs.
m_qgLeader->abandonEdit();
}
QString msg = tr("In progress edit abandoned. Start over.");
getMainWindow()->statusBar()->show();
Gui::getMainWindow()->showMessage(msg, 4000);
Gui::getMainWindow()->showMessage(msg, MessageDuration);
m_pbTrackerState = TrackerAction::EDIT;
ui->pbTracker->setText(tr("Edit points"));
@@ -723,21 +783,6 @@ void TaskLeaderLine::enableTaskButtons(bool enable)
m_btnCancel->setEnabled(enable);
}
int TaskLeaderLine::getPrefArrowStyle()
{
return PreferencesGui::dimArrowStyle();
}
double TaskLeaderLine::prefWeight() const
{
return TechDraw::LineGroup::getDefaultWidth("Thin");
}
App::Color TaskLeaderLine::prefLineColor()
{
return PreferencesGui::leaderColor();
}
//******************************************************************************
bool TaskLeaderLine::accept()
@@ -759,7 +804,7 @@ bool TaskLeaderLine::accept()
updateLeaderFeature();
} else {
// removeTracker();
createLeaderFeature(m_trackerPoints);
createLeaderFeature(m_sceneDeltas);
}
m_trackerMode = QGTracker::TrackerMode::None;
removeTracker();

View File

@@ -57,6 +57,7 @@ class TaskLeaderLine : public QWidget
public:
TaskLeaderLine(TechDraw::DrawView* baseFeat,
TechDraw::DrawPage* page);
//ctor for edit
explicit TaskLeaderLine(TechDrawGui::ViewProviderLeader* leadVP);
~TaskLeaderLine() override = default;
@@ -76,13 +77,13 @@ public Q_SLOTS:
void onTrackerFinished(std::vector<QPointF> pts, TechDrawGui::QGIView* qgParent);
protected:
void trackerPointsFromQPoints(std::vector<QPointF> pts);
std::vector<Base::Vector3d> scenePointsToDeltas(std::vector<QPointF> pts);
void changeEvent(QEvent *event) override;
void startTracker();
void removeTracker();
void abandonEditSession();
void createLeaderFeature(std::vector<Base::Vector3d> converted);
void createLeaderFeature(std::vector<Base::Vector3d> sceneDeltas);
void updateLeaderFeature();
void commonFeatureUpdate();
void removeFeature();
@@ -93,50 +94,48 @@ protected:
void setEditCursor(QCursor cursor);
QGIView* findParentQGIV();
int getPrefArrowStyle();
double prefWeight() const;
App::Color prefLineColor();
void saveState();
void restoreState();
void dumpTrackerPoints(std::vector<Base::Vector3d>& tPoints) const;
protected Q_SLOTS:
void onPointEditComplete();
private:
std::unique_ptr<Ui_TaskLeaderLine> ui;
QGTracker* m_tracker;
ViewProviderPage* m_vpp;
ViewProviderLeader* m_lineVP;
TechDraw::DrawView* m_baseFeat;
TechDraw::DrawPage* m_basePage;
TechDraw::DrawLeaderLine* m_lineFeat;
std::string m_leaderName;
std::string m_leaderType;
QGIView* m_qgParent;
std::string m_qgParentName;
std::vector<Base::Vector3d> m_trackerPoints;
Base::Vector3d m_attachPoint;
bool m_createMode;
QGTracker::TrackerMode m_trackerMode;
Qt::ContextMenuPolicy m_saveContextPolicy;
bool m_inProgressLock;
QGILeaderLine* m_qgLeader;
QGILeaderLine* m_qgLine;
QPushButton* m_btnOK;
QPushButton* m_btnCancel;
int m_pbTrackerState;
std::vector<Base::Vector3d> m_savePoints;
double m_saveX;
double m_saveY;
ViewProviderPage* m_vpp;
std::string m_leaderName;
std::string m_leaderType;
std::string m_qgParentName;
std::vector<Base::Vector3d> m_sceneDeltas;
Base::Vector3d m_attachPoint;
std::vector<Base::Vector3d> m_savePoints;
private Q_SLOTS:
void onStartSymbolChanged();
void onEndSymbolChanged();

View File

@@ -22,7 +22,6 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cmath>
#endif // #ifndef _PreComp_
#include <Base/Console.h>
@@ -165,21 +164,22 @@ void TaskLineDecor::initializeRejectArrays()
}
}
// get the current line tool appearance default
void TaskLineDecor::getDefaults()
{
// Base::Console().Message("TLD::getDefaults()\n");
m_color = LineFormat::getDefEdgeColor();
m_weight = LineFormat::getDefEdgeWidth();
m_visible = true;
m_lineNumber = 1;
m_color = LineFormat::getCurrentLineFormat().getColor();
m_weight = LineFormat::getCurrentLineFormat().getWidth();
m_visible = LineFormat::getCurrentLineFormat().getVisible();
m_lineNumber = LineFormat::getCurrentLineFormat().getLineNumber();
//set defaults to format of 1st edge
if (!m_originalFormats.empty()) {
LineFormat &lf = m_originalFormats.front();
m_style = lf.m_style;
m_color = lf.m_color;
m_weight = lf.m_weight;
m_visible = lf.m_visible;
m_style = lf.getStyle();
m_color = lf.getColor();
m_weight = lf.getWidth();
m_visible = lf.getVisible();
m_lineNumber = lf.getLineNumber();
}
}
@@ -218,10 +218,10 @@ void TaskLineDecor::applyDecorations()
for (auto& e: m_edges) {
LineFormat *lf = getFormatAccessPtr(e);
if (lf) {
lf->m_style = m_style;
lf->m_color = m_color;
lf->m_weight = m_weight;
lf->m_visible = m_visible;
lf->setStyle(m_style);
lf->setColor(m_color);
lf->setWidth(m_weight);
lf->setVisible(m_visible);
lf->setLineNumber(m_lineNumber);
}
}
@@ -353,7 +353,7 @@ int TaskRestoreLines::countInvisibleGeoms()
int iGeoms = 0;
const std::vector<TechDraw::GeomFormat*> geoms = m_partFeat->GeomFormats.getValues();
for (auto& g : geoms) {
if (!g->m_format.m_visible) {
if (!g->m_format.getVisible()) {
iGeoms++;
}
}
@@ -365,7 +365,7 @@ int TaskRestoreLines::countInvisibleCosmetics()
int iCosmos = 0;
const std::vector<TechDraw::CosmeticEdge*> cosmos = m_partFeat->CosmeticEdges.getValues();
for (auto& c : cosmos) {
if (!c->m_format.m_visible) {
if (!c->m_format.getVisible()) {
iCosmos++;
}
}
@@ -377,7 +377,7 @@ int TaskRestoreLines::countInvisibleCenters()
int iCenter = 0;
const std::vector<TechDraw::CenterLine*> centers = m_partFeat->CenterLines.getValues();
for (auto& c : centers) {
if (!c->m_format.m_visible) {
if (!c->m_format.getVisible()) {
iCenter++;
}
}
@@ -395,8 +395,8 @@ void TaskRestoreLines::restoreInvisibleGeoms()
{
const std::vector<TechDraw::GeomFormat*> geoms = m_partFeat->GeomFormats.getValues();
for (auto& g : geoms) {
if (!g->m_format.m_visible) {
g->m_format.m_visible = true;
if (!g->m_format.getVisible()) {
g->m_format.setVisible(true);
}
}
m_partFeat->GeomFormats.setValues(geoms);
@@ -407,8 +407,8 @@ void TaskRestoreLines::restoreInvisibleCosmetics()
{
const std::vector<TechDraw::CosmeticEdge*> cosmos = m_partFeat->CosmeticEdges.getValues();
for (auto& c : cosmos) {
if (!c->m_format.m_visible) {
c->m_format.m_visible = true;
if (!c->m_format.getVisible()) {
c->m_format.setVisible(true);
}
}
m_partFeat->CosmeticEdges.setValues(cosmos);
@@ -419,8 +419,8 @@ void TaskRestoreLines::restoreInvisibleCenters()
{
const std::vector<TechDraw::CenterLine*> centers = m_partFeat->CenterLines.getValues();
for (auto& c : centers) {
if (!c->m_format.m_visible) {
c->m_format.m_visible = true;
if (!c->m_format.getVisible()) {
c->m_format.setVisible(true);
}
}
m_partFeat->CenterLines.setValues(centers);

View File

@@ -52,10 +52,7 @@ enum class EdgeColor {
yellow = 8
};
//===========================================================================
// managing global line attributes
//===========================================================================
// line attributes are now in App/LineFormat
//===========================================================================
// managing global dimension attributes
@@ -83,8 +80,7 @@ dimAttributes activeDimAttributes; // container holding dimension attributes
// TaskSelectLineAttributes
//===========================================================================
TaskSelectLineAttributes::TaskSelectLineAttributes(LineFormat *ptActiveAttributes) :
activeAttributes(ptActiveAttributes),
TaskSelectLineAttributes::TaskSelectLineAttributes() :
ui(new Ui_TaskSelectLineAttributes)
{
m_lineGenerator = new TechDraw::LineGenerator;
@@ -117,7 +113,7 @@ void TaskSelectLineAttributes::changeEvent(QEvent *e)
void TaskSelectLineAttributes::setUiEdit()
{
setWindowTitle(tr("Select line attributes"));
int lineStyle = activeAttributes->getStyle();
int lineStyle = LineFormat::getCurrentLineFormat().getStyle();
// line numbering starts at 1, not 0
DrawGuiUtil::loadLineStyleChoices(ui->cbLineStyle, m_lineGenerator);
if (ui->cbLineStyle->count() >= lineStyle ) {
@@ -129,7 +125,7 @@ void TaskSelectLineAttributes::setUiEdit()
ui->rbMiddle->setText(QString::fromUtf8("Middle %1").arg(QString::number(TechDraw::LineGroup::getDefaultWidth("Graphic"))));
ui->rbThick->setText(QString::fromUtf8("Thick %1").arg(QString::number(TechDraw::LineGroup::getDefaultWidth("Thick"))));
double lineWidth = activeAttributes->getWidth();
double lineWidth = LineFormat::getCurrentLineFormat().getWidth();
if (lineWidth <= TechDraw::LineGroup::getDefaultWidth("Thin")) {
ui->rbThin->setChecked(true);
} else if (lineWidth <= TechDraw::LineGroup::getDefaultWidth("Graphic")) {
@@ -140,7 +136,7 @@ void TaskSelectLineAttributes::setUiEdit()
ui->rbMiddle->setChecked(true);
}
QColor lineColor = activeAttributes->getQColor();
QColor lineColor = LineFormat::getCurrentLineFormat().getQColor();
ui->cbColor->setColor(lineColor);
double cascadeSpacing = activeDimAttributes.getCascadeSpacing();
@@ -152,26 +148,26 @@ void TaskSelectLineAttributes::setUiEdit()
bool TaskSelectLineAttributes::accept()
{
activeAttributes->setStyle(ui->cbLineStyle->currentIndex() + 1);
activeAttributes->setLineNumber(ui->cbLineStyle->currentIndex() + 1);
LineFormat::getCurrentLineFormat().setStyle(ui->cbLineStyle->currentIndex() + 1);
LineFormat::getCurrentLineFormat().setLineNumber(ui->cbLineStyle->currentIndex() + 1);
if (ui->rbThin->isChecked()){
activeAttributes->setWidth(TechDraw::LineGroup::getDefaultWidth("Thin"));
LineFormat::getCurrentLineFormat().setWidth(TechDraw::LineGroup::getDefaultWidth("Thin"));
}
else if (ui->rbMiddle->isChecked()){
activeAttributes->setWidth(TechDraw::LineGroup::getDefaultWidth("Graphic"));
LineFormat::getCurrentLineFormat().setWidth(TechDraw::LineGroup::getDefaultWidth("Graphic"));
}
else if (ui->rbThick->isChecked()){
activeAttributes->setWidth(TechDraw::LineGroup::getDefaultWidth("Thick"));
LineFormat::getCurrentLineFormat().setWidth(TechDraw::LineGroup::getDefaultWidth("Thick"));
}
else {
activeAttributes->setWidth(TechDraw::LineGroup::getDefaultWidth("Graphic"));
LineFormat::getCurrentLineFormat().setWidth(TechDraw::LineGroup::getDefaultWidth("Graphic"));
}
QColor qTemp = ui->cbColor->color();
App::Color temp;
temp.set(qTemp.redF(), qTemp.greenF(), qTemp.blueF(), 1.0 - qTemp.alphaF());
activeAttributes->setColor(temp);
LineFormat::getCurrentLineFormat().setColor(temp);
double cascadeSpacing = ui->sbSpacing->value();
activeDimAttributes.setCascadeSpacing(cascadeSpacing);
@@ -190,10 +186,10 @@ bool TaskSelectLineAttributes::reject()
// TaskDlgSelectLineAttributes
//===========================================================================
TaskDlgSelectLineAttributes::TaskDlgSelectLineAttributes(LineFormat *ptActiveAttributes)
TaskDlgSelectLineAttributes::TaskDlgSelectLineAttributes()
: TaskDialog()
{
widget = new TaskSelectLineAttributes(ptActiveAttributes);
widget = new TaskSelectLineAttributes();
taskbox = new Gui::TaskView::TaskBox(Gui::BitmapFactory().pixmap("TechDraw_ExtensionSelectLineAttributes"),
widget->windowTitle(), true, nullptr);
taskbox->groupLayout()->addWidget(widget);

View File

@@ -94,7 +94,7 @@ class TaskSelectLineAttributes : public QWidget
Q_OBJECT
public:
explicit TaskSelectLineAttributes(TechDraw::LineFormat* ptActiveAttributes);
explicit TaskSelectLineAttributes();
~TaskSelectLineAttributes() override;
virtual bool accept();
@@ -102,13 +102,11 @@ public:
void updateTask();
protected:
void changeEvent(QEvent *e) override;
void changeEvent(QEvent *event) override;
void setUiEdit();
private:
// lineAttributes* activeAttributes;
TechDraw::LineFormat* activeAttributes;
std::unique_ptr<Ui_TaskSelectLineAttributes> ui;
TechDraw::LineGenerator* m_lineGenerator;
@@ -119,7 +117,7 @@ class TaskDlgSelectLineAttributes : public Gui::TaskView::TaskDialog
Q_OBJECT
public:
explicit TaskDlgSelectLineAttributes(TechDraw::LineFormat * ptActiveAttributes);
explicit TaskDlgSelectLineAttributes();
~TaskDlgSelectLineAttributes() override;
public:

View File

@@ -72,14 +72,11 @@ ViewProviderLeader::ViewProviderLeader()
LineStyle.setEnums(LineStyleEnums);
ADD_PROPERTY_TYPE(LineStyle, (1), group, (App::PropertyType)(App::Prop_None), "Line style");
ADD_PROPERTY_TYPE(Color, (getDefLineColor()), group, App::Prop_None, "Color of the Markup");
ADD_PROPERTY_TYPE(UseOldCoords, (false), group, App::Prop_None, "Set to true for older documents ");
StackOrder.setValue(ZVALUE::DIMENSION);
}
ViewProviderLeader::~ViewProviderLeader()
{
}
bool ViewProviderLeader::setEdit(int ModNum)
{
// Base::Console().Message("VPL::setEdit(%d)\n", ModNum);
@@ -88,7 +85,8 @@ bool ViewProviderLeader::setEdit(int ModNum)
}
if (Gui::Control().activeDialog()) {
return false; //TaskPanel already open!
// a TaskPanel is already open!
return false;
}
Gui::Selection().clearSelection();
Gui::Control().showDialog(new TaskDlgLeaderLine(this));
@@ -106,7 +104,8 @@ void ViewProviderLeader::onChanged(const App::Property* p)
{
if ((p == &Color) ||
(p == &LineWidth) ||
(p == &LineStyle)) {
(p == &LineStyle) ||
(p == &UseOldCoords)) {
QGIView* qgiv = getQView();
if (qgiv) {
qgiv->updateView(true);
@@ -123,21 +122,23 @@ std::vector<App::DocumentObject*> ViewProviderLeader::claimChildren() const
std::vector<App::DocumentObject*> temp;
const std::vector<App::DocumentObject *> &views = getFeature()->getInList();
try {
for(std::vector<App::DocumentObject *>::const_iterator it = views.begin(); it != views.end(); ++it) {
auto view = dynamic_cast<TechDraw::DrawView *>(*it);
for(auto& docobj : views) {
auto view = dynamic_cast<TechDraw::DrawView *>(docobj);
if (view && view->claimParent() == getViewObject()) {
// if we are the item's owner, we should add the item to our child list
temp.push_back(view);
continue;
}
if ((*it)->isDerivedFrom<TechDraw::DrawWeldSymbol>()) {
temp.push_back((*it));
if (docobj && docobj->isDerivedFrom<TechDraw::DrawWeldSymbol>()) {
// add welding symbol even if we are not the owner?
temp.push_back(docobj);
}
}
return temp;
}
catch (...) {
return std::vector<App::DocumentObject*>();
return {};
}
}
@@ -193,7 +194,7 @@ void ViewProviderLeader::handleChangedPropertyType(Base::XMLReader &reader, cons
}
}
bool ViewProviderLeader::onDelete(const std::vector<std::string> &)
bool ViewProviderLeader::onDelete(const std::vector<std::string> & parameters)
{
// a leader line cannot be deleted if it has a child weld symbol

View File

@@ -48,17 +48,18 @@ public:
/// constructor
ViewProviderLeader();
/// destructor
~ViewProviderLeader() override;
~ViewProviderLeader() override = default;
App::PropertyLength LineWidth;
App::PropertyEnumeration LineStyle;
App::PropertyColor Color;
App::PropertyBool UseOldCoords;
bool useNewSelectionModel() const override {return false;}
void onChanged(const App::Property* p) override;
bool setEdit(int ModNum) override;
bool doubleClicked() override;
bool onDelete(const std::vector<std::string> &) override;
bool onDelete(const std::vector<std::string> &parameters) override;
bool canDelete(App::DocumentObject* obj) const override;
static const char* LineStyleEnums[];

View File

@@ -343,17 +343,9 @@ void ViewProviderViewPart::handleChangedPropertyType(Base::XMLReader &reader, co
bool ViewProviderViewPart::onDelete(const std::vector<std::string> & subNames)
{
// if a cosmetic subelement is in the list of selected subNames then we treat this
// as a delete of the subelement and not a delete of the DVP
std::vector<std::string> removables = getSelectedCosmetics(subNames);
if (!removables.empty()) {
// we have cosmetics, so remove them and tell Std_Delete not to remove the DVP
deleteCosmeticElements(removables);
getViewObject()->recomputeFeature();
return false;
}
// Base::Console().Message("VPVP::onDelete(%d subNames)\n", subNames.size());
// we cannot delete if the view has a section or detail view
(void) subNames;
QString bodyMessage;
QTextStream bodyMessageStream(&bodyMessage);
@@ -380,52 +372,6 @@ bool ViewProviderViewPart::canDelete(App::DocumentObject *obj) const
return true;
}
//! extract the names of cosmetic subelements from the list of all selected elements
std::vector<std::string> ViewProviderViewPart::getSelectedCosmetics(std::vector<std::string> subNames)
{
std::vector<std::string> result;
// pick out any cosmetic vertices or edges in the selection
for (auto& sub : subNames) {
if (DU::getGeomTypeFromName(sub) == "Vertex") {
if (DU::isCosmeticVertex(getViewObject(), sub)) {
result.emplace_back(sub);
}
} else if (DU::getGeomTypeFromName(sub) == "Edge") {
if (DU::isCosmeticEdge(getViewObject(), sub) ||
DU::isCenterLine(getViewObject(), sub)) {
result.emplace_back(sub);
}
}
}
return result;
}
//! delete cosmetic elements for a list of subelement names
void ViewProviderViewPart::deleteCosmeticElements(std::vector<std::string> removables)
{
for (auto& name : removables) {
if (DU::getGeomTypeFromName(name) == "Vertex") {
CosmeticVertex* vert = getViewObject()->getCosmeticVertexBySelection(name);
getViewObject()->removeCosmeticVertex(vert->getTagAsString());
continue;
}
if (DU::getGeomTypeFromName(name) == "Edge") {
CosmeticEdge* edge = getViewObject()->getCosmeticEdgeBySelection(name);
if (edge) {
// if not edge, something has gone very wrong!
getViewObject()->removeCosmeticEdge(edge->getTagAsString());
continue;
}
CenterLine* line = getViewObject()->getCenterLineBySelection(name);
if (line) {
getViewObject()->removeCenterLine(line->getTagAsString());
continue;
}
}
}
}
App::Color ViewProviderViewPart::prefSectionColor()
{
return PreferencesGui::sectionLineColor();

View File

@@ -79,9 +79,6 @@ public:
std::vector<App::DocumentObject*> claimChildren(void) const override;
void fixSceneDependencies();
std::vector<std::string> getSelectedCosmetics(std::vector<std::string> subNames);
void deleteCosmeticElements(std::vector<std::string> removables);
TechDraw::DrawViewPart* getViewObject() const override;
TechDraw::DrawViewPart* getViewPart() const;
};