[TD]Fix section snapping (fix #15961) (#15450)

* [TD]Add view snapping preferences

* [TD]fix section snapping algo

- snap sections to section normal line.
- snap views to other views in X&Y

* [TD]fix snapping to ProjectionGroups
This commit is contained in:
WandererFan
2024-09-02 12:41:25 -04:00
committed by GitHub
parent 77539c1091
commit e852052df8
12 changed files with 404 additions and 119 deletions

View File

@@ -271,6 +271,37 @@ double DrawUtil::incidenceAngleAtVertex(TopoDS_Edge e, TopoDS_Vertex v, double t
return incidenceAngle;
}
//! true if actualAngle(degrees) is within allowableError [0,360] of
//! targetAngle (degrees)
bool DrawUtil::isWithinRange(double actualAngleIn, double targetAngleIn, double allowableError)
{
constexpr double DegreesPerRevolution{360};
constexpr double DegreesPerHalfRevolution{180};
// map both angles from [0, 360] to [-180, 180]. This solves the problem of
// comparing angles near 0, such as 5deg & 355deg where the desired answer is
// 10, not 350;
double actualAngleDeg = actualAngleIn;
if (actualAngleDeg < DegreesPerRevolution &&
actualAngleDeg > DegreesPerHalfRevolution) {
actualAngleDeg = actualAngleDeg - DegreesPerRevolution;
}
double targetAngleDeg = targetAngleIn;
if (targetAngleDeg < DegreesPerRevolution &&
targetAngleDeg > DegreesPerHalfRevolution) {
targetAngleDeg = targetAngleDeg - DegreesPerRevolution;
}
double actualError = fabs(targetAngleDeg - actualAngleDeg);
if (actualError <= allowableError) {
return true;
}
return false;
}
bool DrawUtil::isFirstVert(TopoDS_Edge e, TopoDS_Vertex v, double tolerance)
{
TopoDS_Vertex first = TopExp::FirstVertex(e);

View File

@@ -275,6 +275,9 @@ public:
static Base::Vector3d toAppSpace(const DrawViewPart& dvp, const Base::Vector3d& inPoint);
static Base::Vector3d toAppSpace(const DrawViewPart& dvp, const QPointF& inPoint);
static bool isWithinRange(double actualAngleIn, double targetAngleIn, double allowableError);
//debugging routines
static void dumpVertexes(const char* text, const TopoDS_Shape& s);
static void dumpEdge(const char* label, int i, TopoDS_Edge e);

View File

@@ -42,9 +42,10 @@
#include "DrawUtil.h"
#include "DrawViewClip.h"
#include "DrawViewCollection.h"
#include "DrawProjGroup.h"
#include "DrawProjGroupItem.h"
#include "Preferences.h"
using namespace TechDraw;
using DU = DrawUtil;
@@ -652,6 +653,22 @@ void DrawView::setScaleAttribute()
}
}
//! due to changes made for the "intelligent" view creation tool, testing for a view being an
//! instance of DrawProjGroupItem is no longer reliable, as views not in a group are sometimes
//! created as DrawProjGroupItem without belonging to a group. We now need to test for the existance
//! of the parent DrawProjGroup
bool DrawView::isProjGroupItem(DrawViewPart* item)
{
auto dpgi = dynamic_cast<DrawProjGroupItem*>(item);
if (!dpgi) {
return false;
}
auto group = dpgi->getPGroup();
if (!group) {
return false;
}
return true;
}
int DrawView::prefScaleType()
{
return Preferences::getPreferenceGroup("General")->GetInt("DefaultScaleType", 0);

View File

@@ -40,7 +40,7 @@ class DrawPage;
class DrawViewCollection;
class DrawViewClip;
class DrawLeaderLine;
/*class CosmeticVertex;*/
class DrawViewPart;
/** Base class of all View Features in the drawing module
*/
@@ -123,6 +123,8 @@ public:
virtual App::PropertyLink *getOwnerProperty() { return nullptr; }
static bool isProjGroupItem(DrawViewPart* item);
protected:
void onBeforeChange(const App::Property *prop) override;
void onChanged(const App::Property* prop) override;

View File

@@ -80,6 +80,7 @@
#include <Base/Console.h>
#include <Base/FileInfo.h>
#include <Base/Parameter.h>
#include <Base/Tools.h>
#include <Mod/Part/App/PartFeature.h>
@@ -1152,21 +1153,15 @@ gp_Ax2 DrawViewSection::getSectionCS() const
return sectionCS;
}
gp_Ax2 DrawViewSection::getProjectionCS(const Base::Vector3d pt) const
//! return the center of the shape resulting from the cut operation
Base::Vector3d DrawViewSection::getCutCentroid() const
{
Base::Vector3d vNormal = SectionNormal.getValue();
gp_Dir gNormal(vNormal.x, vNormal.y, vNormal.z);
Base::Vector3d vXDir = getXDirection();
gp_Dir gXDir(vXDir.x, vXDir.y, vXDir.z);
if (DrawUtil::fpCompare(fabs(gNormal.Dot(gXDir)), 1.0)) {
// can not build a gp_Ax2 from these values
throw Base::RuntimeError(
"DVS::getProjectionCS - SectionNormal and XDirection are parallel");
}
gp_Pnt gOrigin(pt.x, pt.y, pt.z);
return {gOrigin, gNormal, gXDir};
gp_Pnt inputCenter = ShapeUtils::findCentroid(m_cutPieces, getProjectionCS());
return Base::Vector3d(inputCenter.X(), inputCenter.Y(), inputCenter.Z());
}
std::vector<LineSet> DrawViewSection::getDrawableLines(int i)
{
// Base::Console().Message("DVS::getDrawableLines(%d) - lineSets: %d\n", i, m_lineSets.size());

View File

@@ -134,7 +134,6 @@ public:
virtual TopoDS_Shape getShapeToPrepare() const { return m_cutPieces; }
//CS related methods
gp_Ax2 getProjectionCS(Base::Vector3d pt = Base::Vector3d(0.0, 0.0, 0.0)) const override;
void setCSFromBase(const std::string sectionName);
void setCSFromBase(Base::Vector3d localUnit);
void setCSFromLocalUnit(const Base::Vector3d localUnit);
@@ -172,6 +171,8 @@ public:
TopoDS_Shape makeFaceFromWires(std::vector<TopoDS_Wire> &inWires);
Base::Vector3d getCutCentroid() const;
public Q_SLOTS:
virtual void onSectionCutFinished(void);

View File

@@ -599,3 +599,16 @@ bool Preferences::alwaysShowLabel()
{
return getPreferenceGroup("General")->GetBool("AlwaysShowLabel", false);
}
bool Preferences::SnapViews()
{
return getPreferenceGroup("General")->GetBool("SnapViews", true);
}
//! percentage of view size to use in deciding to snap view or not
double Preferences::SnapLimitFactor()
{
return getPreferenceGroup("General")->GetFloat("SnapLimitFactor", 0.05);
}

View File

@@ -138,6 +138,9 @@ public:
static bool useCameraDirection();
static bool alwaysShowLabel();
static bool SnapViews();
static double SnapLimitFactor();
};

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>547</width>
<height>915</height>
<width>578</width>
<height>1073</height>
</rect>
</property>
<property name="sizePolicy">
@@ -886,8 +886,103 @@ for ProjectionGroups</string>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Snapping</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<layout class="QGridLayout" name="gridLayout_8" columnstretch="1,0,2">
<item row="0" column="0">
<widget class="Gui::PrefCheckBox" name="cb_SnapViews">
<property name="toolTip">
<string>Check this box if you want views to snap into alignment when being dragged.</string>
</property>
<property name="text">
<string>Snap View Alignment</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>SnapViews</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/General</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>View Snapping Factor</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="Gui::PrefDoubleSpinBox" name="psb_SnapFactor">
<property name="toolTip">
<string>When dragging a view, if it is within this fraction of view size of the correct alignment, it will snap into alignment.</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="value">
<double>0.050000000000000</double>
</property>
<property name="prefEntry" stdset="0">
<cstring>SnapLimitFactor</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/General</cstring>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="label_12">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>64</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>64</height>
</size>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
@@ -935,6 +1030,11 @@ for ProjectionGroups</string>
<extends>QLineEdit</extends>
<header>Gui/PrefWidgets.h</header>
</customwidget>
<customwidget>
<class>Gui::PrefDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>Gui/PrefWidgets.h</header>
</customwidget>
<customwidget>
<class>Gui::PrefFontBox</class>
<extends>QFontComboBox</extends>

