[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:
@@ -149,5 +149,7 @@ PyMOD_INIT_FUNC(TechDraw)
|
||||
TechDraw::DrawWeldSymbolPython::init();
|
||||
TechDraw::DrawBrokenViewPython::init();
|
||||
|
||||
TechDraw::LineFormat::initCurrentLineFormat();
|
||||
|
||||
PyMOD_Return(mod);
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -174,6 +174,8 @@ SET(TechDraw_SRCS
|
||||
XMLQuery.h
|
||||
LineGenerator.cpp
|
||||
LineGenerator.h
|
||||
LineFormat.cpp
|
||||
LineFormat.h
|
||||
)
|
||||
|
||||
SET(Geometry_SRCS
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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
|
||||
|
||||
117
src/Mod/TechDraw/App/LineFormat.cpp
Normal file
117
src/Mod/TechDraw/App/LineFormat.cpp
Normal 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
|
||||
}
|
||||
|
||||
|
||||
96
src/Mod/TechDraw/App/LineFormat.h
Normal file
96
src/Mod/TechDraw/App/LineFormat.h
Normal 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
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
#include <Mod/TechDraw/TechDrawGlobal.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace TechDraw
|
||||
|
||||
77
src/Mod/TechDraw/ConversionUtilities/moveViews.py
Normal file
77
src/Mod/TechDraw/ConversionUtilities/moveViews.py
Normal 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()
|
||||
45
src/Mod/TechDraw/ConversionUtilities/updateLeaderLines.py
Normal file
45
src/Mod/TechDraw/ConversionUtilities/updateLeaderLines.py
Normal 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")
|
||||
@@ -1262,7 +1262,7 @@ void execCosmeticCircle(Gui::Command* cmd)
|
||||
}
|
||||
|
||||
Gui::Control().showDialog(new TaskDlgCosmeticCircle(baseFeat,
|
||||
points.front(),
|
||||
points,
|
||||
centerIs3d));
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -88,6 +88,9 @@ static QColor lightenColor(QColor orig);
|
||||
|
||||
static double templateClickBoxSize();
|
||||
static QColor templateClickBoxColor();
|
||||
|
||||
static int get3dMarkerSize();
|
||||
|
||||
};
|
||||
|
||||
} //end namespace TechDrawGui
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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> ¶meters) override;
|
||||
bool canDelete(App::DocumentObject* obj) const override;
|
||||
|
||||
static const char* LineStyleEnums[];
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user