TechDraw: Axo Dimension Fixes (#26445)
* [TD]fix dim text on wrong side of dim line - this fixes the problem when the dimension line is +/- vertical * [TD]Avoid use of CosmeticVertex for Axo Dimension * [TD]fix CI warnings re unused variable * Update DrawViewPyImp.cpp per review comments.
This commit is contained in:
@@ -4,7 +4,7 @@ from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from Base.Metadata import export
|
||||
from Base.Metadata import export, constmethod
|
||||
|
||||
from App.DocumentObject import DocumentObject
|
||||
|
||||
@@ -27,10 +27,19 @@ class DrawView(DocumentObject):
|
||||
No return value. Replace the current label with a translated version where possible.
|
||||
"""
|
||||
...
|
||||
|
||||
@constmethod
|
||||
def getScale(self) -> Any:
|
||||
"""
|
||||
float scale = getScale(). Returns the correct scale for this view. Handles whether to
|
||||
use this view's scale property or a parent's view (as in a projection group).
|
||||
"""
|
||||
...
|
||||
|
||||
@constmethod
|
||||
def findParentPage(self) -> Any:
|
||||
"""
|
||||
DrawPage parent = findParentPage(). Returns the parent page that contains this view.
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
// inclusion of the generated files (generated out of DrawViewPy.xml)
|
||||
#include <Mod/TechDraw/App/DrawViewPy.h>
|
||||
#include <Mod/TechDraw/App/DrawViewPy.cpp>
|
||||
#include <Mod/TechDraw/App/DrawPagePy.h>
|
||||
|
||||
using namespace TechDraw;
|
||||
|
||||
@@ -78,7 +79,7 @@ PyObject* DrawViewPy::translateLabel(PyObject *args)
|
||||
}
|
||||
|
||||
//! return the correct scale for this view
|
||||
PyObject* DrawViewPy::getScale(PyObject *args)
|
||||
PyObject* DrawViewPy::getScale(PyObject *args) const
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, "")) {
|
||||
throw Py::TypeError("Do not understand passed parameter.");
|
||||
@@ -89,6 +90,18 @@ PyObject* DrawViewPy::getScale(PyObject *args)
|
||||
return PyFloat_FromDouble(dv->getScale());
|
||||
}
|
||||
|
||||
//! return the correct scale for this view
|
||||
PyObject* DrawViewPy::findParentPage(PyObject *args) const
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, "")) {
|
||||
throw Py::TypeError("Do not understand passed parameter.");
|
||||
}
|
||||
|
||||
DrawView* dv = getDrawViewPtr();
|
||||
DrawPage* parent = dv->findParentPage();
|
||||
|
||||
return Py::new_reference_to(parent->getPyObject());
|
||||
}
|
||||
|
||||
|
||||
PyObject *DrawViewPy::getCustomAttributes(const char* /*attr*/) const
|
||||
|
||||
@@ -38,7 +38,24 @@ import FreeCADGui as Gui
|
||||
import TechDrawTools.TDToolsUtil as Utils
|
||||
|
||||
import TechDraw
|
||||
from math import degrees
|
||||
import math
|
||||
|
||||
# A hack to deal with garbage in the low bits causing wrong decisions. dimensionLineAngle is in radians. If
|
||||
# dimensionLineAngle is 90deg +/- AngularTolerance, we treat it as a vertical dimension line. This affects which
|
||||
# side of the dimension line is used for the dimension text.
|
||||
def makePlumb(dimensionLineAngle):
|
||||
HalfPi = math.pi / 2.0
|
||||
|
||||
AngularTolerance = 0.01 # This value is a guess. It works for the file in issue #16172, but
|
||||
# seems small (~0.5deg).
|
||||
|
||||
if math.isclose(dimensionLineAngle, HalfPi, abs_tol=AngularTolerance):
|
||||
return HalfPi
|
||||
elif math.isclose(dimensionLineAngle, -HalfPi, abs_tol=AngularTolerance):
|
||||
return -HalfPie
|
||||
|
||||
return dimensionLineAngle
|
||||
|
||||
|
||||
class CommandAxoLengthDimension:
|
||||
"""Creates a 3D length dimension."""
|
||||
@@ -68,33 +85,57 @@ class CommandAxoLengthDimension:
|
||||
edges = Utils.getSelEdges(2)
|
||||
vertexes = Utils.getSelVertexes(0)
|
||||
|
||||
vertNames = list()
|
||||
edgeNames = list()
|
||||
if len(vertexes)<2:
|
||||
vertexes.append(edges[0].Vertexes[0])
|
||||
vertexes.append(edges[0].Vertexes[1])
|
||||
edgeNames = Utils.getSelEdgeNames(2)
|
||||
else:
|
||||
vertNames = Utils.getSelVertexNames(2)
|
||||
|
||||
view = Utils.getSelView()
|
||||
page = view.findParentPage()
|
||||
scale = view.getScale()
|
||||
|
||||
StartPt, EndPt = edges[1].Vertexes[0].Point, edges[1].Vertexes[1].Point
|
||||
extLineVec = EndPt.sub(StartPt)
|
||||
StartPt, EndPt = edges[0].Vertexes[0].Point, edges[0].Vertexes[1].Point
|
||||
dimLineVec = EndPt.sub(StartPt)
|
||||
|
||||
xAxis = App.Vector(1,0,0)
|
||||
extAngle = degrees(extLineVec.getAngle(xAxis))
|
||||
lineAngle = degrees(dimLineVec.getAngle(xAxis))
|
||||
extAngle = math.degrees(extLineVec.getAngle(xAxis))
|
||||
lineAngle = math.degrees(makePlumb(dimLineVec.getAngle(xAxis)))
|
||||
|
||||
if extLineVec.y < 0.0:
|
||||
extAngle = 180-extAngle
|
||||
if dimLineVec.y < 0.0:
|
||||
lineAngle = 180-lineAngle
|
||||
|
||||
if abs(extAngle-lineAngle)>0.1:
|
||||
distanceDim=TechDraw.makeDistanceDim(view,'Distance',vertexes[0].Point*scale,vertexes[1].Point*scale)
|
||||
# re issue: https://github.com/FreeCAD/FreeCAD/issues/13677
|
||||
# Instead of using makeDistanceDim (which is meant for extent dimensions), we use the
|
||||
# same steps as in CommandCreateDims.cpp to create a regular length dimension. This avoids
|
||||
# the creation of CosmeticVertex objects to serve as dimension points. These CosmeticVertex
|
||||
# objects are never deleted, but are no longer used once their dimension is deleted.
|
||||
# distanceDim=TechDraw.makeDistanceDim(view,'Distance',vertexes[0].Point*scale,vertexes[1].Point*scale)
|
||||
distanceDim = view.Document.addObject("TechDraw::DrawViewDimension", "Dimension")
|
||||
distanceDim.Type = "Distance"
|
||||
distanceDim.MeasureType = "Projected" #should this not be True?
|
||||
self.setReferences(distanceDim, view, edgeNames, vertNames)
|
||||
page.addView(distanceDim)
|
||||
|
||||
distanceDim.AngleOverride = True
|
||||
distanceDim.LineAngle = lineAngle
|
||||
distanceDim.ExtensionAngle = extAngle
|
||||
distanceDim.X = scale*(vertexes[0].Point.x+vertexes[1].Point.x)/2
|
||||
distanceDim.Y = scale*(vertexes[0].Point.y+vertexes[1].Point.y)/2
|
||||
distanceDim.recompute()
|
||||
|
||||
distanceDim.recompute() # ensure linearPoints has been set
|
||||
|
||||
# as in CmdCreateDims::positionDimText:
|
||||
linearPoints = distanceDim.getLinearPoints()
|
||||
mid = (linearPoints[0] + linearPoints[1]) / 2
|
||||
distanceDim.X = mid.x
|
||||
distanceDim.Y = -mid.y
|
||||
|
||||
(px,py,pz) = Utils.getCoordinateVectors(view)
|
||||
arrowTips = distanceDim.getArrowPositions()
|
||||
@@ -114,8 +155,10 @@ class CommandAxoLengthDimension:
|
||||
|
||||
distanceDim.recompute()
|
||||
view.requestPaint()
|
||||
|
||||
Gui.Selection.clearSelection()
|
||||
App.closeActiveTransaction()
|
||||
view.touch() # make view claim its new child
|
||||
|
||||
def IsActive(self):
|
||||
"""Return True when the command should be active or False when it should be disabled (greyed)."""
|
||||
@@ -146,6 +189,16 @@ class CommandAxoLengthDimension:
|
||||
else:
|
||||
return formatSpec.format(value)
|
||||
|
||||
def setReferences(self, dimension, view, edgeNameList, vertexNameList):
|
||||
references = list()
|
||||
if vertexNameList:
|
||||
for vert in vertexNameList:
|
||||
references.append((view, vert))
|
||||
else:
|
||||
references.append((view, edgeNameList[0]))
|
||||
|
||||
dimension.References2D = references
|
||||
|
||||
#
|
||||
# The command must be "registered" with a unique name by calling its class.
|
||||
Gui.addCommand('TechDraw_AxoLengthDimension', CommandAxoLengthDimension())
|
||||
|
||||
@@ -155,3 +155,68 @@ def getCoordinateVectors(view):
|
||||
py = wire2D.Edges[1].Vertexes[0].Point
|
||||
pz = wire2D.Edges[2].Vertexes[0].Point
|
||||
return (px,py,pz)
|
||||
|
||||
|
||||
# +/- the same as getSelVertexes, but returns the vertex name instead of the vertex object.
|
||||
def getSelVertexNames(nVertex=1, nSel=0):
|
||||
'''
|
||||
vertexNames = getSelVertexNames(nVertex)
|
||||
nVertex=1 ... min. number of selected vertexes
|
||||
nSel=0 ... number of selected view, 0 = first selected
|
||||
Return a list of the names of the selected vertexes if at least nVertex vertexes are selected, otherwise return False
|
||||
'''
|
||||
view = getSelView(nSel)
|
||||
if not view:
|
||||
return False
|
||||
|
||||
if not Gui.Selection.getSelectionEx():
|
||||
displayMessage('TechDraw_Utils',
|
||||
QT_TRANSLATE_NOOP('TechDraw_Utils','No vertex selected'))
|
||||
return False
|
||||
objectList = Gui.Selection.getSelectionEx()[nSel].SubElementNames
|
||||
|
||||
vertexNames = []
|
||||
for objectString in objectList:
|
||||
if objectString[0:6] == 'Vertex':
|
||||
vertexNames.append(objectString)
|
||||
|
||||
if (len(vertexNames) < nVertex):
|
||||
displayMessage('TechDraw_Utils',
|
||||
QT_TRANSLATE_NOOP('TechDraw_Utils','Select at least ')+
|
||||
str(nVertex)+
|
||||
QT_TRANSLATE_NOOP('TechDraw_Utils',' vertexes'))
|
||||
return False
|
||||
|
||||
return vertexNames
|
||||
|
||||
# +/- the same as getSelEdges, but returns the edge name instead of the vertex object.
|
||||
def getSelEdgeNames(nEdge=1, nSel=0):
|
||||
'''
|
||||
edges = getSelEdgeNames(nEdge)
|
||||
nEdge=1 ... min. number of selected edges
|
||||
nSel=0 ... number of selected view, 0 = first selected
|
||||
Return a list of names for selected edges if at least nedge edges are selected, otherwise return False
|
||||
'''
|
||||
view = getSelView(nSel)
|
||||
if not view:
|
||||
return False
|
||||
|
||||
if not Gui.Selection.getSelectionEx():
|
||||
displayMessage('TechDraw_Utils',
|
||||
QT_TRANSLATE_NOOP('TechDraw_Utils','No edge selected'))
|
||||
return False
|
||||
objectList = Gui.Selection.getSelectionEx()[nSel].SubElementNames
|
||||
|
||||
edgeNames = []
|
||||
for objectString in objectList:
|
||||
if objectString[0:4] == 'Edge':
|
||||
edgeNames.append(objectString)
|
||||
|
||||
if (len(edgeNames) < nEdge):
|
||||
displayMessage('TechDraw_Utils',
|
||||
QT_TRANSLATE_NOOP('TechDraw_Utils','Select at least ')+
|
||||
str(nEdge)+
|
||||
QT_TRANSLATE_NOOP('TechDraw_Utils',' edges'))
|
||||
return False
|
||||
else:
|
||||
return edgeNames
|
||||
|
||||
Reference in New Issue
Block a user