TechDraw: Introduce dimension snapping
This commit is contained in:
committed by
WandererFan
parent
80fb3a492c
commit
f523f6c3ad
@@ -53,6 +53,7 @@
|
||||
#include "QGIDimLines.h"
|
||||
#include "QGIVertex.h"
|
||||
#include "QGCustomSvg.h"
|
||||
#include "TaskSelectLineAttributes.h"
|
||||
#include "ViewProviderDimension.h"
|
||||
#include "ZVALUE.h"
|
||||
|
||||
@@ -155,12 +156,24 @@ void QGIDatumLabel::snapPosition(QPointF& pos)
|
||||
return;
|
||||
}
|
||||
|
||||
// First we try to snap the label to its center position.
|
||||
// We only have snap for distances constraints
|
||||
std::string type = dim->Type.getValueAsString();
|
||||
if(type != "Distance" && type != "DistanceX" && type != "DistanceY") {
|
||||
return;
|
||||
}
|
||||
|
||||
// 1 - We try to snap the label to its center position.
|
||||
pointPair pp = dim->getLinearPoints();
|
||||
Base::Vector3d p1_3d = Rez::guiX(pp.first());
|
||||
Base::Vector3d p2_3d = Rez::guiX(pp.second());
|
||||
Base::Vector2d p1 = Base::Vector2d(p1_3d.x, p1_3d.y);
|
||||
Base::Vector2d p2 = Base::Vector2d(p2_3d.x, p2_3d.y);
|
||||
if (type == "DistanceX") {
|
||||
p2 = Base::Vector2d(p2.x, p1.y);
|
||||
}
|
||||
else if (type == "DistanceY") {
|
||||
p2 = Base::Vector2d(p1.x, p2.y);
|
||||
}
|
||||
Base::Vector2d mid = (p1 + p2) * 0.5;
|
||||
Base::Vector2d dir = p2 - p1;
|
||||
Base::Vector2d normal = Base::Vector2d(-dir.y, dir.x);
|
||||
@@ -171,11 +184,80 @@ void QGIDatumLabel::snapPosition(QPointF& pos)
|
||||
projPnt = projPnt + mid;
|
||||
|
||||
if ((projPnt - posV).Length() < dir.Length() * snapPercent) {
|
||||
pos.setX(projPnt.x - m_dimText->boundingRect().width() * 0.5);
|
||||
pos.setY(projPnt.y - m_dimText->boundingRect().height() * 0.5);
|
||||
posV = projPnt;
|
||||
pos.setX(posV.x - m_dimText->boundingRect().width() * 0.5);
|
||||
pos.setY(posV.y - m_dimText->boundingRect().height() * 0.5);
|
||||
|
||||
}
|
||||
|
||||
// 2 - We check for coord/chain dimensions to offer proper snapping
|
||||
auto* qgiv = dynamic_cast<QGIView*>(qgivd->parentItem());
|
||||
if (qgiv) {
|
||||
auto* dvp = dynamic_cast<TechDraw::DrawViewPart*>(qgiv->getViewObject());
|
||||
if (dvp) {
|
||||
std::vector<TechDraw::DrawViewDimension*> dims = dvp->getDimensions();
|
||||
double dimSpacing = Rez::guiX(activeDimAttributes.getCascadeSpacing());
|
||||
snapPercent = 0.2;
|
||||
for (auto& d : dims) {
|
||||
if (d == dim) { continue; }
|
||||
|
||||
std::string dType = d->Type.getValueAsString();
|
||||
if (dType != type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pp = d->getLinearPoints();
|
||||
Base::Vector3d ip1_3d = Rez::guiX(pp.first());
|
||||
Base::Vector3d ip2_3d = Rez::guiX(pp.second());
|
||||
|
||||
Base::Vector2d ip1 = Base::Vector2d(ip1_3d.x, ip1_3d.y);
|
||||
Base::Vector2d ip2 = Base::Vector2d(ip2_3d.x, ip2_3d.y);
|
||||
if (type == "DistanceX") {
|
||||
ip2 = Base::Vector2d(ip2.x, ip1.y);
|
||||
}
|
||||
else if (type == "DistanceY") {
|
||||
ip2 = Base::Vector2d(ip1.x, ip2.y);
|
||||
}
|
||||
Base::Vector2d imid = (ip1 + ip2) * 0.5;
|
||||
Base::Vector2d idir = ip2 - ip1;
|
||||
Base::Vector2d inormal = Base::Vector2d(-idir.y, idir.x);
|
||||
|
||||
if (type == "Distance" && fabs(dir.x * idir.y - dir.y * idir.x) > Precision::Confusion()) {
|
||||
//dimensions not parallel
|
||||
continue;
|
||||
}
|
||||
|
||||
auto* vp = dynamic_cast<ViewProviderDimension*>(Gui::Application::Instance->getViewProvider(d));
|
||||
if (!vp) { continue; }
|
||||
auto* qgivDi(dynamic_cast<QGIViewDimension*>(vp->getQView()));
|
||||
if (!qgivDi) { continue; }
|
||||
auto labeli = qgivDi->getDatumLabel();
|
||||
if (!labeli) { continue; }
|
||||
QPointF posi = labeli->pos();
|
||||
Base::Vector2d posVi = Base::Vector2d(posi.x() + labeli->m_dimText->boundingRect().width() * 0.5,
|
||||
posi.y() + labeli->m_dimText->boundingRect().height() * 0.5);
|
||||
|
||||
Base::Vector2d projPnt2;
|
||||
projPnt2.ProjectToLine(posV - posVi, idir);
|
||||
projPnt2 = projPnt2 + posVi;
|
||||
|
||||
if ((projPnt2 - posV).Length() < dimSpacing * snapPercent) {
|
||||
posV = projPnt2;
|
||||
pos.setX(posV.x - m_dimText->boundingRect().width() * 0.5);
|
||||
pos.setY(posV.y - m_dimText->boundingRect().height() * 0.5);
|
||||
break;
|
||||
}
|
||||
else if (fabs((projPnt2 - posV).Length() - fabs(dimSpacing)) < dimSpacing * snapPercent) {
|
||||
posV = projPnt2 + (posV - projPnt2).Normalize() * dimSpacing;
|
||||
pos.setX(posV.x - m_dimText->boundingRect().width() * 0.5);
|
||||
pos.setY(posV.y - m_dimText->boundingRect().height() * 0.5);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
setPos(pos); // no infinite loop because if pos doesn't change then itemChanged is not triggered.
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user