3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // (C) 2010 Underground Software
8 // JLH = James L. Hammons <jlhamm@acm.org>
11 // --- ---------- -----------------------------------------------------------
12 // JLH 05/28/2010 Added this text. :-)
15 #include "rs_dimension.h"
24 RS_Dimension::RS_Dimension(RS_EntityContainer * parent, const RS_DimensionData & d):
25 RS_EntityContainer(parent), data(d)
29 /*virtual*/ RS_Dimension::~RS_Dimension()
33 /** @return Copy of data that defines the dimension. */
34 RS_DimensionData RS_Dimension::getData() const
39 Vector RS_Dimension::getNearestRef(const Vector & coord, double * dist)
41 return RS_Entity::getNearestRef(coord, dist);
44 Vector RS_Dimension::getNearestSelectedRef(const Vector & coord, double * dist)
46 return RS_Entity::getNearestSelectedRef(coord, dist);
50 * @return Dimension text. Either a text the user defined or
53 * @param resolve false: return plain value. true: return measured
54 * label if appropriate.
55 * @see getMeasuredLabel
57 QString RS_Dimension::getLabel(bool resolve)
64 // One space suppresses the text:
67 // No text prints actual measurement:
68 else if (data.text == "")
69 ret = getMeasuredLabel();
70 // Others print the text (<> is replaced by the measurement)
74 ret = ret.replace(QString("<>"), getMeasuredLabel());
81 * Sets a new text for the label.
83 void RS_Dimension::setLabel(const QString & l)
89 * Creates a dimensioning line (line with one, two or no arrows and a text).
91 * @param forceAutoText Automatically reposition the text label.
93 void RS_Dimension::updateCreateDimensionLine(const Vector & p1,
94 const Vector & p2, bool arrow1, bool arrow2, bool forceAutoText)
96 // text height (DIMTXT)
97 double dimtxt = getTextHeight();
98 // text distance to line (DIMGAP)
99 double dimgap = getDimensionLineGap();
101 // length of dimension line:
102 double distance = p1.distanceTo(p2);
104 // do we have to put the arrows outside of the line?
105 bool outsideArrows = (distance<getArrowSize()*2.5);
108 double arrowAngle1, arrowAngle2;
110 // Create dimension line:
111 RS_Line * dimensionLine = new RS_Line(this, RS_LineData(p1, p2));
112 dimensionLine->setPen(RS_Pen(RS2::FlagInvalid));
113 dimensionLine->setLayer(NULL);
114 addEntity(dimensionLine);
116 if (outsideArrows == false)
118 arrowAngle1 = dimensionLine->getAngle2();
119 arrowAngle2 = dimensionLine->getAngle1();
123 arrowAngle1 = dimensionLine->getAngle1();
124 arrowAngle2 = dimensionLine->getAngle2();
126 // extend dimension line outside arrows
128 dir.setPolar(getArrowSize() * 2, arrowAngle2);
129 dimensionLine->setStartpoint(p1 + dir);
130 dimensionLine->setEndpoint(p2 - dir);
140 arrow = new RS_Solid(this, sd);
141 arrow->shapeArrow(p1, arrowAngle1, getArrowSize());
142 arrow->setPen(RS_Pen(RS2::FlagInvalid));
143 arrow->setLayer(NULL);
150 arrow = new RS_Solid(this, sd);
151 arrow->shapeArrow(p2, arrowAngle2, getArrowSize());
152 arrow->setPen(RS_Pen(RS2::FlagInvalid));
153 arrow->setLayer(NULL);
158 RS_TextData textData;
161 double dimAngle1 = dimensionLine->getAngle1();
163 bool corrected = false;
164 textAngle = RS_Math::makeAngleReadable(dimAngle1, true, &corrected);
166 if (data.middleOfText.valid && !forceAutoText)
168 textPos = data.middleOfText;
172 textPos = dimensionLine->getMiddlepoint();
176 // rotate text so it's readable from the bottom or right (ISO)
180 distV.setPolar(dimgap + dimtxt / 2.0, dimAngle1 - M_PI / 2.0);
184 distV.setPolar(dimgap + dimtxt / 2.0, dimAngle1 + M_PI / 2.0);
187 // move text away from dimension line:
189 //// the next update should still be able to adjust this
190 //// auto text position. leave it invalid
191 data.middleOfText = textPos;
194 textData = RS_TextData(textPos, dimtxt, 30.0, RS2::VAlignMiddle, RS2::HAlignCenter,
195 RS2::LeftToRight, RS2::Exact, 1.0, getLabel(), "standard", textAngle);
197 RS_Text * text = new RS_Text(this, textData);
199 // move text to the side:
202 if (text->getUsedTextWidth() > distance)
204 distH.setPolar(text->getUsedTextWidth() / 2.0
205 + distance / 2.0 + dimgap, textAngle);
209 text->setPen(RS_Pen(RS2::FlagInvalid));
210 text->setLayer(NULL);
214 Vector RS_Dimension::getDefinitionPoint()
216 return data.definitionPoint;
219 Vector RS_Dimension::getMiddleOfText()
221 return data.middleOfText;
224 RS2::VAlign RS_Dimension::getVAlign()
229 RS2::HAlign RS_Dimension::getHAlign()
234 RS2::TextLineSpacingStyle RS_Dimension::getLineSpacingStyle()
236 return data.lineSpacingStyle;
239 double RS_Dimension::getLineSpacingFactor()
241 return data.lineSpacingFactor;
244 QString RS_Dimension::getText()
249 QString RS_Dimension::getStyle()
254 double RS_Dimension::getAngle()
260 * @return arrow size in drawing units.
262 double RS_Dimension::getArrowSize()
264 return getGraphicVariable("$DIMASZ", 2.5, 40);
268 * @return extension line overlength in drawing units.
270 double RS_Dimension::getExtensionLineExtension()
272 return getGraphicVariable("$DIMEXE", 1.25, 40);
276 * @return extension line offset from entities in drawing units.
278 double RS_Dimension::getExtensionLineOffset()
280 return getGraphicVariable("$DIMEXO", 0.625, 40);
284 * @return extension line gap to text in drawing units.
286 double RS_Dimension::getDimensionLineGap()
288 return getGraphicVariable("$DIMGAP", 0.625, 40);
292 * @return Dimension lables text height.
294 double RS_Dimension::getTextHeight()
296 return getGraphicVariable("$DIMTXT", 2.5, 40);
300 * @return the given graphic variable or the default value given in mm
301 * converted to the graphic unit.
302 * If the variable is not found it is added with the given default
303 * value converted to the local unit.
305 double RS_Dimension::getGraphicVariable(const QString & key, double defMM, int code)
307 double v = getGraphicVariableDouble(key, RS_MINDOUBLE);
309 if (v <= RS_MINDOUBLE)
311 addGraphicVariable(key, RS_Units::convert(defMM, RS2::Millimeter, getGraphicUnit()),
313 v = getGraphicVariableDouble(key, 1.0);
319 /*virtual*/ double RS_Dimension::getLength()
324 void RS_Dimension::move(Vector offset)
326 data.definitionPoint.move(offset);
327 data.middleOfText.move(offset);
330 void RS_Dimension::rotate(Vector center, double angle)
332 data.definitionPoint.rotate(center, angle);
333 data.middleOfText.rotate(center, angle);
334 data.angle = RS_Math::correctAngle(data.angle+angle);
337 void RS_Dimension::scale(Vector center, Vector factor)
339 data.definitionPoint.scale(center, factor);
340 data.middleOfText.scale(center, factor);
343 void RS_Dimension::mirror(Vector axisPoint1, Vector axisPoint2)
345 data.definitionPoint.mirror(axisPoint1, axisPoint2);
346 data.middleOfText.mirror(axisPoint1, axisPoint2);