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
8 // JLH = James L. Hammons <jlhamm@acm.org>
11 // --- ---------- -----------------------------------------------------------
12 // JLH 05/28/2010 Added this text. :-)
15 #include "rs_dimangular.h"
17 #include "rs_constructionline.h"
18 #include "rs_filterdxf.h"
20 #include "rs_information.h"
28 * @para parent Parent Entity Container.
29 * @para d Common dimension geometrical data.
30 * @para ed Extended geometrical data for angular dimension.
32 RS_DimAngular::RS_DimAngular(RS_EntityContainer * parent, const RS_DimensionData & d,
33 const RS_DimAngularData & ed): RS_Dimension(parent, d), edata(ed)
38 /*virtual*/ RS_DimAngular::~RS_DimAngular()
42 /*virtual*/ RS_Entity * RS_DimAngular::clone()
44 RS_DimAngular * d = new RS_DimAngular(*this);
45 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
46 // d->entities.setAutoDelete(entities.autoDelete());
52 /** @return RS2::EntityDimAngular */
53 /*virtual*/ RS2::EntityType RS_DimAngular::rtti() const
55 return RS2::EntityDimAngular;
59 * @return Copy of data that defines the angular dimension.
62 RS_DimAngularData RS_DimAngular::getEData() const
68 * @return Automatically created label for the default
69 * measurement of this dimension.
71 QString RS_DimAngular::getMeasuredLabel()
75 int dimaunit = getGraphicVariableInt("$DIMAUNIT", 0);
76 int dimadec = getGraphicVariableInt("$DIMADEC", 0);
78 ret = RS_Units::formatAngle(getAngle(),
79 RS_FilterDXF::numberToAngleFormat(dimaunit),
84 .arg(RS_Math::rad2deg(getAngle()))
93 * @return Angle of the measured dimension.
95 double RS_DimAngular::getAngle() {
98 bool reversed = false;
102 getAngles(ang1, ang2, reversed, p1, p2);
120 * @return Center of the measured dimension.
122 Vector RS_DimAngular::getCenter() {
123 RS_ConstructionLine l1(NULL, RS_ConstructionLineData(edata.definitionPoint1,
124 edata.definitionPoint2));
125 RS_ConstructionLine l2(NULL, RS_ConstructionLineData(edata.definitionPoint3,
126 data.definitionPoint));
127 VectorSolutions vs = RS_Information::getIntersection(&l1, &l2, false);
135 * finds out which angles this dimension actually measures.
137 * @param ang1 Reference will return the start angle
138 * @param ang2 Reference will return the end angle
139 * @param reversed Reference will return the reversed flag.
141 * @return true: on success
143 bool RS_DimAngular::getAngles(double& ang1, double& ang2, bool& reversed,
144 Vector& p1, Vector& p2) {
146 Vector center = getCenter();
147 double ang = center.angleTo(edata.definitionPoint4);
150 // find out the angles this dimension refers to:
151 for (int f1=0; f1<=1 && !done; ++f1) {
152 ang1 = RS_Math::correctAngle(
153 edata.definitionPoint1.angleTo(edata.definitionPoint2) + f1*M_PI);
155 p1 = edata.definitionPoint2;
157 p1 = edata.definitionPoint1;
159 for (int f2=0; f2<=1 && !done; ++f2) {
160 ang2 = RS_Math::correctAngle(
161 edata.definitionPoint3.angleTo(data.definitionPoint) + f2*M_PI);
163 p2 = data.definitionPoint;
165 p2 = edata.definitionPoint3;
167 for (int t=0; t<=1 && !done; ++t) {
184 ang1 = RS_Math::correctAngle(ang1);
185 ang2 = RS_Math::correctAngle(ang2);
187 if (RS_Math::isAngleBetween(ang, ang1, ang2, reversed) &&
202 * Updates the sub entities of this dimension. Called when the
203 * dimension or the position, alignment, .. changes.
205 * @param autoText Automatically reposition the text label
207 void RS_DimAngular::update(bool /*autoText*/) {
209 RS_DEBUG->print("RS_DimAngular::update");
217 // distance from entities (DIMEXO)
218 double dimexo = getExtensionLineOffset();
219 // extension line extension (DIMEXE)
220 double dimexe = getExtensionLineExtension();
221 // text height (DIMTXT)
222 double dimtxt = getTextHeight();
223 // text distance to line (DIMGAP)
224 double dimgap = getDimensionLineGap();
227 Vector center = getCenter();
235 bool reversed = false;
239 getAngles(ang1, ang2, reversed, p1, p2);
241 double rad = edata.definitionPoint4.distanceTo(center);
248 // 1st extension line:
249 dist = center.distanceTo(p1);
250 len = rad - dist + dimexe;
251 dir.setPolar(1.0, ang1);
252 line = new RS_Line(this,
253 RS_LineData(center + dir*dist + dir*dimexo,
254 center + dir*dist + dir*len));
255 line->setPen(RS_Pen(RS2::FlagInvalid));
256 line->setLayer(NULL);
259 // 2nd extension line:
260 dist = center.distanceTo(p2);
261 len = rad - dist + dimexe;
262 dir.setPolar(1.0, ang2);
263 line = new RS_Line(this,
264 RS_LineData(center + dir*dist + dir*dimexo,
265 center + dir*dist + dir*len));
266 line->setPen(RS_Pen(RS2::FlagInvalid));
267 line->setLayer(NULL);
270 // Create dimension line (arc):
271 RS_Arc* arc = new RS_Arc(this,
273 rad, ang1, ang2, reversed));
274 arc->setPen(RS_Pen(RS2::FlagInvalid));
278 // length of dimension arc:
279 double distance = arc->getLength();
281 // do we have to put the arrows outside of the arc?
282 bool outsideArrows = (distance<getArrowSize()*2);
285 double arrowAngle1, arrowAngle2;
288 arrowAng = getArrowSize() / rad;
294 if (!arc->isReversed()) {
295 v1.setPolar(rad, arc->getAngle1()+arrowAng);
297 v1.setPolar(rad, arc->getAngle1()-arrowAng);
299 v1+=arc->getCenter();
300 arrowAngle1 = arc->getStartpoint().angleTo(v1);
303 if (!arc->isReversed()) {
304 v2.setPolar(rad, arc->getAngle2()-arrowAng);
306 v2.setPolar(rad, arc->getAngle2()+arrowAng);
308 v2+=arc->getCenter();
309 arrowAngle2 = arc->getEndpoint().angleTo(v2);
311 if (!outsideArrows) {
312 arrowAngle1 = arrowAngle1+M_PI;
313 arrowAngle2 = arrowAngle2+M_PI;
321 arrow = new RS_Solid(this, sd);
322 arrow->shapeArrow(arc->getStartpoint(),
325 arrow->setPen(RS_Pen(RS2::FlagInvalid));
326 arrow->setLayer(NULL);
330 arrow = new RS_Solid(this, sd);
331 arrow->shapeArrow(arc->getEndpoint(),
334 arrow->setPen(RS_Pen(RS2::FlagInvalid));
335 arrow->setLayer(NULL);
340 RS_TextData textData;
341 Vector textPos = arc->getMiddlepoint();
345 double dimAngle1 = textPos.angleTo(arc->getCenter())-M_PI/2.0;
347 // rotate text so it's readable from the bottom or right (ISO)
349 if (dimAngle1>M_PI/2.0*3.0+0.001 ||
350 dimAngle1<M_PI/2.0+0.001) {
352 distV.setPolar(dimgap, dimAngle1+M_PI/2.0);
353 textAngle = dimAngle1;
357 distV.setPolar(dimgap, dimAngle1-M_PI/2.0);
358 textAngle = dimAngle1+M_PI;
361 // move text away from dimension line:
364 textData = RS_TextData(textPos,
375 RS_Text* text = new RS_Text(this, textData);
377 // move text to the side:
378 text->setPen(RS_Pen(RS2::FlagInvalid));
379 text->setLayer(NULL);
385 Vector RS_DimAngular::getDefinitionPoint1()
387 return edata.definitionPoint1;
390 Vector RS_DimAngular::getDefinitionPoint2()
392 return edata.definitionPoint2;
395 Vector RS_DimAngular::getDefinitionPoint3()
397 return edata.definitionPoint3;
400 Vector RS_DimAngular::getDefinitionPoint4()
402 return edata.definitionPoint4;
405 void RS_DimAngular::move(Vector offset)
407 RS_Dimension::move(offset);
409 edata.definitionPoint1.move(offset);
410 edata.definitionPoint2.move(offset);
411 edata.definitionPoint3.move(offset);
412 edata.definitionPoint4.move(offset);
418 void RS_DimAngular::rotate(Vector center, double angle) {
419 RS_Dimension::rotate(center, angle);
421 edata.definitionPoint1.rotate(center, angle);
422 edata.definitionPoint2.rotate(center, angle);
423 edata.definitionPoint3.rotate(center, angle);
424 edata.definitionPoint4.rotate(center, angle);
430 void RS_DimAngular::scale(Vector center, Vector factor) {
431 RS_Dimension::scale(center, factor);
433 edata.definitionPoint1.scale(center, factor);
434 edata.definitionPoint2.scale(center, factor);
435 edata.definitionPoint3.scale(center, factor);
436 edata.definitionPoint4.scale(center, factor);
442 void RS_DimAngular::mirror(Vector axisPoint1, Vector axisPoint2) {
443 RS_Dimension::mirror(axisPoint1, axisPoint2);
445 edata.definitionPoint1.mirror(axisPoint1, axisPoint2);
446 edata.definitionPoint2.mirror(axisPoint1, axisPoint2);
447 edata.definitionPoint3.mirror(axisPoint1, axisPoint2);
448 edata.definitionPoint4.mirror(axisPoint1, axisPoint2);
453 * Dumps the point's data to stdout.
455 std::ostream& operator << (std::ostream& os, const RS_DimAngular& d) {
456 os << " DimAngular: " << d.getData() << "\n" << d.getEData() << "\n";