/** * Creates an arc from 3 points. */ RArc RArc::createFrom3Points(const RVector& startPoint, const RVector& point, const RVector& endPoint) { // intersection of two middle lines // middle points between first two points: RVector mp1 = RVector::getAverage(startPoint, point); double a1 = startPoint.getAngleTo(point) + M_PI / 2.0; // direction from middle point to center: RVector dir1 = RVector::createPolar(1.0, a1); // middle points between last two points: RVector mp2 = RVector::getAverage(point, endPoint); double a2 = point.getAngleTo(endPoint) + M_PI / 2.0; // direction from middle point to center: RVector dir2 = RVector::createPolar(1.0, a2); RLine midLine1(mp1, mp1 + dir1); RLine midLine2(mp2, mp2 + dir2); QList<RVector> ips = midLine1.getIntersectionPoints(midLine2, false); if (ips.length()!=1) { //this.error = qsTr("No arc possible"); return RArc(); } RVector center = ips[0]; double radius = center.getDistanceTo(endPoint); double angle1 = center.getAngleTo(startPoint); double angle2 = center.getAngleTo(endPoint); bool reversed = RMath::isAngleBetween(center.getAngleTo(point), angle1, angle2, true); return RArc(center, radius, angle1, angle2, reversed); }
RCircle RCircle::createFrom3Points(const RVector& p1, const RVector& p2, const RVector& p3) { // intersection of two middle lines // middle points between first two points: RVector mp1 = RVector::getAverage(p1, p2); double a1 = p1.getAngleTo(p2) + M_PI / 2.0; // direction from middle point to center: RVector dir1 = RVector::createPolar(1.0, a1); // middle points between last two points: RVector mp2 = RVector::getAverage(p2, p3); double a2 = p2.getAngleTo(p3) + M_PI / 2.0; // direction from middle point to center: RVector dir2 = RVector::createPolar(1.0, a2); RLine midLine1(mp1, mp1 + dir1); RLine midLine2(mp2, mp2 + dir2); QList<RVector> ips = midLine1.getIntersectionPoints(midLine2, false); if (ips.length()!=1) { return RCircle(); } RVector center = ips[0]; double radius = center.getDistanceTo(p3); // double angle1 = center.getAngleTo(p1); // double angle2 = center.getAngleTo(p3); // bool reversed = RMath::isAngleBetween(center.getAngleTo(p2), // angle1, angle2, true); return RCircle(center, radius); }
void REllipse::moveEndPoint(const RVector& pos, bool changeAngleOnly) { if (changeAngleOnly) { endParam = getParamTo(pos); } else { RVector sp = getStartPoint(); double distOri = sp.getDistanceTo(getEndPoint()); double angleOri = sp.getAngleTo(getEndPoint()); if (distOri<RS::PointTolerance) { return; } double distNew = sp.getDistanceTo(pos); double angleNew = sp.getAngleTo(pos); double factor = distNew / distOri; if (factor<RS::PointTolerance) { return; } double angleDelta = angleNew - angleOri; center.scale(factor, sp); center.rotate(angleDelta, sp); majorPoint.scale(factor); majorPoint.rotate(angleDelta); } }
/** * Creates an arc from its startpoint, endpoint and bulge (= tan(angle/4)). */ RArc RArc::createFrom2PBulge(const RVector& startPoint, const RVector& endPoint, double bulge) { RArc arc; arc.reversed = (bulge < 0.0); double alpha = atan(bulge) * 4.0; RVector middle = (startPoint + endPoint) / 2.0; double dist = startPoint.getDistanceTo(endPoint) / 2.0; // alpha can't be 0.0 at this point arc.radius = fabs(dist / sin(alpha / 2.0)); double wu = fabs(RMath::pow(arc.radius, 2.0) - RMath::pow(dist, 2.0)); double h = sqrt(wu); double angle = startPoint.getAngleTo(endPoint); if (bulge > 0.0) { angle += M_PI / 2.0; } else { angle -= M_PI / 2.0; } if (fabs(alpha) > M_PI) { h *= -1.0; } arc.center.setPolar(h, angle); arc.center += middle; arc.startAngle = arc.center.getAngleTo(startPoint); arc.endAngle = arc.center.getAngleTo(endPoint); return arc; }
/** * \return Shape of segment at given position. */ QSharedPointer<RShape> RPolyline::getSegmentAt(int i) const { if (i<0 || i>=vertices.size() || i>=bulges.size()) { qWarning() << "RPolyline::getSegmentAt(" << i << "): i out of range"; return QSharedPointer<RShape>(); } RVector p1 = vertices.at(i); RVector p2 = vertices.at((i+1) % vertices.size()); if (RPolyline::isStraight(bulges.at(i))) { return QSharedPointer<RShape>(new RLine(p1, p2)); } else { double bulge = bulges.at(i); bool reversed = bulge<0.0; double alpha = atan(bulge)*4.0; if (fabs(alpha) > 2*M_PI-RS::AngleTolerance) { return QSharedPointer<RShape>(); } double radius; RVector center; RVector middle; double dist; double angle; middle = (p1+p2)/2.0; dist = p1.getDistanceTo(p2)/2.0; angle = p1.getAngleTo(p2); // alpha can't be 0.0 at this point radius = fabs(dist / sin(alpha/2.0)); double rootTerm = fabs(radius*radius - dist*dist); double h = sqrt(rootTerm); if (bulge>0.0) { angle+=M_PI/2.0; } else { angle-=M_PI/2.0; } if (fabs(alpha)>M_PI) { h*=-1.0; } center.setPolar(h, angle); center+=middle; double a1; double a2; a1 = center.getAngleTo(p1); a2 = center.getAngleTo(p2); return QSharedPointer<RShape>(new RArc(center, radius, a1, a2, reversed)); } }
bool RDimDiametricData::moveReferencePoint(const RVector& referencePoint, const RVector& targetPoint) { bool ret = false; if (referencePoint.equalsFuzzy(chordPoint)) { RVector c = (definitionPoint + chordPoint)/2.0; double d = c.getDistanceTo(chordPoint); double a = c.getAngleTo(targetPoint); RVector v = RVector::createPolar(d, a); chordPoint = c + v; definitionPoint = c - v; autoTextPos = true; ret = true; } else if (referencePoint.equalsFuzzy(definitionPoint)) { RVector c = (definitionPoint + chordPoint)/2.0; double d = c.getDistanceTo(definitionPoint); double a = c.getAngleTo(targetPoint); RVector v = RVector::createPolar(d, a); definitionPoint = c + v; chordPoint = c - v; autoTextPos = true; ret = true; } if (!ret) { ret = RDimensionData::moveReferencePoint(referencePoint, targetPoint); } if (ret) { update(); } return ret; }
/** * Finds out which angles this dimension actually measures. * * \param ang1 Reference will return the start angle * \param ang2 Reference will return the end angle * \param reversed Reference will return the reversed flag. * * \return true: on success */ bool RDimAngularData::getAngles(double& ang1, double& ang2, bool& reversed, RVector& p1, RVector& p2) const { RVector center = getCenter(); double ang = center.getAngleTo(dimArcPosition); bool done = false; // find out the angles this dimension refers to: for (int f1=0; f1<=1 && !done; ++f1) { ang1 = RMath::getNormalizedAngle(extensionLine1End.getAngleTo(extensionLine1Start) + f1*M_PI); if (f1==0) { p1 = extensionLine1Start; } else { p1 = extensionLine1End; } for (int f2=0; f2<=1 && !done; ++f2) { ang2 = RMath::getNormalizedAngle(extensionLine2Start.getAngleTo(definitionPoint) + f2*M_PI); if (f2==0) { p2 = definitionPoint; } else { p2 = extensionLine2Start; } for (int t=0; t<=1 && !done; ++t) { reversed = (bool)t; double angDiff; if (!reversed) { if (ang2<ang1) { ang2+=2*M_PI; } angDiff = ang2-ang1; } else { if (ang1<ang2) { ang1+=2*M_PI; } angDiff = ang1-ang2; } ang1 = RMath::getNormalizedAngle(ang1); ang2 = RMath::getNormalizedAngle(ang2); if (RMath::isAngleBetween(ang, ang1, ang2, reversed) && angDiff<=M_PI) { done = true; break; } } } } return done; }
void RDimAlignedData::recomputeDefinitionPoint( const RVector& oldExtPoint1, const RVector& oldExtPoint2, const RVector& newExtPoint1, const RVector& newExtPoint2) { RLine dLine(oldExtPoint1, oldExtPoint2); double d = dLine.getDistanceTo(definitionPoint, false); RS::Side s = dLine.getSideOfPoint(definitionPoint); double a = newExtPoint1.getAngleTo(newExtPoint2); if (s==RS::LeftHand) { a+=M_PI/2.0; } else { a-=M_PI/2.0; } RVector v = RVector::createPolar(d, a); RVector dp = newExtPoint1 + v; if (dp.isValid()) { definitionPoint = dp; } }
/** * \todo Not working as expected, fix or disable */ QSharedPointer<RShape> RArc::getTransformed(const QTransform& transform) const { RVector ct = center.getTransformed2d(transform); RVector sp = getStartPoint(); RVector spt = sp.getTransformed2d(transform); RVector ep = getEndPoint(); RVector ept = ep.getTransformed2d(transform); //RVector mp = getMiddlePoint(); //RVector mpt = mp.getTransformed2d(transform); RArc* ret = new RArc( ct, ct.getDistanceTo(spt), ct.getAngleTo(spt), ct.getAngleTo(ept), reversed ); // if (!ret->getMiddlePoint().equalsFuzzy(mpt)) { // ret->setReversed(!reversed); // } return QSharedPointer<RShape>(ret); }
QList<QSharedPointer<RShape> > RDimAngularData::getShapes(const RBox& queryBox, bool ignoreComplex, bool segment) const { Q_UNUSED(queryBox) Q_UNUSED(ignoreComplex) Q_UNUSED(segment) QSharedPointer<RBlockReferenceEntity> dimBlockReference = getDimensionBlockReference(); if (!dimBlockReference.isNull()) { return dimBlockReference->getShapes(queryBox, ignoreComplex); } QList<QSharedPointer<RShape> > ret; double dimexo = getDimexo(); double dimexe = getDimexe(); double dimtxt = getDimtxt(); double dimgap = getDimgap(); double dimasz = getDimasz(); // find out center: RVector center = getCenter(); if (!center.isValid()) { return ret; } double ang1 = 0.0; double ang2 = 0.0; bool reversed = false; RVector p1; RVector p2; getAngles(ang1, ang2, reversed, p1, p2); double rad = dimArcPosition.getDistanceTo(center); RLine line; RVector dir; double len; double dist; // 1st extension line: dist = center.getDistanceTo2D(p1); len = rad - dist + dimexe; dir.setPolar(1.0, ang1); line = RLine(center + dir*dist + dir*dimexo, center + dir*dist + dir*len); ret.append(QSharedPointer<RShape>(new RLine(line))); // 2nd extension line: dist = center.getDistanceTo2D(p2); len = rad - dist + dimexe; dir.setPolar(1.0, ang2); line = RLine(center + dir*dist + dir*dimexo, center + dir*dist + dir*len); ret.append(QSharedPointer<RShape>(new RLine(line))); // Create dimension line (arc): RArc arc(center, rad, ang1, ang2, reversed); ret.append(QSharedPointer<RShape>(new RArc(arc))); // length of dimension arc: double distance = arc.getLength(); // do we have to put the arrows outside of the arc? bool outsideArrows = (distance<dimasz*2); // arrow angles: double arrowAngle1, arrowAngle2; double arrowAng; if (rad>1.0e-6) { arrowAng = getDimasz() / rad; } else { arrowAng = 0.0; } if (outsideArrows) { arrowAngle1 = arc.getDirection1(); arrowAngle2 = arc.getDirection2(); } else { RVector v1, v2; if (!arc.isReversed()) { v1.setPolar(rad, arc.getStartAngle()+arrowAng); } else { v1.setPolar(rad, arc.getStartAngle()-arrowAng); } v1+=arc.getCenter(); arrowAngle1 = arc.getStartPoint().getAngleTo(v1); if (!arc.isReversed()) { v2.setPolar(rad, arc.getEndAngle()-arrowAng); } else { v2.setPolar(rad, arc.getEndAngle()+arrowAng); } v2+=arc.getCenter(); arrowAngle2 = arc.getEndPoint().getAngleTo(v2); arrowAngle1 = arrowAngle1+M_PI; arrowAngle2 = arrowAngle2+M_PI; } // Arrows: //RTriangle arrow = RTriangle::createArrow(arc.getStartPoint(), arrowAngle1, dimasz); QList<QSharedPointer<RShape> > arrow = getArrow(arc.getStartPoint(), arrowAngle1); ret.append(arrow); //arrow = RTriangle::createArrow(arc.getEndPoint(), arrowAngle2, dimasz); arrow = getArrow(arc.getEndPoint(), arrowAngle2); ret.append(arrow); //ret.append(QSharedPointer<RShape>(new RTriangle(arrow))); //RVector oldMot = textPosition; //textPosition = RVector(0,0); //defaultAngle = 0.0; //dimLineLength = RNANDOUBLE; //getTextData(); //textPosition = oldMot; RVector textPos = arc.getMiddlePoint(); double dimAngle1 = textPos.getAngleTo(arc.getCenter())-M_PI/2.0; if (!autoTextPos) { dimAngle1 = textPositionCenter.getAngleTo(arc.getCenter())-M_PI/2.0; } RVector distV; double textAngle; // rotate text so it's readable from the bottom or right (ISO) // quadrant 1 & 4 if (dimAngle1>M_PI/2.0*3.0+0.001 || dimAngle1<M_PI/2.0+0.001) { distV.setPolar(dimgap + dimtxt/2, dimAngle1+M_PI/2.0); textAngle = dimAngle1; } // quadrant 2 & 3 else { distV.setPolar(dimgap + dimtxt/2, dimAngle1-M_PI/2.0); textAngle = dimAngle1+M_PI; } if (!autoTextPos) { textPos = textPositionCenter; } else { // move text away from dimension line: textPos+=distV; textPositionCenter = textPos; } defaultAngle = textAngle; //getTextData(); //textData.rotate(textAngle, RVector(0,0)); //textData.move(textPos); return ret; }
void REventHandler::drawSnapLabel(QPainter* painter, const RVector& pos, const RVector& posRestriction, const QString& text) { RVector p = graphicsView->mapToView(pos); RVector pr = RVector::invalid; if (posRestriction.isValid()) { pr = graphicsView->mapToView(posRestriction); } RColor color = RSettings::getColor("GraphicsViewColors/TextLabelColor", RColor(249,198,31)); painter->setPen(color); QFont font = RSettings::getSnapLabelFont(); font.setPointSizeF(font.pointSizeF()*graphicsView->getDevicePixelRatio()); QFontMetrics fm(font); painter->setFont(font); int offset = 5 * graphicsView->getDevicePixelRatio(); if (!text.isEmpty()) { painter->drawText( p.x + offset, p.y + offset, fm.width(text)+10, fm.height()+10, Qt::AlignHCenter | Qt::AlignVCenter, text, NULL); } painter->drawEllipse(p.x-offset, p.y-offset, offset*2, offset*2); // restriction position: if (pr.isSane()) { painter->drawLine(pr.x, pr.y-offset, pr.x+offset, pr.y); painter->drawLine(pr.x+offset, pr.y, pr.x, pr.y+offset); painter->drawLine(pr.x, pr.y+offset, pr.x-offset, pr.y); painter->drawLine(pr.x-offset, pr.y, pr.x, pr.y-offset); } // display distance/angle: int display = RSettings::getIntValue("DisplaySettings/DisplayDistanceAngle", 0); if (display == 0) { return; } RDocumentInterface* di = graphicsView->getDocumentInterface(); RDocument* doc = graphicsView->getDocument(); RVector relativeZero = di->getRelativeZero(); double dist, angle; if (posRestriction.isSane()) { dist = relativeZero.getDistanceTo(posRestriction); angle = relativeZero.getAngleTo(posRestriction); } else { dist = relativeZero.getDistanceTo(pos); angle = relativeZero.getAngleTo(pos); } int lp = doc->getLinearPrecision(); QString distStr = RUnit::doubleToString(dist, lp); angle = RMath::rad2deg(angle); int ap = doc->getAnglePrecision(); QString angStr = RUnit::doubleToString(angle, ap); QString sep = RSettings::getStringValue("Input/PolarCoordinateSeparator", "<"); color = RSettings::getColor("GraphicsViewColors/MeasurementToolsColor", RColor(155,220,112)); painter->setPen(color); QString displayText; switch (display) { case 0: displayText = ""; break; case 1: displayText = distStr + sep + angStr + QChar(0x00b0); break; case 2: displayText = distStr; break; case 3: displayText = angStr + QChar(0x00b0); break; default: displayText = ""; } if (!displayText.isEmpty()) { painter->drawText( p.x + offset, p.y - 3*offset - fm.height(), fm.width(displayText)+10, fm.height()+10, Qt::AlignHCenter | Qt::AlignVCenter, displayText, NULL); } }