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