]> Shamusworld >> Repos - architektonas/blob - src/base/rs_dimension.cpp
Fixed problem with dimensions not showing up.
[architektonas] / src / base / rs_dimension.cpp
1 // rs_dimension.cpp
2 //
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
7 //
8 // JLH = James L. Hammons <jlhamm@acm.org>
9 //
10 // Who  When        What
11 // ---  ----------  -----------------------------------------------------------
12 // JLH  05/28/2010  Added this text. :-)
13 //
14
15 #include "rs_dimension.h"
16
17 #include "rs_solid.h"
18 #include "rs_text.h"
19 #include "rs_units.h"
20
21 /**
22  * Constructor.
23  */
24 RS_Dimension::RS_Dimension(RS_EntityContainer * parent, const RS_DimensionData & d):
25         RS_EntityContainer(parent), data(d)
26 {
27 }
28
29 /*virtual*/ RS_Dimension::~RS_Dimension()
30 {
31 }
32
33 /** @return Copy of data that defines the dimension. */
34 RS_DimensionData RS_Dimension::getData() const
35 {
36         return data;
37 }
38
39 Vector RS_Dimension::getNearestRef(const Vector & coord, double * dist)
40 {
41         return RS_Entity::getNearestRef(coord, dist);
42 }
43
44 Vector RS_Dimension::getNearestSelectedRef(const Vector & coord, double * dist)
45 {
46         return RS_Entity::getNearestSelectedRef(coord, dist);
47 }
48
49 /**
50  * @return Dimension text. Either a text the user defined or
51  *         the measured text.
52  *
53  * @param resolve false: return plain value. true: return measured
54  *      label if appropriate.
55  * @see getMeasuredLabel
56  */
57 QString RS_Dimension::getLabel(bool resolve)
58 {
59         if (!resolve)
60                 return data.text;
61
62         QString ret = "";
63
64         // One space suppresses the text:
65         if (data.text == " ")
66                 ret = "";
67         // No text prints actual measurement:
68         else if (data.text == "")
69                 ret = getMeasuredLabel();
70         // Others print the text (<> is replaced by the measurement)
71         else
72         {
73                 ret = data.text;
74                 ret = ret.replace(QString("<>"), getMeasuredLabel());
75         }
76
77         return ret;
78 }
79
80 /**
81  * Sets a new text for the label.
82  */
83 void RS_Dimension::setLabel(const QString & l)
84 {
85         data.text = l;
86 }
87
88 /**
89  * Creates a dimensioning line (line with one, two or no arrows and a text).
90  *
91  * @param forceAutoText Automatically reposition the text label.
92  */
93 void RS_Dimension::updateCreateDimensionLine(const Vector & p1,
94         const Vector & p2, bool arrow1, bool arrow2, bool forceAutoText)
95 {
96 #if 0
97 printf("RS_Dimension::updateCreateDimensionLine()...\n");
98 #endif
99         // text height (DIMTXT)
100         double dimtxt = getTextHeight();
101         // text distance to line (DIMGAP)
102         double dimgap = getDimensionLineGap();
103         // length of dimension line:
104         double distance = p1.distanceTo(p2);
105         // do we have to put the arrows outside of the line?
106         bool outsideArrows = (distance < getArrowSize() * 2.5);
107         // arrow angles:
108         double arrowAngle1, arrowAngle2;
109
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);
115
116         if (!outsideArrows)
117         {
118                 arrowAngle1 = dimensionLine->getAngle2();
119                 arrowAngle2 = dimensionLine->getAngle1();
120         }
121         else
122         {
123                 arrowAngle1 = dimensionLine->getAngle1();
124                 arrowAngle2 = dimensionLine->getAngle2();
125
126                 // extend dimension line outside arrows
127                 Vector dir;
128                 dir.setPolar(getArrowSize() * 2, arrowAngle2);
129                 dimensionLine->setStartpoint(p1 + dir);
130                 dimensionLine->setEndpoint(p2 - dir);
131         }
132
133         // Arrows:
134         RS_SolidData sd;
135         RS_Solid * arrow;
136
137         if (arrow1)
138         {
139                 // arrow 1
140                 arrow = new RS_Solid(this, sd);
141                 arrow->shapeArrow(p1, arrowAngle1, getArrowSize());
142                 arrow->setPen(RS_Pen(RS2::FlagInvalid));
143                 arrow->setLayer(NULL);
144                 addEntity(arrow);
145         }
146
147         if (arrow2)
148         {
149                 // arrow 2:
150                 arrow = new RS_Solid(this, sd);
151                 arrow->shapeArrow(p2, arrowAngle2, getArrowSize());
152                 arrow->setPen(RS_Pen(RS2::FlagInvalid));
153                 arrow->setLayer(NULL);
154                 addEntity(arrow);
155         }
156
157         // Text label:
158         RS_TextData textData;
159         Vector textPos;
160
161         double dimAngle1 = dimensionLine->getAngle1();
162         double textAngle;
163         bool corrected = false;
164         textAngle = RS_Math::makeAngleReadable(dimAngle1, true, &corrected);
165
166         if (data.middleOfText.valid && !forceAutoText)
167         {
168                 textPos = data.middleOfText;
169         }
170         else
171         {
172                 textPos = dimensionLine->getMiddlepoint();
173                 Vector distV;
174
175                 // rotate text so it's readable from the bottom or right (ISO)
176                 // quadrant 1 & 4
177                 if (corrected)
178                         distV.setPolar(dimgap + dimtxt / 2.0, dimAngle1 - M_PI / 2.0);
179                 else
180                         distV.setPolar(dimgap + dimtxt / 2.0, dimAngle1 + M_PI / 2.0);
181
182                 // move text away from dimension line:
183                 textPos += distV;
184                 //// the next update should still be able to adjust this
185                 ////   auto text position. leave it invalid
186                 data.middleOfText = textPos;
187         }
188
189         textData = RS_TextData(textPos, dimtxt, 30.0, RS2::VAlignMiddle, RS2::HAlignCenter,
190                 RS2::LeftToRight, RS2::Exact, 1.0, getLabel(), "standard", textAngle);
191 #if 0
192 printf("--> %s\n", getLabel().toAscii().data());
193 #endif
194
195         RS_Text * text = new RS_Text(this, textData);
196
197         // move text to the side:
198         Vector distH;
199
200         if (text->getUsedTextWidth() > distance)
201         {
202                 distH.setPolar(text->getUsedTextWidth() / 2.0 + distance / 2.0 + dimgap, textAngle);
203                 text->move(distH);
204         }
205
206         text->setPen(RS_Pen(RS2::FlagInvalid));
207         text->setLayer(NULL);
208         addEntity(text);
209 }
210
211 Vector RS_Dimension::getDefinitionPoint()
212 {
213         return data.definitionPoint;
214 }
215
216 Vector RS_Dimension::getMiddleOfText()
217 {
218         return data.middleOfText;
219 }
220
221 RS2::VAlign RS_Dimension::getVAlign()
222 {
223         return data.valign;
224 }
225
226 RS2::HAlign RS_Dimension::getHAlign()
227 {
228         return data.halign;
229 }
230
231 RS2::TextLineSpacingStyle RS_Dimension::getLineSpacingStyle()
232 {
233         return data.lineSpacingStyle;
234 }
235
236 double RS_Dimension::getLineSpacingFactor()
237 {
238         return data.lineSpacingFactor;
239 }
240
241 QString RS_Dimension::getText()
242 {
243         return data.text;
244 }
245
246 QString RS_Dimension::getStyle()
247 {
248         return data.style;
249 }
250
251 double RS_Dimension::getAngle()
252 {
253         return data.angle;
254 }
255
256 /**
257  * @return arrow size in drawing units.
258  */
259 double RS_Dimension::getArrowSize()
260 {
261         return getGraphicVariable("$DIMASZ", 2.5, 40);
262 }
263
264 /**
265  * @return extension line overlength in drawing units.
266  */
267 double RS_Dimension::getExtensionLineExtension()
268 {
269         return getGraphicVariable("$DIMEXE", 1.25, 40);
270 }
271
272 /**
273  * @return extension line offset from entities in drawing units.
274  */
275 double RS_Dimension::getExtensionLineOffset()
276 {
277         return getGraphicVariable("$DIMEXO", 0.625, 40);
278 }
279
280 /**
281  * @return extension line gap to text in drawing units.
282  */
283 double RS_Dimension::getDimensionLineGap()
284 {
285         return getGraphicVariable("$DIMGAP", 0.625, 40);
286 }
287
288 /**
289  * @return Dimension lables text height.
290  */
291 double RS_Dimension::getTextHeight()
292 {
293         return getGraphicVariable("$DIMTXT", 2.5, 40);
294 }
295
296 /**
297  * @return the given graphic variable or the default value given in mm
298  * converted to the graphic unit.
299  * If the variable is not found it is added with the given default
300  * value converted to the local unit.
301  */
302 double RS_Dimension::getGraphicVariable(const QString & key, double defMM, int code)
303 {
304         double v = getGraphicVariableDouble(key, RS_MINDOUBLE);
305
306         if (v <= RS_MINDOUBLE)
307         {
308                 addGraphicVariable(key, RS_Units::convert(defMM, RS2::Millimeter, getGraphicUnit()),
309                         code);
310                 v = getGraphicVariableDouble(key, 1.0);
311         }
312
313         return v;
314 }
315
316 /*virtual*/ double RS_Dimension::getLength()
317 {
318         return -1.0;
319 }
320
321 void RS_Dimension::move(Vector offset)
322 {
323         data.definitionPoint.move(offset);
324         data.middleOfText.move(offset);
325 }
326
327 void RS_Dimension::rotate(Vector center, double angle)
328 {
329         data.definitionPoint.rotate(center, angle);
330         data.middleOfText.rotate(center, angle);
331         data.angle = RS_Math::correctAngle(data.angle+angle);
332 }
333
334 void RS_Dimension::scale(Vector center, Vector factor)
335 {
336         data.definitionPoint.scale(center, factor);
337         data.middleOfText.scale(center, factor);
338 }
339
340 void RS_Dimension::mirror(Vector axisPoint1, Vector axisPoint2)
341 {
342         data.definitionPoint.mirror(axisPoint1, axisPoint2);
343         data.middleOfText.mirror(axisPoint1, axisPoint2);
344 }