1
/****************************************************************************
3
** This file is part of the LibreCAD project, a 2D CAD program
5
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
6
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
9
** This file may be distributed and/or modified under the terms of the
10
** GNU General Public License version 2 as published by the Free Software
11
** Foundation and appearing in the file gpl-2.0.txt included in the
12
** packaging of this file.
14
** This program is distributed in the hope that it will be useful,
15
** but WITHOUT ANY WARRANTY; without even the implied warranty of
16
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
** GNU General Public License for more details.
19
** You should have received a copy of the GNU General Public License
20
** along with this program; if not, write to the Free Software
21
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
** This copyright notice MUST APPEAR in all copies of the script!
25
**********************************************************************/
28
#include "rs_dimangular.h"
30
#include "rs_constructionline.h"
31
#include "rs_graphic.h"
32
#include "rs_information.h"
40
* @para parent Parent Entity Container.
41
* @para d Common dimension geometrical data.
42
* @para ed Extended geometrical data for angular dimension.
44
RS_DimAngular::RS_DimAngular(RS_EntityContainer* parent,
45
const RS_DimensionData& d,
46
const RS_DimAngularData& ed)
47
: RS_Dimension(parent, d), edata(ed) {
55
* @return Automatically created label for the default
56
* measurement of this dimension.
58
QString RS_DimAngular::getMeasuredLabel() {
61
int dimaunit = getGraphicVariableInt("$DIMAUNIT", 0);
62
int dimadec = getGraphicVariableInt("$DIMADEC", 0);
64
ret = RS_Units::formatAngle(getAngle(),
65
RS_Units::numberToAngleFormat(dimaunit),
70
.arg(RS_Math::rad2deg(getAngle()))
79
* @return Angle of the measured dimension.
81
double RS_DimAngular::getAngle() {
84
bool reversed = false;
88
getAngles(ang1, ang2, reversed, p1, p2);
89
return reversed ? RS_Math::correctAngle(ang1 - ang2) : RS_Math::correctAngle(ang2 - ang1);
107
* @return Center of the measured dimension.
109
RS_Vector RS_DimAngular::getCenter() const {
110
RS_ConstructionLine l1(NULL, RS_ConstructionLineData(edata.definitionPoint1,
111
edata.definitionPoint2));
112
RS_ConstructionLine l2(NULL, RS_ConstructionLineData(edata.definitionPoint3,
113
data.definitionPoint));
114
RS_VectorSolutions vs = RS_Information::getIntersection(&l1, &l2, false);
122
* finds out which angles this dimension actually measures.
124
* @param ang1 Reference will return the start angle
125
* @param ang2 Reference will return the end angle
126
* @param reversed Reference will return the reversed flag.
128
* @return true: on success
130
bool RS_DimAngular::getAngles(double& ang1, double& ang2, bool& reversed,
131
RS_Vector& p1, RS_Vector& p2) {
133
RS_Vector vp0(edata.definitionPoint4 - getCenter());
134
RS_Vector vp1(edata.definitionPoint2 - edata.definitionPoint1);
135
RS_Vector vp2(data.definitionPoint - edata.definitionPoint3);
136
// project p0 to the basis of p1 and p2
137
// p0 = a1 p1 + a2 p2
138
// <p0.p1>= a1 |p1|^2 + a2 <p1.p2>
139
// <p0,p2>= a1 <p1.p2> + a2 |p2|^2
140
// a1 = ( |p2|^2 <p0.p1> - <p1.p2><p0.p2>) /( |p1|^2 |p2|^2 - <p1.p2>^2)
141
// a2 = ( |p1|^2 <p0.p2> - <p1.p2><p0.p1>) /( |p1|^2 |p2|^2 - <p1.p2>^2)
143
double rp1=vp1.squared();
144
double rp2=vp2.squared();
145
double p0p1=RS_Vector::dotP(vp0,vp1);
146
double p0p2=RS_Vector::dotP(vp0,vp2);
147
double p1p2=RS_Vector::dotP(vp1,vp2);
148
double d= rp1*rp2 - p1p2*p1p2;
149
double a1=d*(rp2*p0p1-p1p2*p0p2); // we only need the sign, so, use multiply instead of division to avoid divid by zero;
151
p1 = edata.definitionPoint2;
154
p1 = edata.definitionPoint1;
156
a1 = d*(rp1*p0p2-p1p2*p0p1);
158
p2 = data.definitionPoint;
161
p2 = edata.definitionPoint3;
164
RS_Vector center = getCenter();
165
double ang = center.angleTo(edata.definitionPoint4);
168
if ( ! RS_Math::isAngleBetween(ang, ang1,ang2,false) ) {
174
//std::cout<<"RS_DimAngular::getAngles(): new algorithm, angle1= "<<vp1.angle()<<"\tangle2= "<<vp2.angle()<<"\treversed= "<<reversed<<std::endl;
175
// bool done = false;
177
// // find out the angles this dimension refers to:
178
// for (int f1=0; f1<=1 && !done; ++f1) {
179
// ang1 = RS_Math::correctAngle(
180
// edata.definitionPoint1.angleTo(edata.definitionPoint2) + f1*M_PI);
182
// p1 = edata.definitionPoint2;
184
// p1 = edata.definitionPoint1;
186
// for (int f2=0; f2<=1 && !done; ++f2) {
187
// ang2 = RS_Math::correctAngle(
188
// edata.definitionPoint3.angleTo(data.definitionPoint) + f2*M_PI);
190
// p2 = data.definitionPoint;
192
// p2 = edata.definitionPoint3;
194
// for (int t=0; t<=1 && !done; ++t) {
195
// reversed = (bool)t;
203
// angDiff = ang2-ang1;
208
// angDiff = ang1-ang2;
211
// ang1 = RS_Math::correctAngle(ang1);
212
// ang2 = RS_Math::correctAngle(ang2);
214
// if (RS_Math::isAngleBetween(ang, ang1, ang2, reversed) &&
222
//std::cout<<"RS_DimAngular::getAngles(): old algorithm, ang1= "<<ang1<<"\tang2= "<<ang2<<"\treversed= "<<reversed<<std::endl;
230
* Updates the sub entities of this dimension. Called when the
231
* dimension or the position, alignment, .. changes.
233
* @param autoText Automatically reposition the text label
235
void RS_DimAngular::updateDim(bool /*autoText*/) {
237
RS_DEBUG->print("RS_DimAngular::update");
245
// general scale (DIMSCALE)
246
double dimscale = getGeneralScale();
247
// distance from entities (DIMEXO)
248
double dimexo = getExtensionLineOffset()*dimscale;
249
// extension line extension (DIMEXE)
250
double dimexe = getExtensionLineExtension()*dimscale;
251
// text height (DIMTXT)
252
double dimtxt = getTextHeight()*dimscale;
253
// text distance to line (DIMGAP)
254
double dimgap = getDimensionLineGap()*dimscale;
256
double arrowSize = getArrowSize()*dimscale;
259
RS_Vector center = getCenter();
267
bool reversed = false;
271
getAngles(ang1, ang2, reversed, p1, p2);
273
double rad = edata.definitionPoint4.distanceTo(center);
280
// 1st extension line:
281
dist = center.distanceTo(p1);
282
len = rad - dist + dimexe;
283
dir.setPolar(1.0, ang1);
284
line = new RS_Line(this,
285
RS_LineData(center + dir*dist + dir*dimexo,
286
center + dir*dist + dir*len));
287
line->setPen(RS_Pen(RS2::FlagInvalid));
288
line->setLayer(NULL);
291
// 2nd extension line:
292
dist = center.distanceTo(p2);
293
len = rad - dist + dimexe;
294
dir.setPolar(1.0, ang2);
295
line = new RS_Line(this,
296
RS_LineData(center + dir*dist + dir*dimexo,
297
center + dir*dist + dir*len));
298
line->setPen(RS_Pen(RS2::FlagInvalid));
299
line->setLayer(NULL);
302
// Create dimension line (arc):
303
RS_Arc* arc = new RS_Arc(this,
305
rad, ang1, ang2, reversed));
306
arc->setPen(RS_Pen(RS2::FlagInvalid));
310
// length of dimension arc:
311
double distance = arc->getLength();
313
// do we have to put the arrows outside of the arc?
314
bool outsideArrows = (distance<arrowSize*2);
317
double arrowAngle1, arrowAngle2;
320
arrowAng = arrowSize / rad;
326
if (!arc->isReversed()) {
327
v1.setPolar(rad, arc->getAngle1()+arrowAng);
329
v1.setPolar(rad, arc->getAngle1()-arrowAng);
331
v1+=arc->getCenter();
332
arrowAngle1 = arc->getStartpoint().angleTo(v1);
335
if (!arc->isReversed()) {
336
v2.setPolar(rad, arc->getAngle2()-arrowAng);
338
v2.setPolar(rad, arc->getAngle2()+arrowAng);
340
v2+=arc->getCenter();
341
arrowAngle2 = arc->getEndpoint().angleTo(v2);
343
if (!outsideArrows) {
344
arrowAngle1 = arrowAngle1+M_PI;
345
arrowAngle2 = arrowAngle2+M_PI;
353
arrow = new RS_Solid(this, sd);
354
arrow->shapeArrow(arc->getStartpoint(),
357
arrow->setPen(RS_Pen(RS2::FlagInvalid));
358
arrow->setLayer(NULL);
362
arrow = new RS_Solid(this, sd);
363
arrow->shapeArrow(arc->getEndpoint(),
366
arrow->setPen(RS_Pen(RS2::FlagInvalid));
367
arrow->setLayer(NULL);
372
RS_MTextData textData;
373
RS_Vector textPos = arc->getMiddlePoint();
377
double dimAngle1 = textPos.angleTo(arc->getCenter())-M_PI/2.0;
379
// rotate text so it's readable from the bottom or right (ISO)
381
if (dimAngle1>M_PI/2.0*3.0+0.001 ||
382
dimAngle1<M_PI/2.0+0.001) {
384
distV.setPolar(dimgap, dimAngle1+M_PI/2.0);
385
textAngle = dimAngle1;
389
distV.setPolar(dimgap, dimAngle1-M_PI/2.0);
390
textAngle = dimAngle1+M_PI;
393
// move text away from dimension line:
396
textData = RS_MTextData(textPos,
398
RS_MTextData::VABottom,
399
RS_MTextData::HACenter,
400
RS_MTextData::LeftToRight,
407
RS_MText* text = new RS_MText(this, textData);
409
// move text to the side:
410
text->setPen(RS_Pen(RS2::FlagInvalid));
411
text->setLayer(NULL);
419
void RS_DimAngular::move(const RS_Vector& offset) {
420
RS_Dimension::move(offset);
422
edata.definitionPoint1.move(offset);
423
edata.definitionPoint2.move(offset);
424
edata.definitionPoint3.move(offset);
425
edata.definitionPoint4.move(offset);
431
void RS_DimAngular::rotate(const RS_Vector& center, const double& angle) {
432
rotate(center, RS_Vector(angle));
435
void RS_DimAngular::rotate(const RS_Vector& center, const RS_Vector& angleVector) {
436
RS_Dimension::rotate(center, angleVector);
438
edata.definitionPoint1.rotate(center, angleVector);
439
edata.definitionPoint2.rotate(center, angleVector);
440
edata.definitionPoint3.rotate(center, angleVector);
441
edata.definitionPoint4.rotate(center, angleVector);
446
void RS_DimAngular::scale(const RS_Vector& center, const RS_Vector& factor) {
447
RS_Dimension::scale(center, factor);
449
edata.definitionPoint1.scale(center, factor);
450
edata.definitionPoint2.scale(center, factor);
451
edata.definitionPoint3.scale(center, factor);
452
edata.definitionPoint4.scale(center, factor);
458
void RS_DimAngular::mirror(const RS_Vector& axisPoint1, const RS_Vector& axisPoint2) {
459
RS_Dimension::mirror(axisPoint1, axisPoint2);
461
edata.definitionPoint1.mirror(axisPoint1, axisPoint2);
462
edata.definitionPoint2.mirror(axisPoint1, axisPoint2);
463
edata.definitionPoint3.mirror(axisPoint1, axisPoint2);
464
edata.definitionPoint4.mirror(axisPoint1, axisPoint2);
469
* Dumps the point's data to stdout.
471
std::ostream& operator << (std::ostream& os, const RS_DimAngular& d) {
472
os << " DimAngular: " << d.getData() << "\n" << d.getEData() << "\n";