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