[TD]fix leader autohorizontal on rotated base view
This commit is contained in:
committed by
Yorik van Havre
parent
bc6183eb81
commit
0540b473ec
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ protected:
|
||||
void setUiPrimary();
|
||||
void setUiEdit();
|
||||
void enableVPUi(bool enable);
|
||||
void setEditCursor(QCursor cursor);
|
||||
void setEditCursor(const QCursor& cursor);
|
||||
|
||||
QGIView* findParentQGIV();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user