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
10 // JLH = James L. Hammons <jlhamm@acm.org>
13 // --- ---------- -----------------------------------------------------------
14 // JLH 05/28/2010 Added this text. :-)
17 #include "dimangular.h"
19 #include "constructionline.h"
20 #include "filterdxf.h"
22 #include "information.h"
30 * @para parent Parent Entity Container.
31 * @para d Common dimension geometrical data.
32 * @para ed Extended geometrical data for angular dimension.
34 DimAngular::DimAngular(EntityContainer * parent, const DimensionData & d,
35 const DimAngularData & ed): Dimension(parent, d), edata(ed)
40 /*virtual*/ DimAngular::~DimAngular()
44 /*virtual*/ Entity * DimAngular::clone()
46 DimAngular * d = new DimAngular(*this);
47 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
48 // d->entities.setAutoDelete(entities.autoDelete());
54 /** @return RS2::EntityDimAngular */
55 /*virtual*/ RS2::EntityType DimAngular::rtti() const
57 return RS2::EntityDimAngular;
61 * @return Copy of data that defines the angular dimension.
64 DimAngularData DimAngular::getEData() const
70 * @return Automatically created label for the default
71 * measurement of this dimension.
73 QString DimAngular::getMeasuredLabel()
77 int dimaunit = getGraphicVariableInt("$DIMAUNIT", 0);
78 int dimadec = getGraphicVariableInt("$DIMADEC", 0);
80 ret = Units::formatAngle(getAngle(),
81 FilterDXF::numberToAngleFormat(dimaunit),
86 .arg(Math::rad2deg(getAngle()))
95 * @return Angle of the measured dimension.
97 double DimAngular::getAngle() {
100 bool reversed = false;
104 getAngles(ang1, ang2, reversed, p1, p2);
122 * @return Center of the measured dimension.
124 Vector DimAngular::getCenter() {
125 ConstructionLine l1(NULL, ConstructionLineData(edata.definitionPoint1,
126 edata.definitionPoint2));
127 ConstructionLine l2(NULL, ConstructionLineData(edata.definitionPoint3,
128 data.definitionPoint));
129 VectorSolutions vs = Information::getIntersection(&l1, &l2, false);
137 * finds out which angles this dimension actually measures.
139 * @param ang1 Reference will return the start angle
140 * @param ang2 Reference will return the end angle
141 * @param reversed Reference will return the reversed flag.
143 * @return true: on success
145 bool DimAngular::getAngles(double& ang1, double& ang2, bool& reversed,
146 Vector& p1, Vector& p2) {
148 Vector center = getCenter();
149 double ang = center.angleTo(edata.definitionPoint4);
152 // find out the angles this dimension refers to:
153 for (int f1=0; f1<=1 && !done; ++f1) {
154 ang1 = Math::correctAngle(
155 edata.definitionPoint1.angleTo(edata.definitionPoint2) + f1*M_PI);
157 p1 = edata.definitionPoint2;
159 p1 = edata.definitionPoint1;
161 for (int f2=0; f2<=1 && !done; ++f2) {
162 ang2 = Math::correctAngle(
163 edata.definitionPoint3.angleTo(data.definitionPoint) + f2*M_PI);
165 p2 = data.definitionPoint;
167 p2 = edata.definitionPoint3;
169 for (int t=0; t<=1 && !done; ++t) {
186 ang1 = Math::correctAngle(ang1);
187 ang2 = Math::correctAngle(ang2);
189 if (Math::isAngleBetween(ang, ang1, ang2, reversed) &&
204 * Updates the sub entities of this dimension. Called when the
205 * dimension or the position, alignment, .. changes.
207 * @param autoText Automatically reposition the text label
209 void DimAngular::update(bool /*autoText*/) {
211 DEBUG->print("DimAngular::update");
219 // distance from entities (DIMEXO)
220 double dimexo = getExtensionLineOffset();
221 // extension line extension (DIMEXE)
222 double dimexe = getExtensionLineExtension();
223 // text height (DIMTXT)
224 double dimtxt = getTextHeight();
225 // text distance to line (DIMGAP)
226 double dimgap = getDimensionLineGap();
229 Vector center = getCenter();
237 bool reversed = false;
241 getAngles(ang1, ang2, reversed, p1, p2);
243 double rad = edata.definitionPoint4.distanceTo(center);
250 // 1st extension line:
251 dist = center.distanceTo(p1);
252 len = rad - dist + dimexe;
253 dir.setPolar(1.0, ang1);
254 line = new Line(this,
255 LineData(center + dir*dist + dir*dimexo,
256 center + dir*dist + dir*len));
257 line->setPen(Pen(RS2::FlagInvalid));
258 line->setLayer(NULL);
261 // 2nd extension line:
262 dist = center.distanceTo(p2);
263 len = rad - dist + dimexe;
264 dir.setPolar(1.0, ang2);
265 line = new Line(this,
266 LineData(center + dir*dist + dir*dimexo,
267 center + dir*dist + dir*len));
268 line->setPen(Pen(RS2::FlagInvalid));
269 line->setLayer(NULL);
272 // Create dimension line (arc):
273 Arc* arc = new Arc(this,
275 rad, ang1, ang2, reversed));
276 arc->setPen(Pen(RS2::FlagInvalid));
280 // length of dimension arc:
281 double distance = arc->getLength();
283 // do we have to put the arrows outside of the arc?
284 bool outsideArrows = (distance<getArrowSize()*2);
287 double arrowAngle1, arrowAngle2;
290 arrowAng = getArrowSize() / rad;
296 if (!arc->isReversed()) {
297 v1.setPolar(rad, arc->getAngle1()+arrowAng);
299 v1.setPolar(rad, arc->getAngle1()-arrowAng);
301 v1+=arc->getCenter();
302 arrowAngle1 = arc->getStartpoint().angleTo(v1);
305 if (!arc->isReversed()) {
306 v2.setPolar(rad, arc->getAngle2()-arrowAng);
308 v2.setPolar(rad, arc->getAngle2()+arrowAng);
310 v2+=arc->getCenter();
311 arrowAngle2 = arc->getEndpoint().angleTo(v2);
313 if (!outsideArrows) {
314 arrowAngle1 = arrowAngle1+M_PI;
315 arrowAngle2 = arrowAngle2+M_PI;
323 arrow = new Solid(this, sd);
324 arrow->shapeArrow(arc->getStartpoint(),
327 arrow->setPen(Pen(RS2::FlagInvalid));
328 arrow->setLayer(NULL);
332 arrow = new Solid(this, sd);
333 arrow->shapeArrow(arc->getEndpoint(),
336 arrow->setPen(Pen(RS2::FlagInvalid));
337 arrow->setLayer(NULL);
343 Vector textPos = arc->getMiddlepoint();
347 double dimAngle1 = textPos.angleTo(arc->getCenter())-M_PI/2.0;
349 // rotate text so it's readable from the bottom or right (ISO)
351 if (dimAngle1>M_PI/2.0*3.0+0.001 ||
352 dimAngle1<M_PI/2.0+0.001) {
354 distV.setPolar(dimgap, dimAngle1+M_PI/2.0);
355 textAngle = dimAngle1;
359 distV.setPolar(dimgap, dimAngle1-M_PI/2.0);
360 textAngle = dimAngle1+M_PI;
363 // move text away from dimension line:
366 textData = TextData(textPos,
377 Text* text = new Text(this, textData);
379 // move text to the side:
380 text->setPen(Pen(RS2::FlagInvalid));
381 text->setLayer(NULL);
387 Vector DimAngular::getDefinitionPoint1()
389 return edata.definitionPoint1;
392 Vector DimAngular::getDefinitionPoint2()
394 return edata.definitionPoint2;
397 Vector DimAngular::getDefinitionPoint3()
399 return edata.definitionPoint3;
402 Vector DimAngular::getDefinitionPoint4()
404 return edata.definitionPoint4;
407 void DimAngular::move(Vector offset)
409 Dimension::move(offset);
411 edata.definitionPoint1.move(offset);
412 edata.definitionPoint2.move(offset);
413 edata.definitionPoint3.move(offset);
414 edata.definitionPoint4.move(offset);
420 void DimAngular::rotate(Vector center, double angle) {
421 Dimension::rotate(center, angle);
423 edata.definitionPoint1.rotate(center, angle);
424 edata.definitionPoint2.rotate(center, angle);
425 edata.definitionPoint3.rotate(center, angle);
426 edata.definitionPoint4.rotate(center, angle);
432 void DimAngular::scale(Vector center, Vector factor) {
433 Dimension::scale(center, factor);
435 edata.definitionPoint1.scale(center, factor);
436 edata.definitionPoint2.scale(center, factor);
437 edata.definitionPoint3.scale(center, factor);
438 edata.definitionPoint4.scale(center, factor);
444 void DimAngular::mirror(Vector axisPoint1, Vector axisPoint2) {
445 Dimension::mirror(axisPoint1, axisPoint2);
447 edata.definitionPoint1.mirror(axisPoint1, axisPoint2);
448 edata.definitionPoint2.mirror(axisPoint1, axisPoint2);
449 edata.definitionPoint3.mirror(axisPoint1, axisPoint2);
450 edata.definitionPoint4.mirror(axisPoint1, axisPoint2);
455 * Dumps the point's data to stdout.
457 std::ostream& operator << (std::ostream& os, const DimAngular& d) {
458 os << " DimAngular: " << d.getData() << "\n" << d.getEData() << "\n";