TechDraw: Enable snapping section views to their base views.

This commit is contained in:
PaddleStroke
2024-04-29 12:19:04 +02:00
committed by WandererFan
parent f0ebd62637
commit 127ee90cec
5 changed files with 77 additions and 23 deletions

View File

@@ -932,27 +932,29 @@ std::vector<TechDraw::FacePtr> DrawViewSection::makeTDSectionFaces(TopoDS_Compou
std::pair<Base::Vector3d, Base::Vector3d> DrawViewSection::sectionLineEnds()
{
std::pair<Base::Vector3d, Base::Vector3d> result;
Base::Vector3d stdZ(0.0, 0.0, 1.0);
double baseRotation = getBaseDVP()->Rotation.getValue();// Qt degrees are clockwise
Base::Rotation rotator(stdZ, baseRotation * M_PI / 180.0);
Base::Rotation unrotator(stdZ, -baseRotation * M_PI / 180.0);
Base::Vector3d dir = getSectionDirectionOnBaseView();
Base::Vector3d sectionOrg = SectionOrigin.getValue() - getBaseDVP()->getOriginalCentroid();
sectionOrg = getBaseDVP()->projectPoint(sectionOrg);// convert to base view CS
double halfSize = (getBaseDVP()->getSizeAlongVector(dir) / 2.0) * SectionLineStretch.getValue();
result.first = sectionOrg + dir * halfSize;
result.second = sectionOrg - dir * halfSize;
return result;
}
// calculate the direction of the section in 2d on the base view.
Base::Vector3d DrawViewSection::getSectionDirectionOnBaseView()
{
auto sNorm = SectionNormal.getValue();
auto axis = getBaseDVP()->Direction.getValue();
Base::Vector3d stdOrg(0.0, 0.0, 0.0);
Base::Vector3d sectionLineDir = -axis.Cross(sNorm);
sectionLineDir.Normalize();
sectionLineDir = getBaseDVP()->projectPoint(sectionLineDir);// convert to base view CS
sectionLineDir.Normalize();
Base::Vector3d sectionOrg = SectionOrigin.getValue() - getBaseDVP()->getOriginalCentroid();
sectionOrg = getBaseDVP()->projectPoint(sectionOrg);// convert to base view
// CS
double halfSize = (getBaseDVP()->getSizeAlongVector(sectionLineDir) / 2.0) * SectionLineStretch.getValue();
result.first = sectionOrg + sectionLineDir * halfSize;
result.second = sectionOrg - sectionLineDir * halfSize;
return result;
return sectionLineDir;
}
// find the points and directions to make the change point marks.

View File

@@ -165,6 +165,7 @@ public:
static const char* CutSurfaceEnums[];
virtual std::pair<Base::Vector3d, Base::Vector3d> sectionLineEnds();
Base::Vector3d getSectionDirectionOnBaseView();
virtual ChangePointVector getChangePointsFromSectionLine();
bool showSectionEdges(void);

View File

@@ -41,6 +41,8 @@
#include <Mod/TechDraw/App/DrawPage.h>
#include <Mod/TechDraw/App/DrawProjGroup.h>
#include <Mod/TechDraw/App/DrawProjGroupItem.h>
#include <Mod/TechDraw/App/DrawViewSection.h>
#include <Mod/TechDraw/App/DrawViewPart.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include <Mod/TechDraw/App/DrawView.h>
@@ -71,7 +73,8 @@ QGIView::QGIView()
:QGraphicsItemGroup(),
viewObj(nullptr),
m_innerView(false),
m_multiselectActivated(false)
m_multiselectActivated(false),
snapping(false)
{
setCacheMode(QGraphicsItem::NoCache);
setHandlesChildEvents(false);
@@ -153,10 +156,9 @@ void QGIView::alignTo(QGraphicsItem*item, const QString &alignment)
QVariant QGIView::itemChange(GraphicsItemChange change, const QVariant &value)
{
QPointF newPos(0.0, 0.0);
// Base::Console().Message("QGIV::itemChange(%d)\n", change);
if(change == ItemPositionChange && scene()) {
newPos = value.toPointF(); //position within parent!
QPointF newPos = value.toPointF(); //position within parent!
TechDraw::DrawView *viewObj = getViewObject();
auto* dpgi = dynamic_cast<TechDraw::DrawProjGroupItem*>(viewObj);
@@ -181,7 +183,9 @@ QVariant QGIView::itemChange(GraphicsItemChange change, const QVariant &value)
// tell the feature that we have moved
Gui::ViewProvider *vp = getViewProvider(viewObj);
if (vp && !vp->isRestoring()) {
snapping = true; // avoid triggering updateView by the VP updateData
viewObj->setPosition(Rez::appX(newPos.x()), Rez::appX(-newPos.y()));
snapping = false;
}
return newPos;
@@ -201,7 +205,7 @@ QVariant QGIView::itemChange(GraphicsItemChange change, const QVariant &value)
return QGraphicsItemGroup::itemChange(change, value);
}
void QGIView::snapPosition(QPointF& pos)
void QGIView::snapPosition(QPointF& mPos)
{
// For general views we check if the view is close to aligned vertically or horizontally to another view.
@@ -220,20 +224,65 @@ void QGIView::snapPosition(QPointF& pos)
}
std::vector<QGIView*> views = scenePage->getViews();
qreal snapPercent = 0.05;
auto* sectionView = dynamic_cast<TechDraw::DrawViewSection*>(getViewObject());
if (sectionView) {
auto* baseView = sectionView->getBaseDVP();
if (!baseView) { return; }
Base::Vector3d dir3d = sectionView->getSectionDirectionOnBaseView();
double bSize = Rez::guiX(baseView->getSizeAlongVector(dir3d));
double sSize = Rez::guiX(sectionView->getSizeAlongVector(dir3d));
auto* vpdv = dynamic_cast<ViewProviderDrawingView*>(getViewProvider(baseView));
if (!vpdv) { return; }
auto* qgiv(dynamic_cast<QGIView*>(vpdv->getQView()));
if (!qgiv) { return; }
QPointF bvPos = qgiv->pos();
Base::Vector2d bvPt(bvPos.x(), bvPos.y());
Base::Vector2d mPt(mPos.x(), mPos.y());
Base::Vector2d dir(dir3d.x, dir3d.y);
if (dir.Length() < Precision::Confusion()) { return; }
dir.Normalize();
double snapDist = bSize * snapPercent;
Base::Vector2d projPt;
projPt.ProjectToLine(mPt - bvPt, dir);
projPt = projPt + bvPt;
Base::Vector2d v = (projPt - bvPt) + 0.5 * (sSize - bSize) * dir;
int sign = v * dir > 0 ? - 1 : 1;
double dist = v.Length();
if (dist < snapDist) {
v = dist * dir;
mPos = mPos + sign * QPointF(v.x, v.y);
return;
}
v = (projPt - bvPt) + 0.5 * (bSize - sSize) * dir;
sign = v * dir > 0 ? - 1 : 1;
dist = v.Length();
if (dist < snapDist) {
v = dist * dir;
mPos = mPos + sign * QPointF(v.x, v.y);
return;
}
}
for (auto* view : views) {
if (view == this) { continue; }
QPointF vPos = view->pos();
qreal dx = view->boundingRect().width() * snapPercent;
qreal dy = view->boundingRect().height() * snapPercent;
if (fabs(pos.x() - vPos.x()) < dx) {
pos.setX(vPos.x());
if (fabs(mPos.x() - vPos.x()) < dx) {
mPos.setX(vPos.x());
break;
}
else if (fabs(pos.y() - vPos.y()) < dy) {
pos.setY(vPos.y());
else if (fabs(mPos.y() - vPos.y()) < dy) {
mPos.setY(vPos.y());
break;
}
}

View File

@@ -122,6 +122,7 @@ public:
void isInnerView(bool state) { m_innerView = state; }
QGIViewClip* getClipGroup();
bool isSnapping() { return snapping; }
void snapPosition(QPointF& position);
void alignTo(QGraphicsItem*, const QString &alignment);
@@ -182,6 +183,7 @@ private:
QHash<QString, QGraphicsItem*> alignHash;
bool m_innerView; //View is inside another View
bool m_multiselectActivated;
bool snapping;
QPen m_pen;
QBrush m_brush;

View File

@@ -227,7 +227,7 @@ void ViewProviderDrawingView::updateData(const App::Property* prop)
if (prop == &obj->X
|| prop == &obj->Y) {
QGIView* qgiv = getQView();
if (qgiv) {
if (qgiv && !qgiv->isSnapping()) {
qgiv->QGIView::updateView(true);
// Update also the owner/parent view, if there is any