]> Shamusworld >> Repos - architektonas/blob - src/base/rs_dimlinear.cpp
Initial import
[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 "rs_graphic.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         RS_Graphic* graphic = getGraphic();
95
96         QString ret;
97         if (graphic!=NULL)
98         {
99                 ret = RS_Units::formatLinear(dist, graphic->getUnit(),
100                         graphic->getLinearFormat(), graphic->getLinearPrecision());
101         }
102         else
103         {
104                 ret = QString("%1").arg(dist);
105         }
106
107         return ret;
108 }
109
110 bool RS_DimLinear::hasEndpointsWithinWindow(Vector v1, Vector v2)
111 {
112         return (edata.extensionPoint1.isInWindow(v1, v2)
113                 || edata.extensionPoint2.isInWindow(v1, v2));
114 }
115
116 /**
117  * Updates the sub entities of this dimension. Called when the
118  * text or the position, alignment, .. changes.
119  *
120  * @param autoText Automatically reposition the text label
121  */
122 void RS_DimLinear::update(bool autoText)
123 {
124         RS_DEBUG->print("RS_DimLinear::update");
125
126         clear();
127
128         if (isUndone())
129                 return;
130
131         // distance from entities (DIMEXO)
132         double dimexo = getExtensionLineOffset();
133         // extension line extension (DIMEXE)
134         double dimexe = getExtensionLineExtension();
135
136         RS_LineData ld;
137         double extAngle = edata.angle + (M_PI/2.0);
138
139         // direction of dimension line
140         Vector dirDim;
141         dirDim.setPolar(100.0, edata.angle);
142         // direction of extension lines
143         Vector dirExt;
144         dirExt.setPolar(100.0, extAngle);
145
146         // construction line for dimension line
147         RS_ConstructionLine dimLine(NULL, RS_ConstructionLineData(data.definitionPoint,
148                 data.definitionPoint + dirDim));
149
150         Vector dimP1 = dimLine.getNearestPointOnEntity(edata.extensionPoint1);
151         Vector dimP2 = dimLine.getNearestPointOnEntity(edata.extensionPoint2);
152
153         // Definitive dimension line:
154         updateCreateDimensionLine(dimP1, dimP2, true, true, autoText);
155         /*
156         ld = RS_LineData(data.definitionPoint, dimP1);
157         RS_Line* dimensionLine = new RS_Line(this, ld);
158                 addEntity(dimensionLine);
159         */
160         Vector vDimexo1, vDimexe1, vDimexo2, vDimexe2;
161         vDimexe1.setPolar(dimexe, edata.extensionPoint1.angleTo(dimP1));
162         vDimexo1.setPolar(dimexo, edata.extensionPoint1.angleTo(dimP1));
163
164         vDimexe2.setPolar(dimexe, edata.extensionPoint2.angleTo(dimP2));
165         vDimexo2.setPolar(dimexo, edata.extensionPoint2.angleTo(dimP2));
166
167         if ((edata.extensionPoint1 - dimP1).magnitude() < 1e-6)
168         {
169                 vDimexe1.setPolar(dimexe, data.definitionPoint.angleTo(dimP1) - M_PI / 2.0);
170                 vDimexo1.setPolar(dimexo, data.definitionPoint.angleTo(dimP1) - M_PI / 2.0);
171         }
172
173         if ((edata.extensionPoint2 - dimP2).magnitude() < 1e-6)
174         {
175                 vDimexe2.setPolar(dimexe, data.definitionPoint.angleTo(dimP2) - M_PI / 2.0);
176                 vDimexo2.setPolar(dimexo, data.definitionPoint.angleTo(dimP2) - M_PI / 2.0);
177         }
178
179         // extension lines:
180         ld = RS_LineData(edata.extensionPoint1 + vDimexo1, dimP1 + vDimexe1);
181         RS_Line * line = new RS_Line(this, ld);
182         line->setPen(RS_Pen(RS2::FlagInvalid));
183         line->setLayer(NULL);
184         addEntity(line);
185
186         ld = RS_LineData(edata.extensionPoint2 + vDimexo2, dimP2 + vDimexe2);
187         //data.definitionPoint+vDimexe2);
188         line = new RS_Line(this, ld);
189         line->setPen(RS_Pen(RS2::FlagInvalid));
190         line->setLayer(NULL);
191         addEntity(line);
192
193         calculateBorders();
194 }
195
196 Vector RS_DimLinear::getExtensionPoint1()
197 {
198         return edata.extensionPoint1;
199 }
200
201 Vector RS_DimLinear::getExtensionPoint2()
202 {
203         return edata.extensionPoint2;
204 }
205
206 double RS_DimLinear::getAngle()
207 {
208         return edata.angle;
209 }
210
211 void RS_DimLinear::setAngle(double a)
212 {
213         edata.angle = RS_Math::correctAngle(a);
214 }
215
216 double RS_DimLinear::getOblique()
217 {
218         return edata.oblique;
219 }
220
221 void RS_DimLinear::move(Vector offset)
222 {
223         RS_Dimension::move(offset);
224
225         edata.extensionPoint1.move(offset);
226         edata.extensionPoint2.move(offset);
227         update();
228 }
229
230 void RS_DimLinear::rotate(Vector center, double angle)
231 {
232         RS_Dimension::rotate(center, angle);
233
234         edata.extensionPoint1.rotate(center, angle);
235         edata.extensionPoint2.rotate(center, angle);
236         edata.angle = RS_Math::correctAngle(edata.angle+angle);
237         update();
238 }
239
240 void RS_DimLinear::scale(Vector center, Vector factor)
241 {
242         RS_Dimension::scale(center, factor);
243
244         edata.extensionPoint1.scale(center, factor);
245         edata.extensionPoint2.scale(center, factor);
246         update();
247 }
248
249 void RS_DimLinear::mirror(Vector axisPoint1, Vector axisPoint2)
250 {
251         RS_Dimension::mirror(axisPoint1, axisPoint2);
252
253         edata.extensionPoint1.mirror(axisPoint1, axisPoint2);
254         edata.extensionPoint2.mirror(axisPoint1, axisPoint2);
255
256         Vector vec;
257         vec.setPolar(1.0, edata.angle);
258         vec.mirror(Vector(0.0, 0.0), axisPoint2 - axisPoint1);
259         edata.angle = vec.angle();
260
261         update();
262 }
263
264 void RS_DimLinear::stretch(Vector firstCorner, Vector secondCorner, Vector offset)
265 {
266         //e->calculateBorders();
267         if (getMin().isInWindow(firstCorner, secondCorner)
268                 && getMax().isInWindow(firstCorner, secondCorner))
269         {
270                 move(offset);
271         }
272         else
273         {
274                 //Vector v = data.definitionPoint - edata.extensionPoint2;
275                 //double len = edata.extensionPoint2.distanceTo(data.definitionPoint);
276                 //double ang1 = edata.extensionPoint1.angleTo(edata.extensionPoint2)
277                 //              + M_PI/2;
278
279                 if (edata.extensionPoint1.isInWindow(firstCorner, secondCorner))
280                         edata.extensionPoint1.move(offset);
281
282                 if (edata.extensionPoint2.isInWindow(firstCorner, secondCorner))
283                         edata.extensionPoint2.move(offset);
284
285                 /*
286                 double ang2 = edata.extensionPoint1.angleTo(edata.extensionPoint2)
287                                                 + M_PI/2;
288
289                 double diff = RS_Math::getAngleDifference(ang1, ang2);
290                 if (diff>M_PI) {
291                         diff-=2*M_PI;
292                 }
293
294                 if (fabs(diff)>M_PI/2) {
295                         ang2 = RS_Math::correctAngle(ang2+M_PI);
296                 }
297
298                 Vector v;
299                 v.setPolar(len, ang2);
300                 data.definitionPoint = edata.extensionPoint2 + v;
301                 */
302         }
303
304         update(true);
305 }
306
307 void RS_DimLinear::moveRef(const Vector & ref, const Vector & offset)
308 {
309         if (ref.distanceTo(data.definitionPoint) < 1.0e-4)
310         {
311                 data.definitionPoint += offset;
312                 update(true);
313         }
314         else if (ref.distanceTo(data.middleOfText) < 1.0e-4)
315         {
316                 data.middleOfText += offset;
317                 update(false);
318         }
319         else if (ref.distanceTo(edata.extensionPoint1) < 1.0e-4)
320         {
321                 edata.extensionPoint1 += offset;
322                 update(true);
323         }
324         else if (ref.distanceTo(edata.extensionPoint2) < 1.0e-4)
325         {
326                 edata.extensionPoint2 += offset;
327                 update(true);
328         }
329 }
330
331 /**
332  * Dumps the point's data to stdout.
333  */
334 std::ostream & operator<<(std::ostream & os, const RS_DimLinear & d)
335 {
336     os << " DimLinear: " << d.getData() << "\n" << d.getEData() << "\n";
337     return os;
338 }