/** switch x,y for all vectors */ RS_VectorSolutions RS_VectorSolutions::flipXY(void) const { RS_VectorSolutions ret; for(const auto& vp: vector) ret.push_back(vp.flipXY()); return ret; }
/** switch x,y for all vectors */ RS_VectorSolutions RS_VectorSolutions::flipXY(void) const { RS_VectorSolutions ret; const int counts=vector.size(); for(int i=0;i<counts;i++) ret.push_back(vector[i].flipXY()); return ret; }
RS_Vector RS_Line::prepareTrim(const RS_Vector& trimCoord, const RS_VectorSolutions& trimSol) { //prepare trimming for multiple intersections if ( ! trimSol.hasValid()) return(RS_Vector(false)); if ( trimSol.getNumber() == 1 ) return(trimSol.get(0)); return trimSol.getClosest(trimCoord,NULL,0); }
void RS_ActionInfoAngle::trigger() { RS_DEBUG->print("RS_ActionInfoAngle::trigger()"); if (entity1!=NULL && entity2!=NULL) { RS_VectorSolutions sol = RS_Information::getIntersection(entity1, entity2, false); if (sol.hasValid()) { intersection = sol.get(0); if (intersection.valid && point1.valid && point2.valid) { double angle1 = intersection.angleTo(point1); double angle2 = intersection.angleTo(point2); double angle = RS_Math::rad2deg(remainder(angle2-angle1,2.*M_PI)); QString str; str.setNum(angle); str += QChar(0xB0); if(angle<0.) { QString str2; str2.setNum(angle+360.); //positive value str += QString(" or %1%2").arg(str2).arg(QChar(0xB0)); } RS_DIALOGFACTORY->commandMessage(tr("Angle: %1").arg(str)); } } else { RS_DIALOGFACTORY->commandMessage(tr("Lines are parallel")); } } }
void RS_ActionInfoAngle::trigger() { RS_DEBUG->print("RS_ActionInfoAngle::trigger()"); if (entity1!=NULL && entity2!=NULL) { RS_VectorSolutions sol = RS_Information::getIntersection(entity1, entity2, false); if (sol.hasValid()) { intersection = sol.get(0); if (intersection.valid && point1.valid && point2.valid) { double angle1 = intersection.angleTo(point1); double angle2 = intersection.angleTo(point2); double angle = fabs(angle2-angle1); QString str; str.sprintf("%.6f", RS_Math::rad2deg(angle)); RS_DIALOGFACTORY->commandMessage(tr("Angle: %1%2") .arg(str).arg(QChar(0xB0))); } } else { RS_DIALOGFACTORY->commandMessage(tr("Lines are parallel")); } } }
void RS_ActionInfoAngle::trigger() { RS_DEBUG->print("RS_ActionInfoAngle::trigger()"); if (entity1 && entity2) { RS_VectorSolutions sol = RS_Information::getIntersection(entity1, entity2, false); if (sol.hasValid()) { intersection = sol.get(0); if (intersection.valid && point1.valid && point2.valid) { double angle1 = intersection.angleTo(point1); double angle2 = intersection.angleTo(point2); double angle = remainder(angle2-angle1,2.*M_PI); QString str = RS_Units::formatAngle(angle, graphic->getAngleFormat(), graphic->getAnglePrecision()); if(angle<0.){ str += " or "; str += RS_Units::formatAngle(angle + 2.*M_PI, graphic->getAngleFormat(), graphic->getAnglePrecision()); } RS_DIALOGFACTORY->commandMessage(tr("Angle: %1").arg(str)); } } else { RS_DIALOGFACTORY->commandMessage(tr("Lines are parallel")); } } }
/** *find the tangential points from a given point, i.e., the tangent lines should pass * the given point and tangential points * *Author: Dongxu Li */ RS_VectorSolutions RS_Circle::getTangentPoint(const RS_Vector& point) const { RS_VectorSolutions ret; double r2(getRadius()*getRadius()); if(r2<RS_TOLERANCE*RS_TOLERANCE) return ret; //circle too small RS_Vector vp(point-getCenter()); double c2(vp.squared()); if(c2<r2-getRadius()*2.*RS_TOLERANCE) { //inside point, no tangential point return ret; } if(c2>r2+getRadius()*2.*RS_TOLERANCE) { //external point RS_Vector vp1(-vp.y,vp.x); vp1*=getRadius()*sqrt(c2-r2)/c2; vp *= r2/c2; vp += getCenter(); if(vp1.squared()>RS_TOLERANCE*RS_TOLERANCE) { ret.push_back(vp+vp1); ret.push_back(vp-vp1); return ret; } } ret.push_back(point); return ret; }
void RS_Image::draw(RS_Painter* painter, RS_GraphicView* view, double& /*patternOffset*/) { if (!(painter && view) || !img.get() || img->isNull()) return; // erase image: //if (painter->getPen().getColor()==view->getBackground()) { // RS_VectorSolutions sol = getCorners(); // //} RS_Vector scale{view->toGuiDX(data.uVector.magnitude()), view->toGuiDY(data.vVector.magnitude())}; double angle = data.uVector.angle(); painter->drawImg(*img, view->toGui(data.insertionPoint), angle, scale); if (isSelected()) { RS_VectorSolutions sol = getCorners(); for (size_t i = 0; i < sol.size(); ++i){ size_t const j = (i+1)%sol.size(); painter->drawLine(view->toGui(sol.get(i)), view->toGui(sol.get(j))); } } }
/** * @return One or two intersection points between given entities. */ RS_VectorSolutions RS_Information::getIntersectionArcArc(RS_Entity const* e1, RS_Entity const* e2) { RS_VectorSolutions ret; if (!(e1 && e2)) return ret; if(e1->rtti() != RS2::EntityArc && e1->rtti() != RS2::EntityCircle) return ret; if(e2->rtti() != RS2::EntityArc && e2->rtti() != RS2::EntityCircle) return ret; RS_Vector c1 = e1->getCenter(); RS_Vector c2 = e2->getCenter(); double r1 = e1->getRadius(); double r2 = e2->getRadius(); RS_Vector u = c2 - c1; // concentric if (u.magnitude()<1.0e-6) { return ret; } RS_Vector v = RS_Vector(u.y, -u.x); double s, t1, t2, term; s = 1.0/2.0 * ((r1*r1 - r2*r2)/(RS_Math::pow(u.magnitude(), 2.0)) + 1.0); term = (r1*r1)/(RS_Math::pow(u.magnitude(), 2.0)) - s*s; // no intersection: if (term<0.0) { ret = RS_VectorSolutions(); } // one or two intersections: else { t1 = sqrt(term); t2 = -sqrt(term); bool tangent = false; RS_Vector sol1 = c1 + u*s + v*t1; RS_Vector sol2 = c1 + u*s + v*t2; if (sol1.distanceTo(sol2)<1.0e-4) { sol2 = RS_Vector(false); ret = RS_VectorSolutions({sol1}); tangent = true; } else { ret = RS_VectorSolutions({sol1, sol2}); } ret.setTangent(tangent); } return ret; }
double RS_Image::getDistanceToPoint(const RS_Vector& coord, RS_Entity** entity, RS2::ResolveLevel /*level*/, double /*solidDist*/) const{ if (entity) { *entity = const_cast<RS_Image*>(this); } RS_VectorSolutions corners = getCorners(); //allow selecting image by clicking within images, bug#3464626 if(containsPoint(coord)){ //if coord is on image RS_SETTINGS->beginGroup("/Appearance"); bool draftMode = (bool)RS_SETTINGS->readNumEntry("/DraftMode", 0); RS_SETTINGS->endGroup(); if(!draftMode) return double(0.); } //continue to allow selecting by image edges double minDist = RS_MAXDOUBLE; for (size_t i = 0; i < corners.size(); ++i){ size_t const j = (i+1)%corners.size(); RS_Line const l{corners.get(i), corners.get(j)}; double const dist = l.getDistanceToPoint(coord, nullptr); minDist = std::min(minDist, dist); } return minDist; }
RS_Vector RS_Image::getNearestPointOnEntity(const RS_Vector& coord, bool onEntity, double* dist, RS_Entity** entity) const{ if (entity!=NULL) { *entity = const_cast<RS_Image*>(this); } RS_VectorSolutions corners =getCorners(); //allow selecting image by clicking within images, bug#3464626 if(containsPoint(coord)){ //if coord is within image if(dist!=NULL) *dist=0.; return coord; } RS_VectorSolutions points(4); RS_Line l[] = { RS_Line(NULL, RS_LineData(corners.get(0), corners.get(1))), RS_Line(NULL, RS_LineData(corners.get(1), corners.get(2))), RS_Line(NULL, RS_LineData(corners.get(2), corners.get(3))), RS_Line(NULL, RS_LineData(corners.get(3), corners.get(0))) }; for (int i=0; i<4; ++i) { points.set(i, l[i].getNearestPointOnEntity(coord, onEntity)); } return points.getClosest(coord, dist); }
/** //create Ellipse with axes in x-/y- directions from 4 points * * *@Author Dongxu Li */ bool RS_Ellipse::createFrom4P(const RS_VectorSolutions& sol) { if (sol.getNumber() != 4 ) return (false); //only do 4 points QVector<QVector<double> > mt; QVector<double> dn; int mSize(4); mt.resize(mSize); for(int i=0;i<mSize;i++) {//form the linear equation, c0 x^2 + c1 x + c2 y^2 + c3 y = 1 mt[i].resize(mSize+1); mt[i][0]=sol.get(i).x * sol.get(i).x; mt[i][1]=sol.get(i).x ; mt[i][2]=sol.get(i).y * sol.get(i).y; mt[i][3]=sol.get(i).y ; mt[i][4]=1.; } if ( ! RS_Math::linearSolver(mt,dn)) return false; double d(1.+0.25*(dn[1]*dn[1]/dn[0]+dn[3]*dn[3]/dn[2])); if(fabs(dn[0])<RS_TOLERANCE*RS_TOLERANCE ||fabs(dn[2])<RS_TOLERANCE*RS_TOLERANCE ||d/dn[0]<RS_TOLERANCE*RS_TOLERANCE ||d/dn[2]<RS_TOLERANCE*RS_TOLERANCE ) { //ellipse not defined return false; } data.center.set(-0.5*dn[1]/dn[0],-0.5*dn[3]/dn[2]); // center d=sqrt(d/dn[0]); data.majorP.set(d,0.); data.ratio=sqrt(dn[0]/dn[2]); data.angle1=0.; data.angle2=0.; return true; }
void RS_Image::draw(RS_Painter* painter, RS_GraphicView* view, double& /*patternOffset*/) { if (painter==NULL || view==NULL || !img.get() || img->isNull()) { return; } // erase image: //if (painter->getPen().getColor()==view->getBackground()) { // RS_VectorSolutions sol = getCorners(); // //} RS_Vector scale = RS_Vector(view->toGuiDX(data.uVector.magnitude()), view->toGuiDY(data.vVector.magnitude())); double angle = data.uVector.angle(); painter->drawImg(*img, view->toGui(data.insertionPoint), angle, scale); if (isSelected()) { RS_VectorSolutions sol = getCorners(); painter->drawLine(view->toGui(sol.get(0)), view->toGui(sol.get(1))); painter->drawLine(view->toGui(sol.get(1)), view->toGui(sol.get(2))); painter->drawLine(view->toGui(sol.get(2)), view->toGui(sol.get(3))); painter->drawLine(view->toGui(sol.get(3)), view->toGui(sol.get(0))); } }
/** * Selects all entities within the given area. * * @param select True to select, False to deselect the entities. */ void RS_EntityContainer::selectWindow(RS_Vector v1, RS_Vector v2, bool select, bool cross) { bool included; for (RS_Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) { included = false; if (e->isVisible()) { if (e->isInWindow(v1, v2)) { //e->setSelected(select); included = true; } else if (cross==true) { RS_Line l[] = { RS_Line(NULL, RS_LineData(v1, RS_Vector(v2.x, v1.y))), RS_Line(NULL, RS_LineData(RS_Vector(v2.x, v1.y), v2)), RS_Line(NULL, RS_LineData(v2, RS_Vector(v1.x, v2.y))), RS_Line(NULL, RS_LineData(RS_Vector(v1.x, v2.y), v1)) }; RS_VectorSolutions sol; if (e->isContainer()) { RS_EntityContainer* ec = (RS_EntityContainer*)e; for (RS_Entity* se=ec->firstEntity(RS2::ResolveAll); se!=NULL && included==false; se=ec->nextEntity(RS2::ResolveAll)) { for (int i=0; i<4; ++i) { sol = RS_Information::getIntersection( se, &l[i], true); if (sol.hasValid()) { included = true; break; } } } } else { for (int i=0; i<4; ++i) { sol = RS_Information::getIntersection(e, &l[i], true); if (sol.hasValid()) { included = true; break; } } } } } if (included) { e->setSelected(select); } } }
/** * @return Center of the measured dimension. */ RS_Vector RS_DimAngular::getCenter() { RS_ConstructionLine l1(NULL, RS_ConstructionLineData(edata.definitionPoint1, edata.definitionPoint2)); RS_ConstructionLine l2(NULL, RS_ConstructionLineData(edata.definitionPoint3, data.definitionPoint)); RS_VectorSolutions vs = RS_Information::getIntersection(&l1, &l2, false); return vs.get(0); }
/** * Selects all entities within the given area. * * @param select True to select, False to deselect the entities. */ void RS_EntityContainer::selectWindow(RS_Vector v1, RS_Vector v2, bool select, bool cross) { bool included; for(auto e: entities){ included = false; if (e->isVisible()) { if (e->isInWindow(v1, v2)) { //e->setSelected(select); included = true; } else if (cross) { RS_EntityContainer l; l.addRectangle(v1, v2); RS_VectorSolutions sol; if (e->isContainer()) { RS_EntityContainer* ec = (RS_EntityContainer*)e; for (RS_Entity* se=ec->firstEntity(RS2::ResolveAll); se && included==false; se=ec->nextEntity(RS2::ResolveAll)) { if (se->rtti() == RS2::EntitySolid){ included = static_cast<RS_Solid*>(se)->isInCrossWindow(v1,v2); } else { for (auto line: l) { sol = RS_Information::getIntersection( se, line, true); if (sol.hasValid()) { included = true; break; } } } } } else if (e->rtti() == RS2::EntitySolid){ included = static_cast<RS_Solid*>(e)->isInCrossWindow(v1,v2); } else { for (auto line: l) { sol = RS_Information::getIntersection(e, line, true); if (sol.hasValid()) { included = true; break; } } } } } if (included) { e->setSelected(select); } } }
RS_VectorSolutions RS_Ellipse::getRefPoints() { RS_VectorSolutions ret; if(isArc()){ //no start/end point for whole ellipse ret.push_back(getStartpoint()); ret.push_back(getEndpoint()); } ret.push_back(data.center); ret.appendTo(getFoci()); return ret; }
/** * Selects all entities that are intersected by the given line. * * @param v1 Startpoint of line. * @param v2 Endpoint of line. * @param select true: select, false: deselect */ void RS_Selection::selectIntersected(const RS_Vector& v1, const RS_Vector& v2, bool select) { RS_Line line(NULL, RS_LineData(v1, v2)); bool inters; for (RS_Entity* e=container->firstEntity(); e!=NULL; e=container->nextEntity()) { //for (uint i=0; i<container->count(); ++i) { //RS_Entity* e = container->entityAt(i); if (e!=NULL && e->isVisible()) { inters = false; // select containers / groups: if (e->isContainer()) { RS_EntityContainer* ec = (RS_EntityContainer*)e; for (RS_Entity* e2=ec->firstEntity(RS2::ResolveAll); e2!=NULL; e2=ec->nextEntity(RS2::ResolveAll)) { RS_VectorSolutions sol = RS_Information::getIntersection(&line, e2, true); if (sol.hasValid()) { inters = true; } } } else { RS_VectorSolutions sol = RS_Information::getIntersection(&line, e, true); if (sol.hasValid()) { inters = true; } } if (inters) { if (graphicView!=NULL) { graphicView->deleteEntity(e); } e->setSelected(select); if (graphicView!=NULL) { graphicView->drawEntity(e); } } } } }
/** * 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 nullptr 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 && l2)) return nullptr; if(! (l1->rtti()==RS2::EntityLine && l1->rtti()==RS2::EntityLine)) return nullptr; // intersection between entities: sol = RS_Information::getIntersection(l1, l2, false); RS_Vector inters = sol.get(0); if (inters.valid==false) { return nullptr; } 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 = nullptr; if (document && handleUndo) { document->startUndoCycle(); } for (int n=1; n<=num; ++n) { double angle = angle1 + (angleDiff / (num+1) * n); RS_LineData d; RS_Vector v; v.setPolar(length, angle); d = RS_LineData(inters, inters + v); RS_Line* newLine = new RS_Line(container, d); if (ret==nullptr) { ret = newLine; } setEntity(newLine); } if (document && handleUndo) { document->endUndoCycle(); } return ret; }
void RS_Image::calculateBorders() { RS_VectorSolutions sol = getCorners(); minV = RS_Vector::minimum( RS_Vector::minimum(sol.get(0), sol.get(1)), RS_Vector::minimum(sol.get(2), sol.get(3)) ); maxV = RS_Vector::maximum( RS_Vector::maximum(sol.get(0), sol.get(1)), RS_Vector::maximum(sol.get(2), sol.get(3)) ); }
/** * Creates this arc from 3 given points which define the arc line. * * @param p1 1st point. * @param p2 2nd point. * @param p3 3rd point. */ bool RS_Arc::createFrom3P(const RS_Vector& p1, const RS_Vector& p2, const RS_Vector& p3) { if (p1.distanceTo(p2)>RS_TOLERANCE && p2.distanceTo(p3)>RS_TOLERANCE && p3.distanceTo(p1)>RS_TOLERANCE) { // middle points between 3 points: RS_Vector mp1, mp2; RS_Vector dir1, dir2; double a1, a2; // intersection of two middle lines mp1 = (p1 + p2)/2.0; a1 = p1.angleTo(p2) + M_PI/2.0; dir1.setPolar(100.0, a1); mp2 = (p2 + p3)/2.0; a2 = p2.angleTo(p3) + M_PI/2.0; dir2.setPolar(100.0, a2); RS_ConstructionLineData d1(mp1, mp1 + dir1); RS_ConstructionLineData d2(mp2, mp2 + dir2); RS_ConstructionLine midLine1(NULL, d1); RS_ConstructionLine midLine2(NULL, d2); RS_VectorSolutions sol = RS_Information::getIntersection(&midLine1, &midLine2); data.center = sol.get(0); data.radius = data.center.distanceTo(p3); data.angle1 = data.center.angleTo(p1); data.angle2 = data.center.angleTo(p3); data.reversed = RS_Math::isAngleBetween(data.center.angleTo(p2), data.angle1, data.angle2, true); if (sol.get(0).valid && data.radius<1.0e14 && data.radius>RS_TOLERANCE) { calculateEndpoints(); calculateBorders(); return true; } else { RS_DEBUG->print("RS_Arc::createFrom3P(): " "Cannot create an arc with inf radius."); return false; } } else { RS_DEBUG->print("RS_Arc::createFrom3P(): " "Cannot create an arc with radius 0.0."); return false; } }
RS_Vector RS_Image::getNearestDist(double distance, const RS_Vector& coord, double* dist) const{ RS_VectorSolutions const& corners = getCorners(); RS_VectorSolutions points; for (size_t i = 0; i < corners.size(); ++i){ size_t const j = (i+1)%corners.size(); RS_Line const l{corners.get(i), corners.get(j)}; RS_Vector const& vp = l.getNearestDist(distance, coord, dist); points.push_back(vp); } return points.getClosest(coord, dist); }
void RS_ActionSnapIntersectionManual::mouseMoveEvent(QMouseEvent* e) { RS_DEBUG->print("RS_ActionSnapIntersectionManual::mouseMoveEvent begin"); RS_Entity* se = catchEntity(e); RS_Vector mouse = graphicView->toGraph(e->x(), e->y()); switch (getStatus()) { case ChooseEntity1: entity1 = se; break; case ChooseEntity2: { entity2 = se; coord = mouse; RS_VectorSolutions sol = RS_Information::getIntersection(entity1, entity2, false); //for (int i=0; i<sol.getNumber(); i++) { // ip = sol.get(i); // break; //} RS_Vector ip = sol.getClosest(coord); if (ip.valid) { deletePreview(); preview->addEntity( new RS_Circle(preview.get(), RS_CircleData( ip, graphicView->toGraphDX(4)))); drawPreview(); RS_DIALOGFACTORY->updateCoordinateWidget(ip, ip - graphicView->getRelativeZero()); } } break; default: break; } RS_DEBUG->print("RS_ActionSnapIntersectionManual::mouseMoveEvent end"); }
void RS_Circle::moveRef(const RS_Vector& ref, const RS_Vector& offset) { if(ref.distanceTo(data.center)<1.0e-4){ data.center += offset; return; } RS_Vector v1(data.radius, 0.0); RS_VectorSolutions sol; sol.push_back(data.center + v1); sol.push_back(data.center - v1); v1.set(0., data.radius); sol.push_back(data.center + v1); sol.push_back(data.center - v1); double dist; v1=sol.getClosest(ref,&dist); if(dist>1.0e-4) return; data.radius = data.center.distanceTo(v1 + offset); }
RS_VectorSolutions RS_Polyline::getRefPoints() { RS_VectorSolutions ret; ret.push_back(data.startpoint); for (RS_Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e = nextEntity(RS2::ResolveNone)) { if (e->isAtomic()) { ret.push_back(((RS_AtomicEntity*)e)->getEndpoint()); } } ret.push_back( data.endpoint); return ret; }
/** *find the tangential points from a given point, i.e., the tangent lines should pass * the given point and tangential points * *Author: Dongxu Li */ RS_VectorSolutions RS_Ellipse::getTangentPoint(const RS_Vector& point) const { RS_Vector point2(point); point2.move(-getCenter()); RS_Vector aV(-getAngle()); point2.rotate(aV); RS_VectorSolutions sol; double a=getMajorRadius(); if(a<RS_TOLERANCE || getRatio()<RS_TOLERANCE) return sol; RS_Circle c(NULL, RS_CircleData(RS_Vector(0.,0.),a)); point2.y /=getRatio(); sol=c.getTangentPoint(point2); sol.scale(RS_Vector(1.,getRatio())); aV.y *= -1.; sol.rotate(aV); sol.move(getCenter()); return sol; }
RS_Vector RS_Line::prepareTrim(const RS_Vector& trimCoord, const RS_VectorSolutions& trimSol) { //prepare trimming for multiple intersections if ( ! trimSol.hasValid()) return(RS_Vector(false)); if ( trimSol.getNumber() == 1 ) return(trimSol.get(0)); auto&& vp0=trimSol.getClosest(trimCoord,NULL,0); double dr2=trimCoord.squaredTo(vp0); //the trim point found is closer to mouse location (trimCoord) than both end points, return this trim point if(dr2 < trimCoord.squaredTo(getStartpoint()) && dr2 < trimCoord.squaredTo(getEndpoint())) return vp0; //the closer endpoint to trimCoord RS_Vector vp1=(trimCoord.squaredTo(getStartpoint()) <= trimCoord.squaredTo(getEndpoint()))?getStartpoint():getEndpoint(); //searching for intersection in the direction of the closer end point auto&& dvp1=vp1 - trimCoord; RS_VectorSolutions sol1; for(size_t i=0; i<trimSol.size(); i++){ auto&& dvp2=trimSol.at(i) - trimCoord; if( RS_Vector::dotP(dvp1, dvp2) > RS_TOLERANCE) sol1.push_back(trimSol.at(i)); } //if found intersection in direction, return the closest to trimCoord from it if(sol1.size()) return sol1.getClosest(trimCoord,NULL,0); //no intersection by direction, return previously found closest intersection return vp0; }
/** //create Ellipse with center and 3 points * * *@Author Dongxu Li */ bool RS_Ellipse::createFromCenter3Points(const RS_VectorSolutions& sol) { if(sol.getNumber()<3) return false; //need one center and 3 points on ellipse QVector<QVector<double> > mt; int mSize(sol.getNumber() -1); if( (sol.get(mSize) - sol.get(mSize-1)).squared() < RS_TOLERANCE*RS_TOLERANCE ) { //remove the last point mSize--; } mt.resize(mSize); QVector<double> dn(mSize); switch(mSize){ case 2: for(int i=0;i<mSize;i++){//form the linear equation mt[i].resize(mSize+1); RS_Vector vp(sol.get(i+1)-sol.get(0)); //the first vector is center mt[i][0]=vp.x*vp.x; mt[i][1]=vp.y*vp.y; mt[i][2]=1.; } if ( ! RS_Math::linearSolver(mt,dn) ) return false; if( dn[0]<RS_TOLERANCE*RS_TOLERANCE || dn[1]<RS_TOLERANCE*RS_TOLERANCE) return false; setMajorP(RS_Vector(1./sqrt(dn[0]),0.)); setRatio(sqrt(dn[0]/dn[1])); setAngle1(0.); setAngle2(0.); setCenter(sol.get(0)); return true; break; case 3: for(int i=0;i<mSize;i++){//form the linear equation mt[i].resize(mSize+1); RS_Vector vp(sol.get(i+1)-sol.get(0)); //the first vector is center mt[i][0]=vp.x*vp.x; mt[i][1]=vp.x*vp.y; mt[i][2]=vp.y*vp.y; mt[i][3]=1.; } if ( ! RS_Math::linearSolver(mt,dn) ) return false; setCenter(sol.get(0)); return createFromQuadratic(dn); default: return false; } }
/** * @return The intersection which is closest to 'coord' */ RS_Vector RS_EntityContainer::getNearestIntersection(const RS_Vector& coord, double* dist) { double minDist = RS_MAXDOUBLE; // minimum measured distance double curDist; // currently measured distance RS_Vector closestPoint(false); // closest found endpoint RS_Vector point; // endpoint found RS_VectorSolutions sol; RS_Entity* closestEntity; closestEntity = getNearestEntity(coord, NULL, RS2::ResolveAll); if (closestEntity!=NULL) { for (RS_Entity* en = firstEntity(RS2::ResolveAll); en != NULL; en = nextEntity(RS2::ResolveAll)) { if (en->isVisible() && en!=closestEntity) { sol = RS_Information::getIntersection(closestEntity, en, true); for (int i=0; i<4; i++) { point = sol.get(i); if (point.valid) { curDist = coord.distanceTo(point); if (curDist<minDist) { closestPoint = point; minDist = curDist; if (dist!=NULL) { *dist = curDist; } } } } } } //} } return closestPoint; }
RS_Vector RS_Image::getNearestCenter(const RS_Vector& coord, double* dist) const{ RS_VectorSolutions const& corners{getCorners()}; //bug#485, there's no clear reason to ignore snapping to center within an image // if(containsPoint(coord)){ // //if coord is within image // if(dist) *dist=0.; // return coord; // } RS_VectorSolutions points; for (size_t i=0; i < corners.size(); ++i) { size_t const j = (i+1)%corners.size(); points.push_back((corners.get(i) + corners.get(j))*0.5); } points.push_back((corners.get(0) + corners.get(2))*0.5); return points.getClosest(coord, dist); }