]> Shamusworld >> Repos - architektonas/blob - src/base/rs_dimradial.cpp
3ac579bfb1204e94d13aa05ab78194669ca576ec
[architektonas] / src / base / rs_dimradial.cpp
1 // rs_dimradial.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_dimradial.h"
16
17 #include "rs_graphic.h"
18 #include "rs_solid.h"
19 #include "rs_text.h"
20 #include "rs_units.h"
21
22 /**
23  * Constructor.
24  *
25  * @para parent Parent Entity Container.
26  * @para d Common dimension geometrical data.
27  * @para ed Extended geometrical data for radial dimension.
28  */
29 RS_DimRadial::RS_DimRadial(RS_EntityContainer * parent, const RS_DimensionData & d,
30         const RS_DimRadialData & ed): RS_Dimension(parent, d), edata(ed)
31 {
32 }
33
34 /*virtual*/ RS_DimRadial::~RS_DimRadial()
35 {
36 }
37
38 /*virtual*/ RS_Entity * RS_DimRadial::clone()
39 {
40         RS_DimRadial * d = new RS_DimRadial(*this);
41 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
42 //      d->entities.setAutoDelete(entities.autoDelete());
43         d->initId();
44         d->detach();
45         return d;
46 }
47
48 /**     @return RS2::EntityDimRadial */
49 /*virtual*/ RS2::EntityType RS_DimRadial::rtti() const
50 {
51         return RS2::EntityDimRadial;
52 }
53
54 /**
55  * @return Copy of data that defines the radial dimension.
56  * @see getData()
57  */
58 RS_DimRadialData RS_DimRadial::getEData() const
59 {
60         return edata;
61 }
62
63 /**
64  * @return Automatically created label for the default
65  * measurement of this dimension.
66  */
67 QString RS_DimRadial::getMeasuredLabel()
68 {
69     // Definitive dimension line:
70     double dist = data.definitionPoint.distanceTo(edata.definitionPoint);
71
72     RS_Graphic* graphic = getGraphic();
73
74     QString ret;
75     if (graphic!=NULL) {
76         ret = RS_Units::formatLinear(dist, graphic->getUnit(),
77                                      graphic->getLinearFormat(), graphic->getLinearPrecision());
78     } else {
79         ret = QString("%1").arg(dist);
80     }
81
82     return ret;
83 }
84
85
86 VectorSolutions RS_DimRadial::getRefPoints() {
87         VectorSolutions ret(edata.definitionPoint,
88                                                 data.definitionPoint, data.middleOfText);
89         return ret;
90 }
91
92 /**
93  * Updates the sub entities of this dimension. Called when the
94  * dimension or the position, alignment, .. changes.
95  *
96  * @param autoText Automatically reposition the text label
97  */
98 void RS_DimRadial::update(bool autoText)
99 {
100     RS_DEBUG->print("RS_DimRadial::update");
101
102     clear();
103
104     if (isUndone()) {
105         return;
106     }
107
108     // dimension line:
109     //updateCreateDimensionLine(data.definitionPoint, edata.definitionPoint,
110     //false, true);
111
112     Vector p1 = data.definitionPoint;
113     Vector p2 = edata.definitionPoint;
114     double angle = p1.angleTo(p2);
115
116     // text height (DIMTXT)
117     double dimtxt = getTextHeight();
118     // text distance to line (DIMGAP)
119     double dimgap = getDimensionLineGap();
120
121     // length of dimension line:
122     double length = p1.distanceTo(p2);
123
124     RS_TextData textData;
125
126     textData = RS_TextData(Vector(0.0,0.0),
127                            dimtxt, 30.0,
128                            RS2::VAlignMiddle,
129                            RS2::HAlignCenter,
130                            RS2::LeftToRight,
131                            RS2::Exact,
132                            1.0,
133                            getLabel(),
134                            "standard",
135                            0.0);
136
137     RS_Text* text = new RS_Text(this, textData);
138     double textWidth = text->getSize().x;
139
140     // do we have to put the arrow / text outside of the arc?
141     bool outsideArrow = (length<getArrowSize()*2+textWidth);
142     double arrowAngle;
143
144     if (outsideArrow) {
145         length += getArrowSize()*2 + textWidth;
146         arrowAngle = angle+M_PI;
147     } else {
148         arrowAngle = angle;
149     }
150
151     // create arrow:
152     RS_SolidData sd;
153     RS_Solid* arrow;
154
155     arrow = new RS_Solid(this, sd);
156     arrow->shapeArrow(p2,
157                       arrowAngle,
158                       getArrowSize());
159     arrow->setPen(RS_Pen(RS2::FlagInvalid));
160     arrow->setLayer(NULL);
161     addEntity(arrow);
162
163     Vector p3;
164     p3.setPolar(length, angle);
165     p3 += p1;
166
167     // Create dimension line:
168     RS_Line* dimensionLine = new RS_Line(this, RS_LineData(p1, p3));
169     dimensionLine->setPen(RS_Pen(RS2::FlagInvalid));
170     dimensionLine->setLayer(NULL);
171     addEntity(dimensionLine);
172
173     Vector distV;
174     double textAngle;
175
176     // rotate text so it's readable from the bottom or right (ISO)
177     // quadrant 1 & 4
178     if (angle>M_PI/2.0*3.0+0.001 ||
179             angle<M_PI/2.0+0.001) {
180
181         distV.setPolar(dimgap + dimtxt/2.0, angle+M_PI/2.0);
182         textAngle = angle;
183     }
184     // quadrant 2 & 3
185     else {
186         distV.setPolar(dimgap + dimtxt/2.0, angle-M_PI/2.0);
187         textAngle = angle+M_PI;
188     }
189
190     // move text label:
191     Vector textPos;
192
193     if (data.middleOfText.valid && !autoText) {
194         textPos = data.middleOfText;
195     } else {
196         if (outsideArrow) {
197             textPos.setPolar(length-textWidth/2.0-getArrowSize(), angle);
198         } else {
199             textPos.setPolar(length/2.0, angle);
200         }
201         textPos+=p1;
202         // move text away from dimension line:
203         textPos += distV;
204         data.middleOfText = textPos;
205     }
206
207     text->rotate(Vector(0.0,0.0), textAngle);
208     text->move(textPos);
209
210     text->setPen(RS_Pen(RS2::FlagInvalid));
211     text->setLayer(NULL);
212     addEntity(text);
213
214     calculateBorders();
215 }
216
217 Vector RS_DimRadial::getDefinitionPoint()
218 {
219         return edata.definitionPoint;
220 }
221
222 double RS_DimRadial::getLeader()
223 {
224         return edata.leader;
225 }
226
227 void RS_DimRadial::move(Vector offset)
228 {
229     RS_Dimension::move(offset);
230
231     edata.definitionPoint.move(offset);
232     update();
233 }
234
235 void RS_DimRadial::rotate(Vector center, double angle)
236 {
237     RS_Dimension::rotate(center, angle);
238
239     edata.definitionPoint.rotate(center, angle);
240     update();
241 }
242
243
244
245 void RS_DimRadial::scale(Vector center, Vector factor) {
246     RS_Dimension::scale(center, factor);
247
248     edata.definitionPoint.scale(center, factor);
249     edata.leader*=factor.x;
250     update();
251 }
252
253
254
255 void RS_DimRadial::mirror(Vector axisPoint1, Vector axisPoint2) {
256     RS_Dimension::mirror(axisPoint1, axisPoint2);
257
258     edata.definitionPoint.mirror(axisPoint1, axisPoint2);
259     update();
260 }
261
262
263 void RS_DimRadial::moveRef(const Vector& ref, const Vector& offset) {
264
265     if (ref.distanceTo(edata.definitionPoint)<1.0e-4) {
266                 double d = data.definitionPoint.distanceTo(edata.definitionPoint);
267                 double a = data.definitionPoint.angleTo(edata.definitionPoint + offset);
268
269                 Vector v;
270                 v.setPolar(d, a);
271         edata.definitionPoint = data.definitionPoint + v;
272                 update(true);
273     }
274         else if (ref.distanceTo(data.middleOfText)<1.0e-4) {
275         data.middleOfText.move(offset);
276                 update(false);
277     }
278 }
279
280 /**
281  * Dumps the point's data to stdout.
282  */
283 std::ostream& operator << (std::ostream& os, const RS_DimRadial& d) {
284     os << " DimRadial: " << d.getData() << "\n" << d.getEData() << "\n";
285     return os;
286 }
287
288