Enhance Radius dimension drawing
This commit is contained in:
committed by
WandererFan
parent
0cc2920862
commit
f704340f2b
@@ -45,10 +45,10 @@ QGIArrow::QGIArrow() :
|
||||
m_fill(Qt::SolidPattern),
|
||||
m_size(5.0),
|
||||
m_style(0),
|
||||
m_flipped(false),
|
||||
m_dirMode(false),
|
||||
m_dir(Base::Vector3d(1.0,0.0,0.0))
|
||||
{
|
||||
isFlipped = false;
|
||||
m_brush.setStyle(m_fill);
|
||||
|
||||
setCacheMode(QGraphicsItem::NoCache);
|
||||
@@ -57,43 +57,38 @@ QGIArrow::QGIArrow() :
|
||||
setFlag(QGraphicsItem::ItemIsMovable, false);
|
||||
}
|
||||
|
||||
|
||||
void QGIArrow::flip(bool state) {
|
||||
isFlipped = state;
|
||||
}
|
||||
|
||||
void QGIArrow::draw() {
|
||||
QPainterPath path;
|
||||
if (m_style == 0) {
|
||||
if (m_dirMode) {
|
||||
path = makeFilledTriangle(getDirection(), m_size,m_size/6.0);
|
||||
} else {
|
||||
path = makeFilledTriangle(m_size,m_size/6.0,isFlipped); //"arrow l/w sb 3/1" ??
|
||||
path = makeFilledTriangle(m_size,m_size/6.0,isFlipped()); //"arrow l/w sb 3/1" ??
|
||||
}
|
||||
} else if (m_style == 1) {
|
||||
if (m_dirMode) {
|
||||
path = makeOpenArrow(getDirection(), m_size,m_size/3.0); //broad arrow?
|
||||
} else {
|
||||
path = makeOpenArrow(m_size,m_size/3.0,isFlipped);
|
||||
path = makeOpenArrow(m_size,m_size/3.0,isFlipped());
|
||||
}
|
||||
} else if (m_style == 2) {
|
||||
if (m_dirMode) {
|
||||
path = makeHashMark(getDirection(), m_size/2.0,m_size/2.0); //big enough?
|
||||
} else {
|
||||
path = makeHashMark(m_size/2.0,m_size/2.0,isFlipped); //big enough?
|
||||
path = makeHashMark(m_size/2.0,m_size/2.0,isFlipped()); //big enough?
|
||||
}
|
||||
} else if (m_style == 3) {
|
||||
path = makeDot(m_size/2.0,m_size/2.0,isFlipped);
|
||||
path = makeDot(m_size/2.0,m_size/2.0,isFlipped());
|
||||
} else if (m_style == 4) {
|
||||
path = makeOpenDot(m_size/2.0,m_size/2.0,isFlipped);
|
||||
path = makeOpenDot(m_size/2.0,m_size/2.0,isFlipped());
|
||||
} else if (m_style == 5) {
|
||||
if (m_dirMode) {
|
||||
path = makeForkArrow(getDirection(), m_size/2.0,m_size/2.0); //big enough?
|
||||
} else {
|
||||
path = makeForkArrow(m_size/2.0,m_size/2.0,isFlipped); //big enough?
|
||||
path = makeForkArrow(m_size/2.0,m_size/2.0,isFlipped()); //big enough?
|
||||
}
|
||||
} else {
|
||||
path = makeFilledTriangle(m_size,m_size/6.0,isFlipped); //sb a question mark or ???
|
||||
path = makeFilledTriangle(m_size,m_size/6.0,isFlipped()); //sb a question mark or ???
|
||||
}
|
||||
setPath(path);
|
||||
}
|
||||
|
||||
@@ -46,15 +46,18 @@ public:
|
||||
|
||||
public:
|
||||
void draw();
|
||||
void flip(bool state);
|
||||
bool isFlipped() { return m_flipped; }
|
||||
void setFlipped(bool flipped) { m_flipped = flipped; }
|
||||
void flip() { m_flipped = !m_flipped; }
|
||||
double getSize() { return m_size; }
|
||||
void setSize(double s);
|
||||
int getStyle() { return m_style; }
|
||||
void setStyle(int s) { m_style = s; }
|
||||
bool getDirMode() { return m_dirMode; }
|
||||
void setDirMode(bool b) { m_dirMode = b; }
|
||||
Base::Vector3d getDirection(void) { return m_dir; }
|
||||
Base::Vector3d getDirection(void) { return m_flipped ? -m_dir : m_dir; }
|
||||
void setDirection(Base::Vector3d v) { m_dir = v; }
|
||||
void setDirection(double angle) { m_dir = Base::Vector3d(cos(angle), sin(angle), 0.0); }
|
||||
static int getPrefArrowStyle();
|
||||
static double getPrefArrowSize();
|
||||
static double getOverlapAdjust(int style, double size);
|
||||
@@ -78,7 +81,7 @@ private:
|
||||
Qt::BrushStyle m_fill;
|
||||
double m_size;
|
||||
int m_style;
|
||||
bool isFlipped;
|
||||
bool m_flipped;
|
||||
bool m_dirMode;
|
||||
Base::Vector3d m_dir;
|
||||
};
|
||||
|
||||
@@ -69,6 +69,10 @@
|
||||
#include "ViewProviderDimension.h"
|
||||
#include "DrawGuiUtil.h"
|
||||
|
||||
#ifndef M_2PI
|
||||
#define M_2PI 6.283185307179586476925287
|
||||
#endif
|
||||
|
||||
//TODO: hide the Qt coord system (+y down).
|
||||
|
||||
using namespace TechDraw;
|
||||
@@ -182,8 +186,7 @@ void QGIDatumLabel::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
|
||||
QStyleOptionGraphicsItem myOption(*option);
|
||||
myOption.state &= ~QStyle::State_Selected;
|
||||
|
||||
// painter->drawRect(boundingRect()); //good for debugging
|
||||
|
||||
//painter->drawRect(boundingRect()); //good for debugging
|
||||
}
|
||||
|
||||
void QGIDatumLabel::setPosFromCenter(const double &xCenter, const double &yCenter)
|
||||
@@ -1171,127 +1174,7 @@ void QGIViewDimension::draw()
|
||||
// dim->getViewPart()->addVertex(curveCenter,true);
|
||||
// }
|
||||
} else if(strcmp(dimType, "Radius") == 0) {
|
||||
// preferred terminology: Dimension Text, Dimension Line(s), Extension Lines, Arrowheads
|
||||
// radius gets 1 dimension line from the dimension text to a point on the curve
|
||||
Base::Vector3d pointOnCurve,curveCenter;
|
||||
double radius;
|
||||
arcPoints pts = dim->getArcPoints();
|
||||
bool isArc = pts.isArc;
|
||||
radius = Rez::guiX(pts.radius);
|
||||
curveCenter = Rez::guiX(pts.center);
|
||||
pointOnCurve = Rez::guiX(pts.onCurve.first);
|
||||
QRectF mappedRect = mapRectFromItem(datumLabel, datumLabel->boundingRect());
|
||||
lblCenter = Base::Vector3d(mappedRect.center().x(), mappedRect.center().y(), 0.0);
|
||||
|
||||
// Note Bounding Box size is not the same width or height as text (only used for finding center)
|
||||
float bbX = datumLabel->boundingRect().width();
|
||||
float bbY = datumLabel->boundingRect().height();
|
||||
datumLabel->setTransformOriginPoint(bbX / 2, bbY /2);
|
||||
datumLabel->setRotation(0.0); //label is always right side up & horizontal
|
||||
|
||||
//if inside the arc (len(DimLine < radius)) arrow goes from center to edge away from label
|
||||
//if outside the arc arrow kinks, then goes to edge nearest label
|
||||
bool outerPlacement = false;
|
||||
if ((lblCenter - curveCenter).Length() > radius) { //label is outside circle
|
||||
outerPlacement = true;
|
||||
}
|
||||
|
||||
Base::Vector3d dirDimLine = (lblCenter - curveCenter).Normalize();
|
||||
if (fabs(dirDimLine.Length()) < (Precision::Confusion())) {
|
||||
dirDimLine = Base::Vector3d(-1.0,0.0,0.0);
|
||||
}
|
||||
// Base::Vector3d adjustDir = dirDimLine; //adjust line lengths for arrowheads
|
||||
double dimLineAdjust = Rez::guiX(QGIArrow::getOverlapAdjust(QGIArrow::getPrefArrowStyle(),
|
||||
QGIArrow::getPrefArrowSize()));
|
||||
|
||||
|
||||
Base::Vector3d dLineStart;
|
||||
Base::Vector3d dLineEnd; //?? radius draws line from text to curve?? (diam is curve to text!)
|
||||
Base::Vector3d kinkPoint;
|
||||
margin = Rez::guiX(5.f); //space around label
|
||||
double kinkLength = Rez::guiX(5.0); //sb % of horizontal dist(lblCenter,curveCenter)???
|
||||
if (outerPlacement) {
|
||||
double offset = getDefaultTextHorizontalOffset(lblCenter.x > curveCenter.x);
|
||||
dLineStart.y = lblCenter.y;
|
||||
dLineStart.x = lblCenter.x + offset; //start at right or left of label
|
||||
kinkLength = (lblCenter.x < curveCenter.x) ? kinkLength : -kinkLength;
|
||||
kinkPoint.y = dLineStart.y;
|
||||
kinkPoint.x = dLineStart.x + kinkLength;
|
||||
pointOnCurve = curveCenter + (kinkPoint - curveCenter).Normalize() * radius;
|
||||
dLineEnd = pointOnCurve + (kinkPoint - curveCenter).Normalize() * dimLineAdjust;
|
||||
if ((kinkPoint - curveCenter).Length() < radius) {
|
||||
dirDimLine = (curveCenter - kinkPoint).Normalize();
|
||||
} else {
|
||||
dirDimLine = (kinkPoint - curveCenter).Normalize();
|
||||
}
|
||||
} else {
|
||||
dLineStart = curveCenter - dirDimLine * margin; //just beyond centerpoint
|
||||
pointOnCurve = curveCenter - dirDimLine * radius;
|
||||
dLineEnd = pointOnCurve + dirDimLine * dimLineAdjust;
|
||||
kinkPoint = dLineStart; //no kink
|
||||
}
|
||||
|
||||
//handle partial arc weird cases
|
||||
if (isArc) {
|
||||
Base::Vector3d midPt = Rez::guiX(pts.midArc);
|
||||
Base::Vector3d startPt = Rez::guiX(pts.arcEnds.first);
|
||||
Base::Vector3d endPt = Rez::guiX(pts.arcEnds.second);
|
||||
if (outerPlacement &&
|
||||
!dim->leaderIntersectsArc(Rez::appX(curveCenter),Rez::appX(kinkPoint))) { //keep pathological case within arc
|
||||
pointOnCurve = midPt;
|
||||
} else if (!outerPlacement) {
|
||||
if ((midPt - lblCenter).Length() > (midPt - curveCenter).Length()) { //label is farther than center
|
||||
dirDimLine = dirDimLine * -1;
|
||||
}
|
||||
dLineStart = curveCenter + dirDimLine * margin;
|
||||
pointOnCurve = curveCenter + dirDimLine * radius;
|
||||
dLineEnd = pointOnCurve - dirDimLine * dimLineAdjust;
|
||||
kinkPoint = dLineStart;
|
||||
if (!dim->leaderIntersectsArc(Rez::appX(dLineStart),Rez::appX(pointOnCurve))) { //keep pathological case within arc
|
||||
if ((pointOnCurve - endPt).Length() < (pointOnCurve - startPt).Length()) {
|
||||
if (!pts.arcCW ) {
|
||||
pointOnCurve = endPt;
|
||||
} else {
|
||||
pointOnCurve = startPt;
|
||||
}
|
||||
} else {
|
||||
if (!pts.arcCW ) {
|
||||
pointOnCurve = startPt;
|
||||
} else {
|
||||
pointOnCurve = endPt;
|
||||
}
|
||||
}
|
||||
dLineStart = curveCenter + (pointOnCurve - curveCenter).Normalize() * margin;
|
||||
dLineEnd = pointOnCurve - dirDimLine * dimLineAdjust;
|
||||
kinkPoint = dLineStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QPainterPath dLinePath; //radius dimension line path
|
||||
dLinePath.moveTo(dLineStart.x, dLineStart.y);
|
||||
dLinePath.lineTo(kinkPoint.x, kinkPoint.y);
|
||||
dLinePath.lineTo(dLineEnd.x, dLineEnd.y);
|
||||
|
||||
dimLines->setPath(dLinePath);
|
||||
//NOTE: in this case aHead1->dirMode is false and Qt rotation is used to point arrowhead
|
||||
aHead1->setStyle(QGIArrow::getPrefArrowStyle());
|
||||
aHead1->setSize(QGIArrow::getPrefArrowSize());
|
||||
aHead1->draw();
|
||||
|
||||
Base::Vector3d ar1Pos = pointOnCurve;
|
||||
Base::Vector3d dirArrowLine = (pointOnCurve - kinkPoint).Normalize();
|
||||
float arAngle = atan2(dirArrowLine.y, dirArrowLine.x) * 180 / M_PI;
|
||||
|
||||
aHead1->setPos(ar1Pos.x, ar1Pos.y);
|
||||
aHead1->setRotation(arAngle);
|
||||
aHead1->show();
|
||||
aHead2->hide();
|
||||
// if (dim->CentreLines.getValue()) {
|
||||
// curveCenterMark->setPos(curveCenter.x,curveCenter.y);
|
||||
// centerMark->show();
|
||||
// dim->getViewPart()->addVertex(curveCenter,true);
|
||||
// }
|
||||
drawRadius(dim, vp);
|
||||
} else if( (strcmp(dimType, "Angle") == 0) ||
|
||||
(strcmp(dimType, "Angle3Pt") == 0)) {
|
||||
anglePoints pts = dim->getAnglePoints();
|
||||
@@ -1408,7 +1291,7 @@ void QGIViewDimension::draw()
|
||||
dimLines->setPath(path);
|
||||
|
||||
//NOTE: arrowheads are dirMode(false)
|
||||
aHead1->flip(true);
|
||||
aHead1->setFlipped(true);
|
||||
aHead1->setStyle(QGIArrow::getPrefArrowStyle());
|
||||
aHead1->setSize(QGIArrow::getPrefArrowSize());
|
||||
aHead1->draw();
|
||||
@@ -1489,6 +1372,281 @@ void QGIViewDimension::draw()
|
||||
}
|
||||
}
|
||||
|
||||
int QGIViewDimension::classifyPointToArcPosition(double pointDistance, double pointAngle,
|
||||
double radius, double startAngle, double endAngle, bool clockwise) const
|
||||
{
|
||||
if (angleWithinSector(pointAngle, startAngle, endAngle, clockwise)) {
|
||||
return pointDistance > radius ? OUTER_SECTOR : INNER_SECTOR;
|
||||
}
|
||||
|
||||
if (angleWithinSector(addAngles(pointAngle, M_PI), startAngle, endAngle, clockwise)) {
|
||||
return OPPOSITE_SECTOR;
|
||||
}
|
||||
|
||||
return COMPLEMENT_SECTOR;
|
||||
}
|
||||
|
||||
double QGIViewDimension::computeLineAndLabelAngles(Base::Vector3d lineTarget, Base::Vector3d labelCenter,
|
||||
double lineLabelDistance, double &lineAngle, double &labelAngle) const
|
||||
{
|
||||
// By default horizontal line and no label rotation
|
||||
lineAngle = 0.0;
|
||||
labelAngle = 0.0;
|
||||
|
||||
Base::Vector3d rawDirection(labelCenter - lineTarget);
|
||||
double rawDistance = rawDirection.Length();
|
||||
if (rawDistance < Precision::Confusion()) { // Almost single point, can't tell
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double rawAngle = atan2(rawDirection.y, rawDirection.x);
|
||||
lineAngle = rawAngle;
|
||||
|
||||
// If we are too close to the line origin, no further adjustments
|
||||
if (lineLabelDistance >= rawDistance) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// Rotate the line by angle between the label rectangle center and label bottom side center
|
||||
double devAngle = getStandardLinePlacement(rawAngle)*asin(lineLabelDistance/rawDistance);
|
||||
lineAngle = addAngles(lineAngle, devAngle);
|
||||
|
||||
labelAngle = devAngle > 0.0 ? lineAngle : addAngles(lineAngle, M_PI);
|
||||
|
||||
return devAngle;
|
||||
}
|
||||
|
||||
Base::Vector3d QGIViewDimension::computeLineOriginPoint(Base::Vector3d lineTarget, double projectedLabelDistance,
|
||||
double lineAngle, double labelWidth, double direction) const
|
||||
{
|
||||
return lineTarget + (projectedLabelDistance + direction*(0.5*labelWidth + getDefaultReferenceLineOverhang()))
|
||||
*Base::Vector3d(cos(lineAngle), sin(lineAngle), 0.0);
|
||||
}
|
||||
|
||||
void QGIViewDimension::drawRadius(TechDraw::DrawViewDimension *dimension, ViewProviderDimension *viewProvider) const
|
||||
{
|
||||
// Preferred terminology according to ISO 129-1 for Radius:
|
||||
// Dimensional Value, Leader Line, Reference Line, Terminator
|
||||
|
||||
QPainterPath radiusPath;
|
||||
aHead1->setFlipped(false);
|
||||
|
||||
datumLabel->setRotation(0.0);
|
||||
QRectF mappedRect = mapRectFromItem(datumLabel, datumLabel->boundingRect());
|
||||
Base::Vector3d labelCenter = Base::Vector3d(mappedRect.center().x(), mappedRect.center().y(), 0.0);
|
||||
|
||||
arcPoints curvePoints = dimension->getArcPoints();
|
||||
|
||||
Base::Vector3d curveCenter = Rez::guiX(curvePoints.center);
|
||||
double mappedRadius = Rez::guiX(curvePoints.radius);
|
||||
double centerDistance = (labelCenter - curveCenter).Length();
|
||||
|
||||
double arcStartAngle;
|
||||
double arcEndAngle;
|
||||
bool arcClockwise;
|
||||
if (curvePoints.isArc) {
|
||||
arcStartAngle = atan2(curvePoints.arcEnds.first.y - curvePoints.center.y,
|
||||
curvePoints.arcEnds.first.x - curvePoints.center.x);
|
||||
arcEndAngle = atan2(curvePoints.arcEnds.second.y - curvePoints.center.y,
|
||||
curvePoints.arcEnds.second.x - curvePoints.center.x);
|
||||
arcClockwise = !curvePoints.arcCW;
|
||||
}
|
||||
else { // A circle arc covers the whole plane
|
||||
arcStartAngle = -M_PI;
|
||||
arcEndAngle = +M_PI;
|
||||
arcClockwise = false;
|
||||
}
|
||||
|
||||
double labelAngle = 0.0;
|
||||
Base::Vector3d arcPoint;
|
||||
double lineAngle;
|
||||
|
||||
if (viewProvider->TiltText.getValue()) { // We may rotate the label so no reference line is needed
|
||||
double devAngle = computeLineAndLabelAngles(curveCenter, labelCenter,
|
||||
getDefaultTextVerticalOffset(), lineAngle, labelAngle);
|
||||
// Correct the label center distance projected on the leader line
|
||||
centerDistance *= cos(devAngle);
|
||||
|
||||
Base::Vector3d originPoint;
|
||||
Base::Vector3d targetPoint;
|
||||
switch (classifyPointToArcPosition(centerDistance, lineAngle, mappedRadius,
|
||||
arcStartAngle, arcEndAngle, arcClockwise)) {
|
||||
case INNER_SECTOR: {
|
||||
// The label is placed within the arc sector angle, there's always point
|
||||
// on the arc where the leader line can cross it perpendicularly
|
||||
arcPoint = curveCenter + mappedRadius*Base::Vector3d(cos(lineAngle), sin(lineAngle), 0.0);
|
||||
|
||||
if (viewProvider->ExtendToCenter.getValue()) { // Start in the very center
|
||||
originPoint = curveCenter;
|
||||
}
|
||||
else { // Start on the label side closer to the center
|
||||
originPoint = computeLineOriginPoint(curveCenter, centerDistance, lineAngle,
|
||||
mappedRect.width(), -1.0);
|
||||
}
|
||||
targetPoint = arcPoint;
|
||||
break;
|
||||
}
|
||||
case OUTER_SECTOR: {
|
||||
// Same situation as when on the inner side of sector
|
||||
arcPoint = curveCenter + mappedRadius*Base::Vector3d(cos(lineAngle), sin(lineAngle), 0.0);
|
||||
aHead1->flip();
|
||||
|
||||
originPoint = computeLineOriginPoint(curveCenter, centerDistance, lineAngle,
|
||||
mappedRect.width(), +1.0);
|
||||
// If leader line shall not be extended to the center, start on the arc projection
|
||||
targetPoint = viewProvider->ExtendToCenter.getValue() ? curveCenter : arcPoint;
|
||||
break;
|
||||
}
|
||||
case OPPOSITE_SECTOR: {
|
||||
// If the label is placed within the vertically opposite angle of the arc sector,
|
||||
// the leader line passing through the arc center can mark a point on the arc
|
||||
arcPoint = curveCenter - mappedRadius*Base::Vector3d(cos(lineAngle), sin(lineAngle), 0.0);
|
||||
aHead1->flip();
|
||||
|
||||
originPoint = computeLineOriginPoint(curveCenter, centerDistance, lineAngle,
|
||||
mappedRect.width(), +1.0);
|
||||
targetPoint = arcPoint;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// Label outside both arc wedges
|
||||
arcPoint = Rez::guiX(curvePoints.midArc);
|
||||
aHead1->flip();
|
||||
devAngle = computeLineAndLabelAngles(arcPoint, labelCenter,
|
||||
getDefaultTextVerticalOffset(), lineAngle, labelAngle);
|
||||
centerDistance = (labelCenter - arcPoint).Length()*cos(devAngle);
|
||||
|
||||
originPoint = computeLineOriginPoint(arcPoint, centerDistance, lineAngle,
|
||||
mappedRect.width(), +1.0);
|
||||
targetPoint = arcPoint;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw only the leader line from start point to end point
|
||||
radiusPath.moveTo(originPoint.x, originPoint.y);
|
||||
radiusPath.lineTo(targetPoint.x, targetPoint.y);
|
||||
}
|
||||
else { // The dimensional value text must stay horizontal
|
||||
Base::Vector3d leftJoint(mappedRect.left() - getDefaultReferenceLineOverhang(),
|
||||
labelCenter.y + getDefaultTextVerticalOffset(), 0.0);
|
||||
Base::Vector3d rightJoint(mappedRect.right() + getDefaultReferenceLineOverhang(),
|
||||
labelCenter.y + getDefaultTextVerticalOffset(), 0.0);
|
||||
|
||||
double leftAngle = atan2(leftJoint.y - curveCenter.y, leftJoint.x - curveCenter.x);
|
||||
double rightAngle = atan2(rightJoint.y - curveCenter.y, rightJoint.x - curveCenter.x);
|
||||
|
||||
int leftPosition = classifyPointToArcPosition((leftJoint - curveCenter).Length(),
|
||||
leftAngle, mappedRadius, arcStartAngle, arcEndAngle, arcClockwise);
|
||||
int rightPosition = classifyPointToArcPosition((rightJoint - curveCenter).Length(),
|
||||
rightAngle, mappedRadius, arcStartAngle, arcEndAngle, arcClockwise);
|
||||
|
||||
Base::Vector3d originPoint;
|
||||
Base::Vector3d jointPoint;
|
||||
Base::Vector3d targetPoint;
|
||||
if (leftPosition >= OPPOSITE_SECTOR || rightPosition >= OPPOSITE_SECTOR) {
|
||||
// At least from one of the reference line sides can run the leader line
|
||||
// perpendicularly to the arc, i.e. in direction to the center
|
||||
if (leftPosition >= OPPOSITE_SECTOR && rightPosition >= OPPOSITE_SECTOR) {
|
||||
// Both are acceptable, so choose the more convenient one
|
||||
double leftBend = leftPosition == INNER_SECTOR ? M_PI - fabs(leftAngle) : fabs(leftAngle);
|
||||
double rightBend = rightPosition == INNER_SECTOR ? fabs(rightAngle) : M_PI - fabs(rightAngle);
|
||||
|
||||
// If right leader line bends less or does not cross the dimensional value,
|
||||
// use it by marking left point as outlayer
|
||||
if (leftBend <= M_PI_2 || rightBend <= M_PI_2) { // At least one line is not crossing the text
|
||||
if (rightBend < leftBend) {
|
||||
leftPosition = COMPLEMENT_SECTOR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
bool leftDown = leftPosition == INNER_SECTOR ? leftAngle > 0.0 : leftAngle < 0.0;
|
||||
bool rightDown = rightPosition == INNER_SECTOR ? rightAngle > 0.0 : rightAngle < 0.0;
|
||||
|
||||
if (leftDown == rightDown) { // Both lines go downwards or upwards
|
||||
if (rightBend < leftBend) {
|
||||
leftPosition = COMPLEMENT_SECTOR;
|
||||
}
|
||||
}
|
||||
else if (rightDown) {
|
||||
leftPosition = COMPLEMENT_SECTOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int resultPosition;
|
||||
if (leftPosition >= OPPOSITE_SECTOR) {
|
||||
originPoint = rightJoint;
|
||||
jointPoint = leftJoint;
|
||||
lineAngle = leftAngle;
|
||||
resultPosition = leftPosition;
|
||||
}
|
||||
else {
|
||||
originPoint = leftJoint;
|
||||
jointPoint = rightJoint;
|
||||
lineAngle = rightAngle;
|
||||
resultPosition = rightPosition;
|
||||
}
|
||||
|
||||
switch (resultPosition) {
|
||||
case INNER_SECTOR:
|
||||
arcPoint = curveCenter + mappedRadius*Base::Vector3d(cos(lineAngle), sin(lineAngle), 0.0);
|
||||
targetPoint = arcPoint;
|
||||
break;
|
||||
case OUTER_SECTOR:
|
||||
arcPoint = curveCenter + mappedRadius*Base::Vector3d(cos(lineAngle), sin(lineAngle), 0.0);
|
||||
// If desired, extend the target point to the center
|
||||
targetPoint = viewProvider->ExtendToCenter.getValue() ? curveCenter : arcPoint;
|
||||
aHead1->flip();
|
||||
break;
|
||||
case OPPOSITE_SECTOR:
|
||||
arcPoint = curveCenter - mappedRadius*Base::Vector3d(cos(lineAngle), sin(lineAngle), 0.0);
|
||||
targetPoint = arcPoint;
|
||||
aHead1->flip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else { // Both joint points lay outside the vertical angles
|
||||
arcPoint = Rez::guiX(curvePoints.midArc);
|
||||
|
||||
if (labelCenter.x >= arcPoint.x) { // Place the dimensional value right
|
||||
originPoint = rightJoint;
|
||||
jointPoint = leftJoint;
|
||||
}
|
||||
else { // Place the dimensional value left
|
||||
originPoint = leftJoint;
|
||||
jointPoint = rightJoint;
|
||||
}
|
||||
|
||||
targetPoint = arcPoint;
|
||||
lineAngle = atan2(targetPoint.y - jointPoint.y, targetPoint.x - jointPoint.x);
|
||||
}
|
||||
|
||||
radiusPath.moveTo(originPoint.x, originPoint.y);
|
||||
radiusPath.lineTo(jointPoint.x, jointPoint.y);
|
||||
radiusPath.lineTo(targetPoint.x, targetPoint.y);
|
||||
}
|
||||
|
||||
datumLabel->setTransformOriginPoint(datumLabel->boundingRect().width()*0.5,
|
||||
datumLabel->boundingRect().height()*0.5);
|
||||
datumLabel->setRotation(labelAngle*180.0/M_PI);
|
||||
|
||||
dimLines->setPath(radiusPath);
|
||||
|
||||
aHead1->setPos(arcPoint.x, arcPoint.y);
|
||||
aHead1->setDirMode(true);
|
||||
aHead1->setDirection(lineAngle);
|
||||
if (viewProvider->FlipArrowheads.getValue()) {
|
||||
aHead1->flip();
|
||||
}
|
||||
aHead1->setStyle(QGIArrow::getPrefArrowStyle());
|
||||
aHead1->setSize(QGIArrow::getPrefArrowSize());
|
||||
aHead1->draw();
|
||||
aHead1->show();
|
||||
|
||||
aHead2->hide();
|
||||
}
|
||||
|
||||
QColor QGIViewDimension::getNormalColor()
|
||||
{
|
||||
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
|
||||
@@ -1613,6 +1771,50 @@ double QGIViewDimension::getDefaultTextVerticalOffset() const
|
||||
return textMult*Rez::guiX(vp->Fontsize.getValue()) + TextOffsetFudge;
|
||||
}
|
||||
|
||||
double QGIViewDimension::getDefaultReferenceLineOverhang() const
|
||||
{
|
||||
return 2.0*TextOffsetFudge;
|
||||
}
|
||||
|
||||
double QGIViewDimension::getStandardLinePlacement(double labelAngle)
|
||||
{
|
||||
// According to ISO 129-1 Standard Figure 23, the bordering angle is 2/3 PI, resp. -1/3 PI
|
||||
// As Qt Y axis points downwards, all signs are flipped
|
||||
return labelAngle > +M_PI/3.0 || labelAngle < -2.0*M_PI/3.0
|
||||
? -1.0 : +1.0;
|
||||
}
|
||||
|
||||
bool QGIViewDimension::angleWithinSector(double testAngle, double startAngle, double endAngle, bool clockwise)
|
||||
{
|
||||
if (clockwise) {
|
||||
std::swap(startAngle, endAngle);
|
||||
}
|
||||
|
||||
if (endAngle < startAngle) {
|
||||
endAngle += M_2PI;
|
||||
}
|
||||
|
||||
if (testAngle < startAngle) {
|
||||
testAngle += M_2PI;
|
||||
}
|
||||
|
||||
return testAngle <= endAngle;
|
||||
}
|
||||
|
||||
double QGIViewDimension::addAngles(double angle1, double angle2)
|
||||
{
|
||||
angle1 += angle2;
|
||||
|
||||
if (angle2 >= 0.0) {
|
||||
if (angle1 > +M_PI) angle1 -= M_2PI;
|
||||
return angle1;
|
||||
}
|
||||
else {
|
||||
if (angle1 < -M_PI) angle1 += M_2PI;
|
||||
return angle1;
|
||||
}
|
||||
}
|
||||
|
||||
//frame, border, caption are never shown in QGIVD, so shouldn't be in bRect
|
||||
QRectF QGIViewDimension::boundingRect() const
|
||||
{
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace TechDrawGui
|
||||
class QGIArrow;
|
||||
class QGIDimLines;
|
||||
class QGIViewDimension;
|
||||
class ViewProviderDimension;
|
||||
|
||||
class QGIDatumLabel : public QGraphicsObject
|
||||
{
|
||||
@@ -154,6 +155,20 @@ public Q_SLOTS:
|
||||
void updateDim(bool obtuse = false);
|
||||
|
||||
protected:
|
||||
|
||||
static const int INNER_SECTOR = 3;
|
||||
static const int OUTER_SECTOR = 2;
|
||||
static const int OPPOSITE_SECTOR = 1;
|
||||
static const int COMPLEMENT_SECTOR = 0;
|
||||
|
||||
int classifyPointToArcPosition(double pointDistance, double pointAngle,
|
||||
double radius, double startAngle, double endAngle, bool clockwise) const;
|
||||
double computeLineAndLabelAngles(Base::Vector3d lineTarget, Base::Vector3d labelCenter,
|
||||
double lineLabelDistance, double &lineAngle, double &labelAngle) const;
|
||||
Base::Vector3d computeLineOriginPoint(Base::Vector3d lineTarget, double projectedLabelDistance,
|
||||
double lineAngle, double labelWidth, double direction) const;
|
||||
|
||||
void drawRadius(TechDraw::DrawViewDimension *dimension, ViewProviderDimension *viewProvider) const;
|
||||
void draw() override;
|
||||
virtual QVariant itemChange( GraphicsItemChange change,
|
||||
const QVariant &value ) override;
|
||||
@@ -178,6 +193,11 @@ private:
|
||||
|
||||
double getDefaultTextHorizontalOffset(bool toLeft) const;
|
||||
double getDefaultTextVerticalOffset() const;
|
||||
double getDefaultReferenceLineOverhang() const;
|
||||
|
||||
static double getStandardLinePlacement(double labelAngle);
|
||||
static bool angleWithinSector(double testAngle, double startAngle, double endAngle, bool clockwise);
|
||||
static double addAngles(double angle1, double angle2);
|
||||
};
|
||||
|
||||
} // namespace MDIViewPageGui
|
||||
|
||||
@@ -79,8 +79,9 @@ ViewProviderDimension::ViewProviderDimension()
|
||||
fcColor.setPackedValue(hGrp->GetUnsigned("Color", 0x00000000));
|
||||
ADD_PROPERTY_TYPE(Color,(fcColor),group,App::Prop_None,"The color of the Dimension");
|
||||
|
||||
ADD_PROPERTY_TYPE(FlipArrowheads ,(false),group,App::Prop_None,"Reverse the normal direction of arrowheads on dimline");
|
||||
|
||||
ADD_PROPERTY_TYPE(FlipArrowheads, (false), group, App::Prop_None,"Reverse the normal direction of arrowheads on dimline");
|
||||
ADD_PROPERTY_TYPE(TiltText, (true), group, App::Prop_None,"Rotate the text label so it is parallel with dimline");
|
||||
ADD_PROPERTY_TYPE(ExtendToCenter, (true), group, App::Prop_None,"Prolong the leader line right upto the center point");
|
||||
}
|
||||
|
||||
ViewProviderDimension::~ViewProviderDimension()
|
||||
@@ -131,7 +132,9 @@ void ViewProviderDimension::onChanged(const App::Property* p)
|
||||
if ((p == &Font) ||
|
||||
(p == &Fontsize) ||
|
||||
(p == &LineWidth) ||
|
||||
(p == &FlipArrowheads)) {
|
||||
(p == &FlipArrowheads) ||
|
||||
(p == &TiltText) ||
|
||||
(p == &ExtendToCenter)) {
|
||||
QGIView* qgiv = getQView();
|
||||
if (qgiv) {
|
||||
qgiv->updateView(true);
|
||||
|
||||
@@ -49,7 +49,8 @@ public:
|
||||
App::PropertyFloat LineWidth;
|
||||
App::PropertyColor Color;
|
||||
App::PropertyBool FlipArrowheads;
|
||||
|
||||
App::PropertyBool TiltText;
|
||||
App::PropertyBool ExtendToCenter;
|
||||
|
||||
virtual void attach(App::DocumentObject *);
|
||||
virtual void setDisplayMode(const char* ModeName);
|
||||
|
||||
Reference in New Issue
Block a user