View File

@@ -79,6 +79,8 @@ void DlgPrefsTechDrawGeneralImp::saveSettings()
ui->cb_useCameraDirection->onSave();
ui->cb_alwaysShowLabel->onSave();
ui->cb_SnapViews->onSave();
ui->psb_SnapFactor->onSave();
}
void DlgPrefsTechDrawGeneralImp::loadSettings()
@@ -124,6 +126,9 @@ void DlgPrefsTechDrawGeneralImp::loadSettings()
ui->cb_useCameraDirection->onRestore();
ui->cb_alwaysShowLabel->onRestore();
ui->cb_SnapViews->onRestore();
ui->psb_SnapFactor->onRestore();
}
/**

View File

@@ -1,4 +1,4 @@
/***************************************************************************
/***************************************************************************
* Copyright (c) 2012-2013 Luke Parry <l.parry@warwick.ac.uk> *
* *
* This file is part of the FreeCAD CAx development system. *
@@ -33,6 +33,7 @@
#include <App/Application.h>
#include <App/DocumentObject.h>
#include <Base/Console.h>
#include <Base/Tools.h>
#include <Gui/Application.h>
#include <Gui/Document.h>
#include <Gui/MainWindow.h>
@@ -68,15 +69,16 @@
using namespace TechDrawGui;
using namespace TechDraw;
using DU = DrawUtil;
const float labelCaptionFudge = 0.2f; // temp fiddle for devel
QGIView::QGIView()
:QGraphicsItemGroup(),
viewObj(nullptr),
m_innerView(false),
m_multiselectActivated(false),
snapping(false)
viewObj(nullptr),
m_innerView(false),
m_multiselectActivated(false),
snapping(false)
{
setCacheMode(QGraphicsItem::NoCache);
setHandlesChildEvents(false);
@@ -158,7 +160,7 @@ void QGIView::alignTo(QGraphicsItem*item, const QString &alignment)
QVariant QGIView::itemChange(GraphicsItemChange change, const QVariant &value)
{
// Base::Console().Message("QGIV::itemChange(%d)\n", change);
// Base::Console().Message("QGIV::itemChange(%d)\n", change);
if(change == ItemPositionChange && scene()) {
QPointF newPos = value.toPointF(); //position within parent!
@@ -184,7 +186,7 @@ QVariant QGIView::itemChange(GraphicsItemChange change, const QVariant &value)
}
}
// tell the feature that we have moved
// 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
@@ -207,89 +209,196 @@ QVariant QGIView::itemChange(GraphicsItemChange change, const QVariant &value)
return QGraphicsItemGroup::itemChange(change, value);
}
void QGIView::snapPosition(QPointF& mPos)
//! align this view with others. newPosition is in this view's parent's coord
//! system. if this view is not in a ProjectionGroup, then this is the scene
//! position, otherwise it is the position within the ProjectionGroup.
void QGIView::snapPosition(QPointF& newPosition)
{
// For general views we check if the view is close to aligned vertically or horizontally to another view.
if (!Preferences::SnapViews()) {
return;
}
// First get a list of the views of the page.
auto* mdi = dynamic_cast<MDIViewPage*>(Gui::getMainWindow()->activeWindow());
if (!mdi) {
auto feature = getViewObject();
if (!feature) {
return;
}
ViewProviderPage* vp = mdi->getViewProviderPage();
if (!vp) {
auto dvp = dynamic_cast<DrawViewPart*>(feature);
if (dvp &&
!dvp->hasGeometry()) {
// too early. wait for updates to finish.
return;
}
QGSPage* scenePage = vp->getQGSPage();
auto vpPage = getViewProviderPage(feature);
QGSPage* scenePage = vpPage->getQGSPage();
if (!scenePage) {
return;
}
std::vector<QGIView*> views = scenePage->getViews();
qreal snapPercent = 0.05;
auto* sectionView = dynamic_cast<TechDraw::DrawViewSection*>(getViewObject());
auto* sectionView = dynamic_cast<TechDraw::DrawViewSection*>(feature);
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;
}
snapSectionView(sectionView, newPosition);
return;
}
for (auto* view : views) {
if (view == this) { continue; }
// For general views we check if the view is close to aligned vertically or horizontally to another view.
QPointF vPos = view->pos();
qreal dx = view->boundingRect().width() * snapPercent;
qreal dy = view->boundingRect().height() * snapPercent;
if (fabs(mPos.x() - vPos.x()) < dx) {
mPos.setX(vPos.x());
break;
// if we are not a section view, then we could be in a projection group and
// need to get the correct scene position.
auto newScenePos = newPosition;
if (parentItem()) {
newScenePos = parentItem()->mapToScene(newPosition);
}
// First get a list of the views of the page.
qreal snapPercent = Preferences::SnapLimitFactor();
std::vector<QGIView*> views = scenePage->getViews();
for (auto* view : views) {
if (view == this) {
continue;
}
else if (fabs(mPos.y() - vPos.y()) < dy) {
mPos.setY(vPos.y());
break;
auto viewFeature = view->getViewObject();
auto viewDvp = dynamic_cast<DrawViewPart*>(viewFeature);
auto viewScenePos = view->scenePos();
if (viewDvp &&
DrawView::isProjGroupItem(viewDvp)) {
viewScenePos = DU::toQPointF(projItemPagePos(viewDvp));
viewScenePos = DU::invertY(Rez::guiX(viewScenePos));
}
auto xwindow = view->boundingRect().width() * snapPercent;
auto ywindow = view->boundingRect().height() * snapPercent;
auto xerror = fabs(newScenePos.x() - viewScenePos.x());
auto yerror = fabs(newScenePos.y() - viewScenePos.y());
// if the smaller of vertical and horizontal errors is within the acceptable
// window, snap to position.
if (xerror <= yerror &&
xerror <= xwindow) {
newScenePos.setX(viewScenePos.x());
if (parentItem()) {
newScenePos = parentItem()->mapFromScene(newScenePos);
}
newPosition = newScenePos;
return;
}
if (yerror < xerror &&
yerror <= ywindow) {
newScenePos.setY(viewScenePos.y());
if (parentItem()) {
newScenePos = parentItem()->mapFromScene(newScenePos);
}
newPosition = newScenePos;
return;
}
}
}
//! snap this section view to its base view. The section should be positioned on
//! line from the base view along the section normal direction, ie the same direction
//! as the arrows on the section line.
// Note: positions are in Qt inverted Y coordinates. They need to be converted before
// doing math on them, then converted back on return.
// Note: section views are never inside a ProjectionGroup, so their position is
// always in scene coordinates.
void QGIView::snapSectionView(const TechDraw::DrawViewSection* sectionView,
QPointF& newPosition)
{
auto* baseView = sectionView->getBaseDVP();
if (!baseView) {
return;
}
auto* vpdv = dynamic_cast<ViewProviderDrawingView*>(getViewProvider(baseView));
if (!vpdv) {
return;
}
auto* qgiv(dynamic_cast<QGIView*>(vpdv->getQView()));
if (!qgiv) {
return;
}
Base::Vector3d arrowDirection = sectionView->SectionNormal.getValue() * -1;
auto arrowDirectionOnBase = baseView->projectPoint(arrowDirection, false);
if (arrowDirectionOnBase.Length() < Precision::Confusion()) {
return;
}
arrowDirectionOnBase.Normalize();
double baseSize = Rez::guiX(baseView->getSizeAlongVector(arrowDirectionOnBase));
double snapDist = baseSize * getScale() * Preferences::SnapLimitFactor();
// find the scene position of the SO on the base view
auto baseX = baseView->X.getValue();
auto baseY = baseView->Y.getValue();
Base::Vector3d baseScenePos{baseX, baseY, 0}; // paper space position
if (DrawView::isProjGroupItem(baseView)) {
baseScenePos = projItemPagePos(baseView);
}
auto sectionOrg3d = sectionView->SectionOrigin.getValue();
auto shapeCenter3d = baseView->getCurrentCentroid();
auto baseShapeCenter = baseView->projectPoint(shapeCenter3d, false);
auto baseSectionOrg = baseView->projectPoint(sectionOrg3d, false);
auto baseSOOffset = (baseSectionOrg - baseShapeCenter) * baseView->getScale();
auto baseSOScenePos = baseScenePos + baseSOOffset;
// find the SO offset from origin on the rotated & scaled sectionView
auto sectionCutCenter = sectionView->projectPoint(sectionView->getCutCentroid(), false);
auto sectionSectionOrg = sectionView->projectPoint(sectionOrg3d, false);
auto sectionSOOffset = (sectionSectionOrg - sectionCutCenter) * sectionView->getScale();
auto sectionRotationDeg = sectionView->Rotation.getValue();
sectionSOOffset.RotateZ(Base::toRadians(sectionRotationDeg));
// from here on, we work with scene units (1/10 mm)
sectionSOOffset = Rez::guiX(sectionSOOffset);
baseSOScenePos = Rez::guiX(baseSOScenePos);
// check our alignment
auto newSOPosition = DU::invertY(DU::toVector3d(newPosition)) + sectionSOOffset;
Base::Vector3d actualAlignmentVector = newSOPosition - baseSOScenePos;
actualAlignmentVector.Normalize();
// if we are not on the correct side of the section line, we should not try to snap
auto dot = arrowDirectionOnBase.Dot(actualAlignmentVector);
if (dot <= 0) {
return;
}
auto pointOnArrowLine = newSOPosition.Perpendicular(baseSOScenePos, arrowDirectionOnBase);
auto errorVector = pointOnArrowLine - newSOPosition;
if (errorVector.Length() < snapDist) {
// get the position point corresponding to our SO alignment
auto netPosition = pointOnArrowLine - sectionSOOffset;
netPosition = DU::invertY(netPosition);
newPosition = DU::toQPointF(netPosition);
}
return;
}
Base::Vector3d QGIView::projItemPagePos(DrawViewPart* item)
{
if (!DrawView::isProjGroupItem(item)) {
return Base::Vector3d(0, 0, 0);
}
auto dpgi = static_cast<DrawProjGroupItem*>(item);
auto group = dpgi->getPGroup();
auto itemX = dpgi->X.getValue();
auto itemY = dpgi->Y.getValue();
Base::Vector3d itemOffsetPos{itemX, itemY, 0}; // relative to group
auto groupX = group->X.getValue();
auto groupY = group->Y.getValue();
Base::Vector3d groupPagePos{groupX, groupY, 0}; // relative to page
return groupPagePos + itemOffsetPos;
}
void QGIView::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
Qt::KeyboardModifiers originalModifiers = event->modifiers();
@@ -334,7 +443,7 @@ void QGIView::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
void QGIView::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
// Base::Console().Message("QGIV::hoverEnterEvent()\n");
// Base::Console().Message("QGIV::hoverEnterEvent()\n");
Q_UNUSED(event);
// TODO don't like this but only solution at the minute (MLP)
if (isSelected()) {
@@ -360,7 +469,7 @@ void QGIView::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
//sets position in /Gui(graphics), not /App
void QGIView::setPosition(qreal xPos, qreal yPos)
{
// Base::Console().Message("QGIV::setPosition(%.3f, %.3f) (gui)\n", x, y);
// Base::Console().Message("QGIV::setPosition(%.3f, %.3f) (gui)\n", x, y);
double newX = xPos;
double newY = -yPos;
double oldX = pos().x();
@@ -389,9 +498,9 @@ QGIViewClip* QGIView::getClipGroup()
void QGIView::updateView(bool forceUpdate)
{
// Base::Console().Message("QGIV::updateView() - %s\n", getViewObject()->getNameInDocument());
// Base::Console().Message("QGIV::updateView() - %s\n", getViewObject()->getNameInDocument());
//allow/prevent dragging
//allow/prevent dragging
if (getViewObject()->isLocked()) {
setFlag(QGraphicsItem::ItemIsMovable, false);
} else {
@@ -415,10 +524,10 @@ void QGIView::updateView(bool forceUpdate)
//QGIVP derived classes do not need a rotate view method as rotation is handled on App side.
void QGIView::rotateView()
{
//NOTE: QPainterPaths have to be rotated individually. This transform handles Rotation for everything else.
//Scale is handled in GeometryObject for DVP & descendents
//Objects not descended from DVP must setScale for themselves
//note that setTransform(, ,rotation, ,) is not the same as setRotation!!!
//NOTE: QPainterPaths have to be rotated individually. This transform handles Rotation for everything else.
//Scale is handled in GeometryObject for DVP & descendents
//Objects not descended from DVP must setScale for themselves
//note that setTransform(, ,rotation, ,) is not the same as setRotation!!!
double rot = getViewObject()->Rotation.getValue();
QPointF centre = boundingRect().center();
setTransform(QTransform().translate(centre.x(), centre.y()).rotate(-rot).translate(-centre.x(), -centre.y()));
@@ -455,7 +564,7 @@ void QGIView::setViewFeature(TechDraw::DrawView *obj)
viewObj = obj;
viewName = obj->getNameInDocument();
//mark the actual QGraphicsItem so we can check what's in the scene later
//mark the actual QGraphicsItem so we can check what's in the scene later
setData(0, QString::fromUtf8("QGIV"));
setData(1, QString::fromUtf8(obj->getNameInDocument()));
}
@@ -470,7 +579,7 @@ void QGIView::toggleCache(bool state)
void QGIView::draw()
{
// Base::Console().Message("QGIV::draw()\n");
// Base::Console().Message("QGIV::draw()\n");
double xFeat, yFeat;
if (getViewObject()) {
xFeat = Rez::guiX(getViewObject()->X.getValue());
@@ -489,7 +598,7 @@ void QGIView::draw()
void QGIView::drawCaption()
{
// Base::Console().Message("QGIV::drawCaption()\n");
// Base::Console().Message("QGIV::drawCaption()\n");
prepareGeometryChange();
QRectF displayArea = customChildrenBoundingRect();
m_caption->setDefaultTextColor(m_colCurrent);
@@ -515,7 +624,7 @@ void QGIView::drawCaption()
void QGIView::drawBorder()
{
// Base::Console().Message("QGIV::drawBorder() - %s\n", getViewName());
// Base::Console().Message("QGIV::drawBorder() - %s\n", getViewName());
auto feat = getViewObject();
if (!feat)
return;
@@ -524,9 +633,9 @@ void QGIView::drawBorder()
auto vp = static_cast<ViewProviderDrawingView*>(getViewProvider(getViewObject()));
if (!getFrameState() && !vp->KeepLabel.getValue()) {
m_label->hide();
m_border->hide();
m_lock->hide();
m_label->hide();
m_border->hide();
m_lock->hide();
return;
}
@@ -596,8 +705,8 @@ void QGIView::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, Q
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
QGraphicsItemGroup::paint(painter, &myOption, widget);
}
@@ -622,15 +731,15 @@ QRectF QGIView::customChildrenBoundingRect() const
continue;
}
if ( (child->type() != dimItemType) &&
(child->type() != leaderItemType) &&
(child->type() != textLeaderItemType) &&
(child->type() != editablePathItemType) &&
(child->type() != movableTextItemType) &&
(child->type() != borderItemType) &&
(child->type() != labelItemType) &&
(child->type() != weldingSymbolItemType) &&
(child->type() != captionItemType) &&
(child->type() != centerMarkItemType)) {
(child->type() != leaderItemType) &&
(child->type() != textLeaderItemType) &&
(child->type() != editablePathItemType) &&
(child->type() != movableTextItemType) &&
(child->type() != borderItemType) &&
(child->type() != labelItemType) &&
(child->type() != weldingSymbolItemType) &&
(child->type() != captionItemType) &&
(child->type() != centerMarkItemType)) {
QRectF childRect = mapFromItem(child, child->boundingRect()).boundingRect();
result = result.united(childRect);
}
@@ -710,7 +819,7 @@ void QGIView::removeChild(QGIView* child)
bool QGIView::getFrameState()
{
// Base::Console().Message("QGIV::getFrameState() - %s\n", getViewName());
// Base::Console().Message("QGIV::getFrameState() - %s\n", getViewName());
TechDraw::DrawView* dv = getViewObject();
if (!dv) return true;
@@ -734,7 +843,7 @@ void QGIView::hideFrame()
void QGIView::addArbitraryItem(QGraphicsItem* qgi)
{
if (qgi) {
// m_randomItems.push_back(qgi);
// m_randomItems.push_back(qgi);
addToGroup(qgi);
qgi->show();
}
@@ -772,7 +881,7 @@ void QGIView::setStackFromVP()
{
TechDraw::DrawView* feature = getViewObject();
ViewProviderDrawingView* vpdv = static_cast<ViewProviderDrawingView*>
(getViewProvider(feature));
(getViewProvider(feature));
int z = vpdv->getZ();
setStack(z);
}
@@ -795,7 +904,7 @@ QColor QGIView::getSelectColor()
Base::Reference<ParameterGrp> QGIView::getParmGroupCol()
{
return App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Colors");
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Colors");
}
//convert input font size in mm to scene units

View File

@@ -55,6 +55,8 @@ class ViewProvider;
namespace TechDraw
{
class DrawView;
class DrawViewSection;
class DrawViewPart;
}
namespace TechDrawGui
@@ -124,7 +126,9 @@ public:
bool isSnapping() { return snapping; }
void snapPosition(QPointF& position);
void snapSectionView(const TechDraw::DrawViewSection* sectionView,
QPointF& newPosition);
Base::Vector3d projItemPagePos(TechDraw::DrawViewPart* item);
void alignTo(QGraphicsItem*, const QString &alignment);
QColor prefNormalColor(); //preference
@@ -202,6 +206,8 @@ private:
double m_lockHeight;
int m_zOrder;
bool m_snapped{false};
};
} // namespace