📄 rs_creation.cpp
字号:
if (inside) { distance *= -1; } for (int num=1; num<=number; ++num) { // calculate parallel: bool ok = true; RS_Circle parallel1(NULL, e->getData()); parallel1.setRadius(e->getRadius() + distance*num); if (parallel1.getRadius()<0.0) { parallel1.setRadius(RS_MAXDOUBLE); ok = false; } // calculate 2nd parallel: //RS_Circle parallel2(NULL, e->getData()); //parallel2.setRadius(e->getRadius()+distance*num); //double dist1 = parallel1.getDistanceToPoint(coord); //double dist2 = parallel2.getDistanceToPoint(coord); //double minDist = min(dist1, dist2); //if (minDist<RS_MAXDOUBLE) { if (ok==true) { //if (dist1<dist2) { parallelData = parallel1.getData(); //} else { // parallelData = parallel2.getData(); //} if (document!=NULL && handleUndo) { document->startUndoCycle(); } RS_Circle* newCircle = new RS_Circle(container, parallelData); newCircle->setLayerToActive(); newCircle->setPenToActive(); if (ret==NULL) { ret = newCircle; } if (container!=NULL) { container->addEntity(newCircle); } if (document!=NULL && handleUndo) { document->addUndoable(newCircle); document->endUndoCycle(); } if (graphicView!=NULL) { graphicView->drawEntity(newCircle); } } } return ret;}/** * Creates a bisecting line of the angle between the entities * e1 and e2. Out of the 4 possible bisectors, the one closest to * the given coordinate is returned. * * @param coord Coordinate to define which bisector we want (typically a * mouse coordinate). * @param length Length of the bisecting line. * @param num Number of bisectors * @param l1 First line. * @param l2 Second line. * * @return Pointer to the first bisector created or NULL if no bisectors * were created. */RS_Line* RS_Creation::createBisector(const RS_Vector& coord1, const RS_Vector& coord2, double length, int num, RS_Line* l1, RS_Line* l2) { RS_VectorSolutions sol; // check given entities: if (l1==NULL || l2==NULL || l1->rtti()!=RS2::EntityLine || l2->rtti()!=RS2::EntityLine) { return NULL; } // intersection between entities: sol = RS_Information::getIntersection(l1, l2, false); RS_Vector inters = sol.get(0); if (inters.valid==false) { return NULL; } double angle1 = inters.angleTo(l1->getNearestPointOnEntity(coord1)); double angle2 = inters.angleTo(l2->getNearestPointOnEntity(coord2)); double angleDiff = RS_Math::getAngleDifference(angle1, angle2); if (angleDiff>M_PI) { angleDiff = angleDiff - 2*M_PI; } RS_Line* ret = NULL; if (document!=NULL && handleUndo) { document->startUndoCycle(); } for (int n=1; n<=num; ++n) { double angle = angle1 + (angleDiff / (num+1) * n); RS_LineData d; RS_Vector v; RS_Vector c; v.setPolar(length, angle); d = RS_LineData(inters, inters + v); RS_Line* newLine = new RS_Line(container, d); if (container!=NULL) { newLine->setLayerToActive(); newLine->setPenToActive(); container->addEntity(newLine); } if (document!=NULL && handleUndo) { document->addUndoable(newLine); } if (graphicView!=NULL) { graphicView->drawEntity(newLine); } if (ret==NULL) { ret = newLine; } } if (document!=NULL && handleUndo) { document->endUndoCycle(); } return ret;}/** * Creates a tangent between a given point and a circle or arc. * Out of the 2 possible tangents, the one closest to * the given coordinate is returned. * * @param coord Coordinate to define which tangent we want (typically a * mouse coordinate). * @param point Point. * @param circle Circle, arc or ellipse entity. */RS_Line* RS_Creation::createTangent1(const RS_Vector& coord, const RS_Vector& point, RS_Entity* circle) { RS_Line* ret = NULL; RS_Vector circleCenter; // check given entities: if (circle==NULL || !point.valid || (circle->rtti()!=RS2::EntityArc && circle->rtti()!=RS2::EntityCircle && circle->rtti()!=RS2::EntityEllipse)) { return NULL; } if (circle->rtti()==RS2::EntityCircle) { circleCenter = ((RS_Circle*)circle)->getCenter(); } else if (circle->rtti()==RS2::EntityArc) { circleCenter = ((RS_Arc*)circle)->getCenter(); } else if (circle->rtti()==RS2::EntityEllipse) { circleCenter = ((RS_Ellipse*)circle)->getCenter(); } // the two tangent points: RS_VectorSolutions sol; // calculate tangent points for arcs / circles: if (circle->rtti()!=RS2::EntityEllipse) { // create temp. thales circle: RS_Vector tCenter = (point + circleCenter)/2.0; double tRadius = point.distanceTo(tCenter); RS_Circle tmp(NULL, RS_CircleData(tCenter, tRadius)); // get the two intersection points which are the tangent points: sol = RS_Information::getIntersection(&tmp, circle, false); } // calculate tangent points for ellipses: else { RS_Ellipse* el = (RS_Ellipse*)circle; sol.alloc(2); //sol.set(0, circleCenter); //sol.set(1, circleCenter); double a = el->getMajorRadius(); // the length of the major axis / 2 double b = el->getMinorRadius(); // the length of the minor axis / 2 // rotate and move point: RS_Vector point2 = point; point2.move(-el->getCenter()); point2.rotate(-el->getAngle()); double xp = point2.x; // coordinates of the given point double yp = point2.y; double xt1; // Tangent point 1 double yt1; double xt2; // Tangent point 2 double yt2; double a2 = a * a; double b2 = b * b; double d = a2 / b2 * yp / xp; double e = a2 / xp; double af = b2 * d * d + a2; double bf = -b2 * d * e * 2.0; double cf = b2 * e * e - a2 * b2; double t = sqrt(bf * bf - af * cf * 4.0); yt1 = (t - bf) / (af * 2.0); xt1 = e - d * yt1; yt2 = (-t - bf) / (af * 2.0); xt2 = e - d * yt2; RS_Vector s1 = RS_Vector(xt1, yt1); RS_Vector s2 = RS_Vector(xt2, yt2); s1.rotate(el->getAngle()); s1.move(el->getCenter()); s2.rotate(el->getAngle()); s2.move(el->getCenter()); sol.set(0, s1); sol.set(1, s2); } if (!sol.get(0).valid || !sol.get(1).valid) { return NULL; } // create all possible tangents: RS_Line* poss[2]; RS_LineData d; d = RS_LineData(sol.get(0), point); poss[0] = new RS_Line(NULL, d); d = RS_LineData(sol.get(1), point); poss[1] = new RS_Line(NULL, d); // find closest tangent: double minDist = RS_MAXDOUBLE; double dist; int idx = -1; for (int i=0; i<2; ++i) { dist = poss[i]->getDistanceToPoint(coord); if (dist<minDist) { minDist = dist; idx = i; } } // create the closest tangent: if (idx!=-1) { RS_LineData d = poss[idx]->getData(); for (int i=0; i<2; ++i) { delete poss[i]; } if (document!=NULL && handleUndo) { document->startUndoCycle(); } ret = new RS_Line(container, d); ret->setLayerToActive(); ret->setPenToActive(); if (container!=NULL) { container->addEntity(ret); } if (document!=NULL && handleUndo) { document->addUndoable(ret); document->endUndoCycle(); } if (graphicView!=NULL) { graphicView->drawEntity(ret); } } else { ret = NULL; } return ret;}/** * Creates a tangent between two circles or arcs. * Out of the 4 possible tangents, the one closest to * the given coordinate is returned. * * @param coord Coordinate to define which tangent we want (typically a * mouse coordinate). * @param circle1 1st circle or arc entity. * @param circle2 2nd circle or arc entity. */RS_Line* RS_Creation::createTangent2(const RS_Vector& coord, RS_Entity* circle1, RS_Entity* circle2) { RS_Line* ret = NULL; RS_Vector circleCenter1; RS_Vector circleCenter2; double circleRadius1 = 0.0; double circleRadius2 = 0.0; // check given entities: if (circle1==NULL || circle2==NULL || (circle1->rtti()!=RS2::EntityArc && circle1->rtti()!=RS2::EntityCircle) || (circle2->rtti()!=RS2::EntityArc && circle2->rtti()!=RS2::EntityCircle) ) { return NULL; } if (circle1->rtti()==RS2::EntityCircle) { circleCenter1 = ((RS_Circle*)circle1)->getCenter(); circleRadius1 = ((RS_Circle*)circle1)->getRadius(); } else if (circle1->rtti()==RS2::EntityArc) { circleCenter1 = ((RS_Arc*)circle1)->getCenter(); circleRadius1 = ((RS_Arc*)circle1)->getRadius(); } if (circle2->rtti()==RS2::EntityCircle) { circleCenter2 = ((RS_Circle*)circle2)->getCenter(); circleRadius2 = ((RS_Circle*)circle2)->getRadius(); } else if (circle2->rtti()==RS2::EntityArc) { circleCenter2 = ((RS_Arc*)circle2)->getCenter(); circleRadius2 = ((RS_Arc*)circle2)->getRadius(); } // create all possible tangents: RS_Line* poss[4]; for (int i=0; i<4; ++i) { poss[i] = NULL; } RS_LineData d; double angle1 = circleCenter1.angleTo(circleCenter2); double dist1 = circleCenter1.distanceTo(circleCenter2); if (dist1>1.0e-6) { // outer tangents: double dist2 = circleRadius2 - circleRadius1; if (dist1>dist2) { double angle2 = asin(dist2/dist1); double angt1 = angle1 + angle2 + M_PI/2.0; double angt2 = angle1 - angle2 - M_PI/2.0; RS_Vector offs1; RS_Vector offs2; offs1.setPolar(circleRadius1, angt1); offs2.setPolar(circleRadius2, angt1); d = RS_LineData(circleCenter1 + offs1, circleCenter2 + offs2); poss[0] = new RS_Line(NULL, d); offs1.setPolar(circleRadius1, angt2); offs2.setPolar(circleRadius2, angt2); d = RS_LineData(circleCenter1 + offs1, circleCenter2 + offs2); poss[1] = new RS_Line(NULL, d); } // inner tangents: double dist3 = circleRadius2 + circleRadius1; if (dist1>dist3) { double angle3 = asin(dist3/dist1); double angt3 = angle1 + angle3 + M_PI/2.0; double angt4 = angle1 - angle3 - M_PI/2.0; RS_Vector offs1; RS_Vector offs2; offs1.setPolar(circleRadius1, angt3); offs2.setPolar(circleRadius2, angt3); d = RS_LineData(circleCenter1 - offs1, circleCenter2 + offs2); poss[2] = new RS_Line(NULL, d); offs1.setPolar(circleRadius1, angt4); offs2.setPolar(circleRadius2, angt4); d = RS_LineData(circleCenter1 - offs1, circleCenter2 + offs2); poss[3] = new RS_Line(NULL, d); } } // find closest tangent: double minDist = RS_MAXDOUBLE; double dist; int idx = -1; for (int i=0; i<4; ++i) { if (poss[i]!=NULL) { dist = poss[i]->getDistanceToPoint(coord); if (dist<minDist) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -