[TD]fix leader autohorizontal on rotated base view

This commit is contained in:
wandererfan
2024-11-19 18:59:39 -05:00
committed by Yorik van Havre
parent 23354b57cb
commit a92acbd457
7 changed files with 75 additions and 63 deletions

View File

@@ -30,6 +30,7 @@
#include <App/Document.h>
#include <Base/Console.h>
#include <Base/Parameter.h>
#include <Base/Tools.h>
#include "DrawViewPart.h"
#include "DrawPage.h"
@@ -96,7 +97,6 @@ DrawLeaderLine::DrawLeaderLine()
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);
ScaleType.setStatus(App::Property::Hidden, true);
@@ -110,11 +110,6 @@ DrawLeaderLine::DrawLeaderLine()
LockPosition.setStatus(App::Property::Hidden, true);
}
void DrawLeaderLine::onChanged(const App::Property* prop)
{
DrawView::onChanged(prop);
}
short DrawLeaderLine::mustExecute() const
{
if (!isRestoring() && LeaderParent.isTouched()) {
@@ -140,8 +135,6 @@ App::DocumentObjectExecReturn *DrawLeaderLine::execute()
return App::DocumentObject::StdReturn;
}
// is horizLastSegment something that should be done only at draw time?
horizLastSegment();
overrideKeepUpdated(false);
return DrawView::execute();
}
@@ -202,35 +195,39 @@ Base::Vector3d DrawLeaderLine::getAttachPoint()
//! 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()
std::vector<Base::Vector3d> DrawLeaderLine::horizLastSegment(const std::vector<Base::Vector3d>& inDeltas, double rotationDeg)
{
// 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());
Base::Vector3d stdX{1, 0, 0};
std::vector<Base::Vector3d> wp = inDeltas;
if (wp.size() > 1) {
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;
auto lastSeg = DU::invertY(last - penUlt);
auto lastSegLong = lastSeg.Length();
auto lastSegRotated = lastSeg;
lastSegRotated.RotateZ(Base::toRadians(rotationDeg));
auto lastSegRotatedUnit = lastSegRotated;
lastSegRotatedUnit.Normalize();
auto dot = lastSegRotatedUnit.Dot(stdX);
auto newLast = penUlt + stdX * lastSegLong;
if (dot < 0) {
newLast = penUlt - stdX * lastSegLong;
}
wp.at(iLast) = newLast;
}
return wp;
}
//! returns the mid point of last segment. used by leader decorators like weld symbol.
//! the returned point is unscaled and unrotated.
Base::Vector3d DrawLeaderLine::getTileOrigin() const
{
std::vector<Base::Vector3d> wp = WayPoints.getValues();
@@ -273,7 +270,7 @@ Base::Vector3d DrawLeaderLine::getTailPoint() const
//! 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);
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 {};
@@ -338,7 +335,6 @@ DrawLeaderLine* DrawLeaderLine::makeLeader(DrawViewPart* parent, std::vector<Bas
//! 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?
@@ -378,7 +374,6 @@ 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};
@@ -414,12 +409,15 @@ DrawLeaderLine::makeCanonicalPointsInverted(const std::vector<Base::Vector3d>& i
for (auto& point : inPoints) {
conventionalPoints.push_back(DU::invertY(point));
}
auto conventionalCanon = makeCanonicalPoints(inPoints, doScale, doRotate);
auto conventionalCanon = makeCanonicalPoints(conventionalPoints, doScale, doRotate);
std::vector<Base::Vector3d> invertedPoints;
invertedPoints.reserve(inPoints.size());
for (auto& point : conventionalCanon) {
invertedPoints.push_back(DU::invertY(point));
}
return invertedPoints;
}
@@ -442,6 +440,14 @@ bool DrawLeaderLine::getDefAuto() const
return Preferences::getPreferenceGroup("LeaderLine")->GetBool("AutoHorizontal", true);
}
void DrawLeaderLine::dumpWaypoints(const std::vector<Base::Vector3d> &points, const std::string &label)
{
Base::Console().Message("DLL::dumpWaypoints - %s\n", label.c_str());
for (auto& p : points) {
Base::Console().Message(">>>> a point: %s\n", DU::formatVector(p).c_str());
}
}
PyObject *DrawLeaderLine::getPyObject()
{

View File

@@ -69,8 +69,7 @@ public:
bool keepUpdated() override;
double getScale() const override;
double getBaseScale() const;
void horizLastSegment();
static std::vector<Base::Vector3d> horizLastSegment(const std::vector<Base::Vector3d>& inDeltas);
static std::vector<Base::Vector3d> horizLastSegment(const std::vector<Base::Vector3d>& inDeltas, double rotationDeg);
bool getDefAuto() const;
Base::Vector3d getTileOrigin() const;
@@ -88,8 +87,7 @@ public:
bool isParentReady() const;
protected:
void onChanged(const App::Property* prop) override;
void dumpWaypoints(const std::vector<Base::Vector3d>& points, const std::string& label);
private:

View File

@@ -60,6 +60,9 @@ void QGIDecoration::paint ( QPainter * painter, const QStyleOptionGraphicsItem *
QStyleOptionGraphicsItem myOption(*option);
myOption.state &= ~QStyle::State_Selected;
painter->setPen(Qt::green);
painter->drawRect(boundingRect()); //good for debugging
QGraphicsItemGroup::paint (painter, &myOption, widget);
}

View File

@@ -143,21 +143,18 @@ QVariant QGILeaderLine::itemChange(GraphicsItemChange change, const QVariant& va
//QGILL isn't draggable so skip QGIV::mousePress have event
void QGILeaderLine::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
// Base::Console().Message("QGILL::mousePressEvent() - %s\n", getViewName());
QGraphicsItem::mousePressEvent(event);
}
//QGILL isn't draggable so skip QGIV::mouseRelease
//QGILL isn't draggable so skip QGIV::Release
void QGILeaderLine::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
// Base::Console().Message("QGILL::mouseReleaseEvent() - %s\n", getViewName());
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";
@@ -419,7 +416,6 @@ void QGILeaderLine::draw()
QPainterPath QGILeaderLine::makeLeaderPath(std::vector<QPointF> qPoints)
{
// Base::Console().Message("QGILeaderLine::makeLeaderPath()\n");
QPainterPath result;
DrawLeaderLine* featLeader = getLeaderFeature();
if (!featLeader) {
@@ -469,7 +465,6 @@ QPainterPath QGILeaderLine::makeLeaderPath(std::vector<QPointF> qPoints)
//! result is is not inverted (Y grows upwards).
QPointF QGILeaderLine::getAttachFromFeature()
{
// Base::Console().Message("QGILL::getAttachFromFeature()\n");
TechDraw::DrawLeaderLine* featLeader = getLeaderFeature();
if (!featLeader) {
// Base::Console().Message("QGIL::getAttachFromLeader - no feature\n");
@@ -483,7 +478,6 @@ QPointF QGILeaderLine::getAttachFromFeature()
std::vector<QPointF> QGILeaderLine::getWayPointsFromFeature()
{
// Base::Console().Message("QGILL::getWayPointsFromFeature()\n");
DrawLeaderLine* featLeader = getLeaderFeature();
if (!featLeader) {
// Base::Console().Message("QGILL::getWayPointsFromFeature - featLeader is nullptr\n");
@@ -494,6 +488,9 @@ std::vector<QPointF> QGILeaderLine::getWayPointsFromFeature()
auto doScale = featLeader->Scalable.getValue();
auto doRotate = featLeader->RotatesWithParent.getValue();
auto vPoints = featLeader->getScaledAndRotatedPoints(doScale, doRotate);
if (featLeader->AutoHorizontal.getValue()) {
vPoints = DrawLeaderLine::horizLastSegment(vPoints, featLeader->getBaseView()->Rotation.getValue());
}
std::vector<QPointF> qPoints;
qPoints.reserve(vPoints.size());
@@ -504,20 +501,19 @@ std::vector<QPointF> QGILeaderLine::getWayPointsFromFeature()
qPoints.push_back(DU::toQPointF(entry));
} else {
// use points as saved in >= v0.22
qPoints.push_back(DU::toQPointF(DGU::toSceneCoords(entry, false)));
qPoints.push_back(DU::toQPointF(Rez::guiX(entry)));
}
}
if (qPoints.empty()) {
Base::Console().Warning("QGILeaderLine::getWayPointsFromFeature - no points\n");
}
return qPoints;
}
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 = getLeaderFeature();
@@ -628,8 +624,8 @@ void QGILeaderLine::paint(QPainter* painter, const QStyleOptionGraphicsItem* opt
QStyleOptionGraphicsItem myOption(*option);
myOption.state &= ~QStyle::State_Selected;
// painter->setPen(Qt::blue);
// painter->drawRect(boundingRect()); //good for debugging
painter->setPen(Qt::blue);
painter->drawRect(boundingRect()); //good for debugging
QGIView::paint(painter, &myOption, widget);
}

View File

@@ -21,6 +21,7 @@
***************************************************************************/
#include "PreCompiled.h"
#include <qpainter.h>
#ifndef _PreComp_
# include <cmath>
# include <QGraphicsScene>
@@ -546,8 +547,8 @@ void QGIWeldSymbol::paint ( QPainter * painter, const QStyleOptionGraphicsItem *
QStyleOptionGraphicsItem myOption(*option);
myOption.state &= ~QStyle::State_Selected;
// painter->setPen(Qt::red);
// painter->drawRect(boundingRect()); //good for debugging
painter->setPen(Qt::red);
painter->drawRect(boundingRect()); //good for debugging
QGIView::paint (painter, &myOption, widget);
}

View File

@@ -215,7 +215,6 @@ void TaskLeaderLine::changeEvent(QEvent *event)
void TaskLeaderLine::setUiPrimary()
{
// Base::Console().Message("TTL::setUiPrimary()\n");
enableVPUi(true);
setWindowTitle(QObject::tr("New Leader Line"));
@@ -258,7 +257,6 @@ void TaskLeaderLine::enableVPUi(bool enable)
void TaskLeaderLine::setUiEdit()
{
// Base::Console().Message("TTL::setUiEdit()\n");
enableVPUi(true);
setWindowTitle(QObject::tr("Edit Leader Line"));
@@ -380,16 +378,14 @@ void TaskLeaderLine::createLeaderFeature(std::vector<Base::Vector3d> sceneDeltas
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);
Base::Vector3d deltaInPageCoords = Rez::appX(delta);
pageDeltas.push_back(deltaInPageCoords);
}
// should just do this in place.
if (m_lineFeat->AutoHorizontal.getValue()) {
pageDeltas = DrawLeaderLine::horizLastSegment(pageDeltas);
}
// convert to unscaled, unrotated but inverted
auto temp = m_lineFeat->makeCanonicalPointsInverted(pageDeltas);
// already unrotated, now convert to unscaled, but inverted
bool doScale{true};
bool doRotate{false};
auto temp = m_lineFeat->makeCanonicalPointsInverted(pageDeltas, doScale, doRotate);
m_lineFeat->WayPoints.setValues(temp);
}
commonFeatureUpdate();
@@ -491,8 +487,6 @@ void TaskLeaderLine::removeFeature()
void TaskLeaderLine::onTrackerClicked(bool clicked)
{
Q_UNUSED(clicked);
// Base::Console().Message("TTL::onTrackerClicked() m_pbTrackerState: %d\n",
// m_pbTrackerState);
if (!m_vpp->getMDIViewPage()) {
Base::Console().Message("TLL::onTrackerClicked - no Mdi, no Tracker!\n");
return;
@@ -714,7 +708,7 @@ QGIView* TaskLeaderLine::findParentQGIV()
return vpdv->getQView();;
}
void TaskLeaderLine::setEditCursor(QCursor cursor)
void TaskLeaderLine::setEditCursor(const QCursor &cursor)
{
if (!m_vpp->getQGSPage()) {
return;
@@ -725,15 +719,29 @@ void TaskLeaderLine::setEditCursor(QCursor cursor)
}
}
//from scene QPointF to zero origin (delta from p0) Vector3d points
// 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::scenePointsToDeltas(%d)\n", pts.size());
if (scenePoints.empty()) {
return {};
}
std::vector<Base::Vector3d> result;
auto frontPoint = DU::toVector3d(m_qgParent->mapFromScene(scenePoints.front()));
result.reserve(scenePoints.size());
for (auto& point: scenePoints) {
QPointF delta = point - scenePoints.front();
result.push_back(DU::toVector3d(delta));
auto viewPoint = m_qgParent->mapFromScene(point);
auto vPoint = DU::toVector3d(viewPoint);
auto delta = vPoint - frontPoint;
auto rotationDeg = m_baseFeat->Rotation.getValue();
auto deltaUnrotated{delta};
if (rotationDeg != 0) {
deltaUnrotated = DU::invertY(deltaUnrotated);
deltaUnrotated.RotateZ(-Base::toRadians(rotationDeg));
deltaUnrotated = DU::invertY(deltaUnrotated);
}
result.push_back(deltaUnrotated);
}
return result;
}

View File

@@ -91,7 +91,7 @@ protected:
void setUiPrimary();
void setUiEdit();
void enableVPUi(bool enable);
void setEditCursor(QCursor cursor);
void setEditCursor(const QCursor& cursor);
QGIView* findParentQGIV();