]> Shamusworld >> Repos - architektonas/blob - src/base/rs_dimaligned.cpp
Changed RS_Graphic to Drawing; this is less confusing as a drawing is
[architektonas] / src / base / rs_dimaligned.cpp
1 // rs_dimaligned.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_dimaligned.h"
16
17 #include "drawing.h"
18 #include "rs_units.h"
19 #include "rs_constructionline.h"
20
21 /**
22  * Constructor.
23  *
24  * @para parent Parent Entity Container.
25  * @para d Common dimension geometrical data.
26  * @para ed Extended geometrical data for aligned dimension.
27  */
28 RS_DimAligned::RS_DimAligned(RS_EntityContainer * parent, const RS_DimensionData & d,
29         const RS_DimAlignedData & ed): RS_Dimension(parent, d), edata(ed)
30 {
31     calculateBorders();
32 }
33
34 /*virtual*/ RS_DimAligned::~RS_DimAligned()
35 {
36 }
37
38 /*virtual*/ RS_Entity * RS_DimAligned::clone()
39 {
40         RS_DimAligned * d = new RS_DimAligned(*this);
41 #warning "!!! Need to port setAutoDelete in QList/QMultiHash from Qt3 to Qt4 !!!"
42 //      d->entities.setAutoDelete(entities.autoDelete());
43         d->initId();
44         d->detach();
45         return d;
46 }
47
48 /**     @return RS2::EntityDimAligned */
49 /*virtual*/ RS2::EntityType RS_DimAligned::rtti() const
50 {
51         return RS2::EntityDimAligned;
52 }
53
54 /**
55  * @return Copy of data that defines the aligned dimension.
56  * @see getData()
57  */
58 RS_DimAlignedData RS_DimAligned::getEData() const
59 {
60         return edata;
61 }
62
63 /**
64  * Sets a new text. The entities representing the
65  * text are updated.
66  */
67 //void RS_DimAligned::setText(const QString& t) {
68 //    data.text = t;
69 //    update();
70 //}
71
72 VectorSolutions RS_DimAligned::getRefPoints()
73 {
74         VectorSolutions ret(edata.extensionPoint1, edata.extensionPoint2,
75                 data.definitionPoint, data.middleOfText);
76         return ret;
77 }
78
79 /**
80  * @return Automatically creted label for the default
81  * measurement of this dimension.
82  */
83 QString RS_DimAligned::getMeasuredLabel()
84 {
85         double dist = edata.extensionPoint1.distanceTo(edata.extensionPoint2);
86         Drawing * graphic = getGraphic();
87         QString ret;
88
89         if (graphic != NULL)
90         {
91                 ret = RS_Units::formatLinear(dist, graphic->getUnit(),
92                         graphic->getLinearFormat(), graphic->getLinearPrecision());
93         }
94         else
95         {
96                 ret = QString("%1").arg(dist);
97         }
98
99         return ret;
100 }
101
102 /**
103  * Updates the sub entities of this dimension. Called when the
104  * text or the position, alignment, .. changes.
105  *
106  * @param autoText Automatically reposition the text label
107  */
108 void RS_DimAligned::update(bool autoText)
109 {
110         RS_DEBUG->print("RS_DimAligned::update");
111
112         clear();
113
114         if (isUndone())
115                 return;
116
117         // distance from entities (DIMEXO)
118         double dimexo = getExtensionLineOffset();
119         // definition line definition (DIMEXE)
120         double dimexe = getExtensionLineExtension();
121         // text height (DIMTXT)
122         //double dimtxt = getTextHeight();
123         // text distance to line (DIMGAP)
124         //double dimgap = getDimensionLineGap();
125
126         // Angle from extension endpoints towards dimension line
127         double extAngle = edata.extensionPoint2.angleTo(data.definitionPoint);
128         // extension lines length
129         double extLength = edata.extensionPoint2.distanceTo(data.definitionPoint);
130
131         Vector v1, v2, e1;
132         RS_LineData ld;
133         RS_Line * line;
134
135         v1.setPolar(dimexo, extAngle);
136         v2.setPolar(dimexe, extAngle);
137         e1.setPolar(1.0, extAngle);
138
139         // Extension line 1:
140         ld = RS_LineData(edata.extensionPoint1 + v1, edata.extensionPoint1 + e1 * extLength + v2);
141         line = new RS_Line(this, ld);
142         //line->setLayerToActive();
143         //line->setPenToActive();
144         line->setPen(RS_Pen(RS2::FlagInvalid));
145         line->setLayer(NULL);
146         addEntity(line);
147
148         // Extension line 2:
149         ld = RS_LineData(edata.extensionPoint2 + v1, edata.extensionPoint2 + e1 * extLength + v2);
150         line = new RS_Line(this, ld);
151         //line->setLayerToActive();
152         //line->setPenToActive();
153         line->setPen(RS_Pen(RS2::FlagInvalid));
154         line->setLayer(NULL);
155         addEntity(line);
156
157         // Dimension line:
158         updateCreateDimensionLine(edata.extensionPoint1 + e1 * extLength,
159                 edata.extensionPoint2 + e1 * extLength, true, true, autoText);
160
161         calculateBorders();
162 }
163
164 Vector RS_DimAligned::getExtensionPoint1()
165 {
166         return edata.extensionPoint1;
167 }
168
169 Vector RS_DimAligned::getExtensionPoint2()
170 {
171         return edata.extensionPoint2;
172 }
173
174 bool RS_DimAligned::hasEndpointsWithinWindow(Vector v1, Vector v2)
175 {
176         return (edata.extensionPoint1.isInWindow(v1, v2)
177                 || edata.extensionPoint2.isInWindow(v1, v2));
178 }
179
180 void RS_DimAligned::move(Vector offset)
181 {
182         RS_Dimension::move(offset);
183
184         edata.extensionPoint1.move(offset);
185         edata.extensionPoint2.move(offset);
186         update();
187 }
188
189 void RS_DimAligned::rotate(Vector center, double angle)
190 {
191         RS_Dimension::rotate(center, angle);
192
193         edata.extensionPoint1.rotate(center, angle);
194         edata.extensionPoint2.rotate(center, angle);
195         update();
196 }
197
198 void RS_DimAligned::scale(Vector center, Vector factor)
199 {
200         RS_Dimension::scale(center, factor);
201
202         edata.extensionPoint1.scale(center, factor);
203         edata.extensionPoint2.scale(center, factor);
204         update();
205 }
206
207 void RS_DimAligned::mirror(Vector axisPoint1, Vector axisPoint2)
208 {
209         RS_Dimension::mirror(axisPoint1, axisPoint2);
210
211         edata.extensionPoint1.mirror(axisPoint1, axisPoint2);
212         edata.extensionPoint2.mirror(axisPoint1, axisPoint2);
213         update();
214 }
215
216 void RS_DimAligned::stretch(Vector firstCorner, Vector secondCorner, Vector offset)
217 {
218         //e->calculateBorders();
219         if (getMin().isInWindow(firstCorner, secondCorner) && getMax().isInWindow(firstCorner, secondCorner))
220         {
221                 move(offset);
222         }
223         else
224         {
225                 //Vector v = data.definitionPoint - edata.extensionPoint2;
226                 double len = edata.extensionPoint2.distanceTo(data.definitionPoint);
227                 double ang1 = edata.extensionPoint1.angleTo(edata.extensionPoint2) + M_PI / 2;
228
229                 if (edata.extensionPoint1.isInWindow(firstCorner, secondCorner))
230                 {
231                         edata.extensionPoint1.move(offset);
232                 }
233
234                 if (edata.extensionPoint2.isInWindow(firstCorner, secondCorner))
235                 {
236                         edata.extensionPoint2.move(offset);
237                 }
238
239                 double ang2 = edata.extensionPoint1.angleTo(edata.extensionPoint2) + M_PI / 2;
240
241                 double diff = RS_Math::getAngleDifference(ang1, ang2);
242
243                 if (diff > M_PI)
244                 {
245                         diff -= 2 * M_PI;
246                 }
247
248                 if (fabs(diff) > M_PI / 2)
249                 {
250                         ang2 = RS_Math::correctAngle(ang2 + M_PI);
251                 }
252
253                 Vector v;
254                 v.setPolar(len, ang2);
255                 data.definitionPoint = edata.extensionPoint2 + v;
256         }
257
258         update(true);
259 }
260
261 void RS_DimAligned::moveRef(const Vector & ref, const Vector & offset)
262 {
263         if (ref.distanceTo(data.definitionPoint) < 1.0e-4)
264         {
265                 RS_ConstructionLine l(NULL, RS_ConstructionLineData(edata.extensionPoint1,
266                         edata.extensionPoint2));
267                 double d = l.getDistanceToPoint(data.definitionPoint + offset);
268                 double a = edata.extensionPoint2.angleTo(data.definitionPoint);
269                 double ad = RS_Math::getAngleDifference(a,
270                         edata.extensionPoint2.angleTo(data.definitionPoint + offset));
271
272                 if (fabs(ad) > M_PI / 2.0 && fabs(ad) < 3.0 / 2.0 * M_PI)
273                 {
274                         a = RS_Math::correctAngle(a + M_PI);
275                 }
276
277                 Vector v;
278                 v.setPolar(d, a);
279         data.definitionPoint = edata.extensionPoint2 + v;
280                 update(true);
281     }
282         else if (ref.distanceTo(data.middleOfText) < 1.0e-4)
283         {
284         data.middleOfText.move(offset);
285                 update(false);
286     }
287         else if (ref.distanceTo(edata.extensionPoint1) < 1.0e-4)
288         {
289                 double a1 = edata.extensionPoint2.angleTo(edata.extensionPoint1);
290                 double a2 = edata.extensionPoint2.angleTo(edata.extensionPoint1+offset);
291                 double d1 = edata.extensionPoint2.distanceTo(edata.extensionPoint1);
292                 double d2 = edata.extensionPoint2.distanceTo(edata.extensionPoint1+offset);
293                 rotate(edata.extensionPoint2, a2-a1);
294
295                 if (fabs(d1) > 1.0e-4)
296                 {
297                         scale(edata.extensionPoint2, Vector(d2 / d1, d2 / d1));
298                 }
299
300                 update(true);
301     }
302         else if (ref.distanceTo(edata.extensionPoint2) < 1.0e-4)
303         {
304                 double a1 = edata.extensionPoint1.angleTo(edata.extensionPoint2);
305                 double a2 = edata.extensionPoint1.angleTo(edata.extensionPoint2 + offset);
306                 double d1 = edata.extensionPoint1.distanceTo(edata.extensionPoint2);
307                 double d2 = edata.extensionPoint1.distanceTo(edata.extensionPoint2 + offset);
308                 rotate(edata.extensionPoint1, a2 - a1);
309
310                 if (fabs(d1) > 1.0e-4)
311                 {
312                         scale(edata.extensionPoint1, Vector(d2/d1, d2/d1));
313                 }
314
315                 update(true);
316     }
317 }
318
319 /**
320  * Dumps the point's data to stdout.
321  */
322 std::ostream & operator<<(std::ostream & os, const RS_DimAligned & d)
323 {
324     os << " DimAligned: " << d.getData() << "\n" << d.getEData() << "\n";
325     return os;
326 }