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