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_dimlinear.h"
17 #include "rs_constructionline.h"
20 #include "rs_graphic.h"
26 * @para parent Parent Entity Container.
27 * @para d Common dimension geometrical data.
28 * @para ed Extended geometrical data for linear dimension.
30 RS_DimLinear::RS_DimLinear(RS_EntityContainer * parent, const RS_DimensionData & d,
31 const RS_DimLinearData & ed): RS_Dimension(parent, d), edata(ed)
36 /*virtual*/ RS_DimLinear::~RS_DimLinear()
40 /*virtual*/ RS_Entity * RS_DimLinear::clone()
42 RS_DimLinear * d = new RS_DimLinear(*this);
43 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
44 // d->entities.setAutoDelete(entities.autoDelete());
51 /** @return RS2::EntityDimLinear */
52 /*virtual*/ RS2::EntityType RS_DimLinear::rtti() const
54 return RS2::EntityDimLinear;
58 * @return Copy of data that defines the linear dimension.
61 RS_DimLinearData RS_DimLinear::getEData() const
66 VectorSolutions RS_DimLinear::getRefPoints()
68 VectorSolutions ret(edata.extensionPoint1, edata.extensionPoint2,
69 data.definitionPoint, data.middleOfText);
75 * @return Automatically created label for the default
76 * measurement of this dimension.
78 QString RS_DimLinear::getMeasuredLabel()
80 // direction of dimension line
82 dirDim.setPolar(100.0, edata.angle);
84 // construction line for dimension line
85 RS_ConstructionLine dimLine(NULL, RS_ConstructionLineData(data.definitionPoint,
86 data.definitionPoint + dirDim));
88 Vector dimP1 = dimLine.getNearestPointOnEntity(edata.extensionPoint1);
89 Vector dimP2 = dimLine.getNearestPointOnEntity(edata.extensionPoint2);
91 // Definitive dimension line:
92 double dist = dimP1.distanceTo(dimP2);
94 RS_Graphic* graphic = getGraphic();
99 ret = RS_Units::formatLinear(dist, graphic->getUnit(),
100 graphic->getLinearFormat(), graphic->getLinearPrecision());
104 ret = QString("%1").arg(dist);
110 bool RS_DimLinear::hasEndpointsWithinWindow(Vector v1, Vector v2)
112 return (edata.extensionPoint1.isInWindow(v1, v2)
113 || edata.extensionPoint2.isInWindow(v1, v2));
117 * Updates the sub entities of this dimension. Called when the
118 * text or the position, alignment, .. changes.
120 * @param autoText Automatically reposition the text label
122 void RS_DimLinear::update(bool autoText)
124 RS_DEBUG->print("RS_DimLinear::update");
131 // distance from entities (DIMEXO)
132 double dimexo = getExtensionLineOffset();
133 // extension line extension (DIMEXE)
134 double dimexe = getExtensionLineExtension();
137 double extAngle = edata.angle + (M_PI/2.0);
139 // direction of dimension line
141 dirDim.setPolar(100.0, edata.angle);
142 // direction of extension lines
144 dirExt.setPolar(100.0, extAngle);
146 // construction line for dimension line
147 RS_ConstructionLine dimLine(NULL, RS_ConstructionLineData(data.definitionPoint,
148 data.definitionPoint + dirDim));
150 Vector dimP1 = dimLine.getNearestPointOnEntity(edata.extensionPoint1);
151 Vector dimP2 = dimLine.getNearestPointOnEntity(edata.extensionPoint2);
153 // Definitive dimension line:
154 updateCreateDimensionLine(dimP1, dimP2, true, true, autoText);
156 ld = RS_LineData(data.definitionPoint, dimP1);
157 RS_Line* dimensionLine = new RS_Line(this, ld);
158 addEntity(dimensionLine);
160 Vector vDimexo1, vDimexe1, vDimexo2, vDimexe2;
161 vDimexe1.setPolar(dimexe, edata.extensionPoint1.angleTo(dimP1));
162 vDimexo1.setPolar(dimexo, edata.extensionPoint1.angleTo(dimP1));
164 vDimexe2.setPolar(dimexe, edata.extensionPoint2.angleTo(dimP2));
165 vDimexo2.setPolar(dimexo, edata.extensionPoint2.angleTo(dimP2));
167 if ((edata.extensionPoint1 - dimP1).magnitude() < 1e-6)
169 vDimexe1.setPolar(dimexe, data.definitionPoint.angleTo(dimP1) - M_PI / 2.0);
170 vDimexo1.setPolar(dimexo, data.definitionPoint.angleTo(dimP1) - M_PI / 2.0);
173 if ((edata.extensionPoint2 - dimP2).magnitude() < 1e-6)
175 vDimexe2.setPolar(dimexe, data.definitionPoint.angleTo(dimP2) - M_PI / 2.0);
176 vDimexo2.setPolar(dimexo, data.definitionPoint.angleTo(dimP2) - M_PI / 2.0);
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);
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);
196 Vector RS_DimLinear::getExtensionPoint1()
198 return edata.extensionPoint1;
201 Vector RS_DimLinear::getExtensionPoint2()
203 return edata.extensionPoint2;
206 double RS_DimLinear::getAngle()
211 void RS_DimLinear::setAngle(double a)
213 edata.angle = RS_Math::correctAngle(a);
216 double RS_DimLinear::getOblique()
218 return edata.oblique;
221 void RS_DimLinear::move(Vector offset)
223 RS_Dimension::move(offset);
225 edata.extensionPoint1.move(offset);
226 edata.extensionPoint2.move(offset);
230 void RS_DimLinear::rotate(Vector center, double angle)
232 RS_Dimension::rotate(center, angle);
234 edata.extensionPoint1.rotate(center, angle);
235 edata.extensionPoint2.rotate(center, angle);
236 edata.angle = RS_Math::correctAngle(edata.angle+angle);
240 void RS_DimLinear::scale(Vector center, Vector factor)
242 RS_Dimension::scale(center, factor);
244 edata.extensionPoint1.scale(center, factor);
245 edata.extensionPoint2.scale(center, factor);
249 void RS_DimLinear::mirror(Vector axisPoint1, Vector axisPoint2)
251 RS_Dimension::mirror(axisPoint1, axisPoint2);
253 edata.extensionPoint1.mirror(axisPoint1, axisPoint2);
254 edata.extensionPoint2.mirror(axisPoint1, axisPoint2);
257 vec.setPolar(1.0, edata.angle);
258 vec.mirror(Vector(0.0, 0.0), axisPoint2 - axisPoint1);
259 edata.angle = vec.angle();
264 void RS_DimLinear::stretch(Vector firstCorner, Vector secondCorner, Vector offset)
266 //e->calculateBorders();
267 if (getMin().isInWindow(firstCorner, secondCorner)
268 && getMax().isInWindow(firstCorner, secondCorner))
274 //Vector v = data.definitionPoint - edata.extensionPoint2;
275 //double len = edata.extensionPoint2.distanceTo(data.definitionPoint);
276 //double ang1 = edata.extensionPoint1.angleTo(edata.extensionPoint2)
279 if (edata.extensionPoint1.isInWindow(firstCorner, secondCorner))
280 edata.extensionPoint1.move(offset);
282 if (edata.extensionPoint2.isInWindow(firstCorner, secondCorner))
283 edata.extensionPoint2.move(offset);
286 double ang2 = edata.extensionPoint1.angleTo(edata.extensionPoint2)
289 double diff = RS_Math::getAngleDifference(ang1, ang2);
294 if (fabs(diff)>M_PI/2) {
295 ang2 = RS_Math::correctAngle(ang2+M_PI);
299 v.setPolar(len, ang2);
300 data.definitionPoint = edata.extensionPoint2 + v;
307 void RS_DimLinear::moveRef(const Vector & ref, const Vector & offset)
309 if (ref.distanceTo(data.definitionPoint) < 1.0e-4)
311 data.definitionPoint += offset;
314 else if (ref.distanceTo(data.middleOfText) < 1.0e-4)
316 data.middleOfText += offset;
319 else if (ref.distanceTo(edata.extensionPoint1) < 1.0e-4)
321 edata.extensionPoint1 += offset;
324 else if (ref.distanceTo(edata.extensionPoint2) < 1.0e-4)
326 edata.extensionPoint2 += offset;
332 * Dumps the point's data to stdout.
334 std::ostream & operator<<(std::ostream & os, const RS_DimLinear & d)
336 os << " DimLinear: " << d.getData() << "\n" << d.getEData() << "\n";