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