Example #1
0
/** @return the nearest of equidistant middle points of the line. */
RS_Vector RS_Line::getNearestMiddle(const RS_Vector& coord,
                                        double* dist,
                                        int middlePoints
                                        )const 
{
//        RS_DEBUG->print("RS_Line::getNearestMiddle(): begin\n");
        RS_Vector dvp(getEndpoint() - getStartpoint());
        double l=dvp.magnitude();
        if( l<= RS_TOLERANCE) {
            //line too short
            return const_cast<RS_Line*>(this)->getNearestCenter(coord, dist);   /* ?????? */
        }
        RS_Vector vp0(getNearestPointOnEntity(coord,true,dist));
        int counts=middlePoints+1;
        int i( static_cast<int>(vp0.distanceTo(getStartpoint())/l*counts+0.5));
        if(!i) i++; // remove end points
        if(i==counts) i--;
        vp0=getStartpoint() + dvp*(double(i)/double(counts));

        if(dist != NULL) {
            *dist=vp0.distanceTo(coord);
        }
   
   //std::cout << "rs_line.cpp Dist " << *dist << "\n";
   
   
//        RS_DEBUG->print("RS_Line::getNearestMiddle(): end\n");
        return vp0;
}
Example #2
0
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;
}
Example #3
0
    /** @return the nearest of equidistant middle points of the line. */
    RS_Vector RS_Line::getNearestMiddle(const RS_Vector& coord,
                                        double* dist,
                                        int middlePoints
                                        ) {
        RS_DEBUG->print("RS_Line::getNearestMiddle(): begin\n");
        RS_Vector dvp(getEndpoint() - getStartpoint());
        double l=dvp.magnitude();
        if( l<= RS_TOLERANCE) {
            //line too short
            RS_Vector vp(getStartpoint() + dvp*0.5);
            if (dist != NULL) {
                *dist=vp.distanceTo(coord);
            }
            return vp;
        }
        RS_Vector vp0(getNearestPointOnEntity(coord,true,dist));
        int counts=middlePoints+1;
        int i( static_cast<int>(vp0.distanceTo(getStartpoint())/l*counts+0.5));
        if(!i) i++; // remove end points
        if(i==counts) i--;
        vp0=getStartpoint() + dvp*(double(i)/double(counts));

        if(dist != NULL) {
            *dist=vp0.distanceTo(coord);
        }
        RS_DEBUG->print("RS_Line::getNearestMiddle(): end\n");
        return vp0;
    }
Example #4
0
/**
 * Stretches the given range of the entity by the given offset.
 */
void RS_Line::stretch(RS_Vector firstCorner,
                      RS_Vector secondCorner,
                      RS_Vector offset) {

    if (getStartpoint().isInWindow(firstCorner,
                                   secondCorner)) {
        moveStartpoint(getStartpoint() + offset);
    }
    if (getEndpoint().isInWindow(firstCorner,
                                 secondCorner)) {
        moveEndpoint(getEndpoint() + offset);
    }
}
Example #5
0
/**
 * Stretches the given range of the entity by the given offset.
 */
void RS_Line::stretch(const RS_Vector& firstCorner,
                      const RS_Vector& secondCorner,
                      const RS_Vector& offset) {

    RS_Vector vLow( std::min(firstCorner.x, secondCorner.x), std::min(firstCorner.y, secondCorner.y));
    RS_Vector vHigh( std::max(firstCorner.x, secondCorner.x), std::max(firstCorner.y, secondCorner.y));

    if (getStartpoint().isInWindowOrdered(vLow, vHigh)) {
        moveStartpoint(getStartpoint() + offset);
    }
    if (getEndpoint().isInWindowOrdered(vLow, vHigh)) {
        moveEndpoint(getEndpoint() + offset);
    }
}
Example #6
0
/**
  * this function creates offset
  *@coord, position indicates the direction of offset
  *@distance, distance of offset
  * return true, if success, otherwise, false
  *
  *Author: Dongxu Li
  */
bool RS_Line::offset(const RS_Vector& coord, const double& distance) {
	RS_Vector direction{getEndpoint()-getStartpoint()};
    double ds(direction.magnitude());
    if(ds< RS_TOLERANCE) return false;
    direction /= ds;
    RS_Vector vp(coord-getStartpoint());
//    RS_Vector vp1(getStartpoint() + direction*(RS_Vector::dotP(direction,vp))); //projection
    direction.set(-direction.y,direction.x); //rotate pi/2
    if(RS_Vector::dotP(direction,vp)<0.) {
        direction *= -1.;
    }
    direction*=distance;
    move(direction);
    return true;
}
Example #7
0
double RS_Arc::getDistanceToPoint(const RS_Vector& coord,
                                  RS_Entity** entity,
                                  RS2::ResolveLevel,
                                  double) {
    if (entity!=NULL) {
        *entity = this;
    }

    // check endpoints first:
    double dist = coord.distanceTo(getStartpoint());
    if (dist<1.0e-4) {
        return dist;
    }
    dist = coord.distanceTo(getEndpoint());
    if (dist<1.0e-4) {
        return dist;
    }

    if (RS_Math::isAngleBetween(data.center.angleTo(coord),
                                data.angle1, data.angle2,
                                isReversed())) {

        return fabs((coord-data.center).magnitude() - data.radius);
    } else {
        return RS_MAXDOUBLE;
    }
}
Example #8
0
RS_Vector RS_Spline::getNearestEndpoint(const RS_Vector& coord,
                                        double* dist)const {
    double minDist = RS_MAXDOUBLE;
    RS_Vector ret(false);
    if(! data.closed) { // no endpoint for closed spline
       RS_Vector vp1(getStartpoint());
       RS_Vector vp2(getEndpoint());
       double d1( (coord-vp1).squared());
       double d2( (coord-vp2).squared());
       if( d1<d2){
           ret=vp1;
           minDist=sqrt(d1);
       }else{
           ret=vp2;
           minDist=sqrt(d2);
       }
//        for (int i=0; i<data.controlPoints.count(); i++) {
//            d = (data.controlPoints.at(i)).distanceTo(coord);

//            if (d<minDist) {
//                minDist = d;
//                ret = data.controlPoints.at(i);
//            }
//        }
    }
	if (dist!=nullptr) {
        *dist = minDist;
    }
    return ret;
}
Example #9
0
/* Dongxu Li's Version, 19 Aug 2011
 * scale an ellipse
 * Find the eigen vactors and eigen values by optimization
 * original ellipse equation,
 * x= a cos t
 * y= b sin t
 * rotated by angle,
 *
 * x = a cos t cos (angle) - b sin t sin(angle)
 * y = a cos t sin (angle) + b sin t cos(angle)
 * scaled by ( kx, ky),
 * x *= kx
 * y *= ky
 * find the maximum and minimum of x^2 + y^2,
 */
void RS_Ellipse::scale(RS_Vector center, RS_Vector factor) {
    data.center.scale(center, factor);
    RS_Vector vpStart=getStartpoint().scale(getCenter(),factor);
    RS_Vector vpEnd=getEndpoint().scale(getCenter(),factor);;
    double ct=cos(getAngle());
    double ct2 = ct*ct; // cos^2 angle
    double st=sin(getAngle());
    double st2=1.0 - ct2; // sin^2 angle
    double kx2= factor.x * factor.x;
    double ky2= factor.y * factor.y;
    double a=getMajorRadius();
    double b=getMinorRadius();
    double cA=0.5*a*a*(kx2*ct2+ky2*st2);
    double cB=0.5*b*b*(kx2*st2+ky2*ct2);
    double cC=a*b*ct*st*(ky2-kx2);
    RS_Vector vp(cA-cB,cC);
    setMajorP(RS_Vector(a,b).scale(RS_Vector(vp.angle())).rotate(RS_Vector(ct,st)).scale(factor));
    a=cA+cB;
    b=vp.magnitude();
    setRatio( sqrt((a - b)/(a + b) ));
    if(   std::isnormal(getAngle1()) || std::isnormal(getAngle2() ) )  {
        //only reset start/end points for ellipse arcs, i.e., angle1 angle2 are not both zero
        setAngle1(getEllipseAngle(vpStart));
        setAngle2(getEllipseAngle(vpEnd));
    }
    correctAngles();//avoid extra 2.*M_PI in angles
    //calculateEndpoints();
    calculateBorders();
}
Example #10
0
bool RS_Ellipse::switchMajorMinor(void)
//switch naming of major/minor, return true if success
{
    if (fabs(data.ratio) < RS_TOLERANCE) return false;
    RS_Vector vp_start=getStartpoint();
    RS_Vector vp_end=getStartpoint();
    RS_Vector vp=getMajorP();
    setMajorP(RS_Vector(- data.ratio*vp.y, data.ratio*vp.x)); //direction pi/2 relative to old MajorP;
    setRatio(1./data.ratio);
    if(   std::isnormal(getAngle1()) || std::isnormal(getAngle2() ) )  {
        //only reset start/end points for ellipse arcs, i.e., angle1 angle2 are not both zero
        setAngle1(getEllipseAngle(vp_start));
        setAngle2(getEllipseAngle(vp_end));
    }
    return true;
}
Example #11
0
RS_Vector RS_Ellipse::getNearestMiddle(const RS_Vector& coord,
                                       double* dist,
                                       int middlePoints
                                      ) {
    if ( ! ( std::isnormal(getAngle1()) || std::isnormal(getAngle2()))) {
        //no middle point for whole ellipse, angle1=angle2=0
        if (dist!=NULL) {
            *dist = RS_MAXDOUBLE;
        }
        return RS_Vector(false);
    }
    if ( getMajorRadius() < RS_TOLERANCE || getMinorRadius() < RS_TOLERANCE ) {
        //zero radius, return the center
        RS_Vector vp(getCenter());
        if (dist!=NULL) {
            *dist = vp.distanceTo(coord);
        }
        return vp;
    }
    double angle=getAngle();
    double amin=getCenter().angleTo(getStartpoint());
    double amax=getCenter().angleTo(getEndpoint());
    if(isReversed()) {
        std::swap(amin,amax);
    }
    int i=middlePoints + 1;
    double da=fmod(amax-amin+2.*M_PI, 2.*M_PI);
    if ( da < RS_TOLERANCE ) {
        da = 2.*M_PI; //whole ellipse
    }
    da /= i;
    int j=1;
    double curDist=RS_MAXDOUBLE;
    //double a=RS_Math::correctAngle(amin+da-angle);
    double a=amin-angle+da;
    RS_Vector curPoint;
    RS_Vector scaleFactor(RS_Vector(1./getMajorRadius(),1./getMinorRadius()));
    do {
        RS_Vector vp(a);
        RS_Vector vp2=vp;
        vp2.scale(scaleFactor);
        vp.scale(1./vp2.magnitude());
        vp.rotate(angle);
        vp.move(getCenter());
        double d=coord.distanceTo(vp);
        if(d<curDist) {
            curDist=d;
            curPoint=vp;
        }
        j++;
        a += da;
    } while (j<i);
    if (dist!=NULL) {
        *dist = curDist;
    }
    RS_DEBUG->print("RS_Ellipse::getNearestMiddle: angle1=%g, angle2=%g, middle=%g\n",amin,amax,a);
    return curPoint;
}
Example #12
0
RS_Vector RS_Line::getNearestDist(double distance,
                                  const RS_Vector& coord,
								  double* dist) const{

	RS_Vector dv = RS_Vector::polar(distance, getAngle1());

    RS_Vector ret;
    //if(coord.distanceTo(getStartpoint()) < coord.distanceTo(getEndpoint())) {
    if( (coord-getStartpoint()).squared()<  (coord-getEndpoint()).squared() ) {
        ret = getStartpoint() + dv;
    }else{
        ret = getEndpoint() - dv;
    }
	if (dist)
        *dist=coord.distanceTo(ret);

    return ret;
}
Example #13
0
void RS_OverlayLine::draw(RS_Painter* painter, RS_GraphicView* view, double patternOffset) {
    if (painter==NULL || view==NULL) {
        return;
    }
	
	painter->drawLine(getStartpoint(),
					  getEndpoint());

}
Example #14
0
RS2::Ending RS_Line::getTrimPoint(const RS_Vector& trimCoord,
                                  const RS_Vector& trimPoint) {
    RS_Vector vp1=getStartpoint() - trimCoord;
    RS_Vector vp2=trimPoint - trimCoord;
    if ( RS_Vector::dotP(vp1,vp2) < 0 ) {
        return RS2::EndingEnd;
    } else {
        return RS2::EndingStart;
    }
}
Example #15
0
void RS_Arc::stretch(RS_Vector firstCorner,
                      RS_Vector secondCorner,
                      RS_Vector offset) {

    if (getMin().isInWindow(firstCorner, secondCorner) &&
            getMax().isInWindow(firstCorner, secondCorner)) {

        move(offset);
    }
	else {
	    if (getStartpoint().isInWindow(firstCorner,
    	                               secondCorner)) {
        	moveStartpoint(getStartpoint() + offset);
	    }
	    if (getEndpoint().isInWindow(firstCorner,
	                                 secondCorner)) {
	        moveEndpoint(getEndpoint() + offset);
	    }
	}
}
Example #16
0
void RS_Ellipse::moveRef(const RS_Vector& ref, const RS_Vector& offset) {
	RS_Vector startpoint = getStartpoint();
	RS_Vector endpoint = getEndpoint();
	
    if (ref.distanceTo(startpoint)<1.0e-4) {
        moveStartpoint(startpoint+offset);
    }
    if (ref.distanceTo(endpoint)<1.0e-4) {
        moveEndpoint(endpoint+offset);
    }
}
Example #17
0
void RS_Ellipse::moveRef(const RS_Vector& ref, const RS_Vector& offset) {
    RS_Vector startpoint = getStartpoint();
    RS_Vector endpoint = getEndpoint();

    if (ref.distanceTo(startpoint)<1.0e-4) {
        moveStartpoint(startpoint+offset);
    }
    if (ref.distanceTo(endpoint)<1.0e-4) {
        moveEndpoint(endpoint+offset);
    }
    correctAngles();//avoid extra 2.*M_PI in angles
}
Example #18
0
void RS_Arc::moveEndpoint(const RS_Vector& pos) {
    // polyline arcs: move point not angle:
    //if (parent!=NULL && parent->rtti()==RS2::EntityPolyline) {
		double bulge = getBulge();
		createFrom2PBulge(getStartpoint(), pos, bulge);
    //}

	// normal arc: move angle1
	/*else {
    	data.angle2 = data.center.angleTo(pos);
	    calculateEndpoints();
    	calculateBorders();
	}*/
}
Example #19
0
/** whether the entity's bounding box intersects with visible portion of graphic view */
bool RS_Entity::isVisibleInWindow(RS_GraphicView* view) const
{
    RS_Vector vpMin(view->toGraph(0,view->getHeight()));
    RS_Vector vpMax(view->toGraph(view->getWidth(),0));
    if( getStartpoint().isInWindowOrdered(vpMin, vpMax) ) return true;
    if( getEndpoint().isInWindowOrdered(vpMin, vpMax) ) return true;
    QPolygonF visualBox(QRectF(vpMin.x,vpMin.y,vpMax.x-vpMin.x, vpMax.y-vpMin.y));
	std::vector<RS_Vector> vps;
    for(unsigned short i=0;i<4;i++){
        const QPointF& vp(visualBox.at(i));
		vps.emplace_back(vp.x(),vp.y());
    }
    for(unsigned short i=0;i<4;i++){
		RS_Line const line{vps.at(i),vps.at((i+1)%4)};
		if( RS_Information::getIntersection(this, &line, true).size()>0) return true;
    }
    if( minV.isInWindowOrdered(vpMin,vpMax)||maxV.isInWindowOrdered(vpMin,vpMax)) return true;
    return false;
}
Example #20
0
/**
 * mirror by the axis defined by axisPoint1 and axisPoint2
 */
void RS_Ellipse::mirror(RS_Vector axisPoint1, RS_Vector axisPoint2) {
    RS_Vector center=getCenter();
    RS_Vector mp = center + getMajorP();
    RS_Vector startpoint = getStartpoint();
    RS_Vector endpoint = getEndpoint();

    center.mirror(axisPoint1, axisPoint2);
    mp.mirror(axisPoint1, axisPoint2);
    startpoint.mirror(axisPoint1, axisPoint2);
    endpoint.mirror(axisPoint1, axisPoint2);

    setCenter(center);
    setReversed(!isReversed());
    setMajorP(mp - center);
    if(   std::isnormal(getAngle1()) || std::isnormal(getAngle2() ) )  {
        //only reset start/end points for ellipse arcs, i.e., angle1 angle2 are not both zero
        setAngle1( getEllipseAngle(startpoint));
        setAngle2( getEllipseAngle(endpoint));
    }
    /*  old version
        data.majorP = mp - data.center;

        double a = axisPoint1.angleTo(axisPoint2);

        RS_Vector vec;
        vec.setPolar(1.0, data.angle1);
        vec.mirror(RS_Vector(0.0,0.0), axisPoint2-axisPoint1);
        data.angle1 = vec.angle() - 2*a;

        vec.setPolar(1.0, data.angle2);
        vec.mirror(RS_Vector(0.0,0.0), axisPoint2-axisPoint1);
        data.angle2 = vec.angle() - 2*a;

        data.reversed = (!data.reversed);
    */
    //calculateEndpoints();
    correctAngles();//avoid extra 2.*M_PI in angles
    calculateBorders();
}
Example #21
0
/**
 * Calculates the boundary box of this ellipse.
 *
 * @todo Fix that - the algorithm used is really bad / slow.
 */
void RS_Ellipse::calculateBorders() {
	RS_DEBUG->print("RS_Ellipse::calculateBorders");

    double radius1 = getMajorRadius();
    double radius2 = getMinorRadius();
    double angle = getAngle();
    double a1 = ((!isReversed()) ? data.angle1 : data.angle2);
    double a2 = ((!isReversed()) ? data.angle2 : data.angle1);
	RS_Vector startpoint = getStartpoint();
	RS_Vector endpoint = getEndpoint();

    double minX = std::min(startpoint.x, endpoint.x);
    double minY = std::min(startpoint.y, endpoint.y);
    double maxX = std::max(startpoint.x, endpoint.x);
    double maxY = std::max(startpoint.y, endpoint.y);

    // kind of a brute force. TODO: calculation
    RS_Vector vp;
	double a = a1;
	do {
        vp.set(data.center.x + radius1 * cos(a),
               data.center.y + radius2 * sin(a));
        vp.rotate(data.center, angle);

        minX = std::min(minX, vp.x);
        minY = std::min(minY, vp.y);
        maxX = std::max(maxX, vp.x);
        maxY = std::max(maxY, vp.y);

		a += 0.03;
    } while (RS_Math::isAngleBetween(RS_Math::correctAngle(a), a1, a2, false) && 
			a<4*M_PI);


    minV.set(minX, minY);
    maxV.set(maxX, maxY);
	RS_DEBUG->print("RS_Ellipse::calculateBorders: OK");
}
Example #22
0
RS_Vector RS_Ellipse::getNearestEndpoint(const RS_Vector& coord, double* dist) {
    double dist1, dist2;
    RS_Vector nearerPoint;
	RS_Vector startpoint = getStartpoint();
	RS_Vector endpoint = getEndpoint();

    dist1 = startpoint.distanceTo(coord);
    dist2 = endpoint.distanceTo(coord);

    if (dist2<dist1) {
        if (dist!=NULL) {
            *dist = dist2;
        }
        nearerPoint = endpoint;
    } else {
        if (dist!=NULL) {
            *dist = dist1;
        }
        nearerPoint = startpoint;
    }

    return nearerPoint;
}
Example #23
0
    RS_Vector RS_Line::getMiddlePoint()const
{
        return (getStartpoint() + getEndpoint())*0.5;
}
Example #24
0
void RS_Line::draw(RS_Painter* painter, RS_GraphicView* view, double patternOffset)
{
  if (painter==NULL || view==NULL)
  {
    return;
  }

  if (getPen().getLineType()==RS2::SolidLine ||
      isSelected() ||
      view->getDrawingMode()==RS2::ModePreview)
  {

    painter->drawLine(view->toGui(getStartpoint()),
                      view->toGui(getEndpoint()));
  }
  else
  {
    double styleFactor = getStyleFactor(view);
    if (styleFactor<0.0)
    {
      painter->drawLine(view->toGui(getStartpoint()),
                        view->toGui(getEndpoint()));
      return;
    }

    // Pattern:
    RS_LineTypePattern* pat;
    if (isSelected())
    {
      pat = &patternSelected;
    }
    else
    {
      pat = view->getPattern(getPen().getLineType());
    }
    if (pat==NULL)
    {
      RS_DEBUG->print(RS_Debug::D_WARNING,
                      "RS_Line::draw: Invalid line pattern");
      return;
    }

    // Pen to draw pattern is always solid:
    RS_Pen pen = painter->getPen();

    pen.setLineType(RS2::SolidLine);
    painter->setPen(pen);

    // index counter
    int i;

    // line data:
    double length = getLength();
    double angle = getAngle1();

    // pattern segment length:
    double patternSegmentLength = 0.0;

    // create pattern:
    RS_Vector* dp = new RS_Vector[pat->num];

    for (i=0; i<pat->num; ++i)
    {
      dp[i] = RS_Vector(cos(angle) * fabs(pat->pattern[i] * styleFactor),
                        sin(angle) * fabs(pat->pattern[i] * styleFactor));

      patternSegmentLength += fabs(pat->pattern[i] * styleFactor);
    }

    // handle pattern offset:
    int m;
    if (patternOffset<0.0)
    {
      m = (int)ceil(patternOffset / patternSegmentLength);
    }
    else
    {
      m = (int)floor(patternOffset / patternSegmentLength);
    }

    patternOffset -= (m*patternSegmentLength);
    //if (patternOffset<0.0) {
    //  patternOffset+=patternSegmentLength;
    //}
    //RS_DEBUG->print("pattern. offset: %f", patternOffset);
    RS_Vector patternOffsetVec;
    patternOffsetVec.setPolar(patternOffset, angle);

    double tot=patternOffset;
    i=0;
    bool done = false;
    bool cutStartpoint, cutEndpoint, drop;
    RS_Vector curP=getStartpoint()+patternOffsetVec;

    do
    {
      cutStartpoint = false;
      cutEndpoint = false;
      drop = false;

      // line segment (otherwise space segment)
      if (pat->pattern[i]>0.0)
      {
        // drop the whole pattern segment line:
        if (tot+pat->pattern[i]*styleFactor < 0.0)
        {
          drop = true;
        }
        else
        {
          // trim startpoint of pattern segment line to line startpoint
          if (tot < 0.0)
          {
            cutStartpoint = true;
          }
          // trim endpoint of pattern segment line to line endpoint
          if (tot+pat->pattern[i]*styleFactor > length)
          {
            cutEndpoint = true;
          }
        }

        if (drop)
        {
          // do nothing
        }
        else
        {
          RS_Vector p1 = curP;
          RS_Vector p2 = curP + dp[i];

          if (cutStartpoint)
          {
            p1 = getStartpoint();
          }
          if (cutEndpoint)
          {
            p2 = getEndpoint();
          }

          painter->drawLine(view->toGui(p1),
                            view->toGui(p2));
        }
      }
      curP+=dp[i];
      tot+=fabs(pat->pattern[i]*styleFactor);
      //RS_DEBUG->print("pattern. tot: %f", tot);
      done=tot>length;

      i++;
      if (i>=pat->num)
      {
        i=0;
      }
    }
    while(!done);

    delete[] dp;

  }
}
Example #25
0
/**
 * @todo Implement this.
 */
RS_Vector RS_Ellipse::getNearestPointOnEntity(const RS_Vector& coord,
        bool onEntity, double* dist, RS_Entity** entity) {

	RS_DEBUG->print("RS_Ellipse::getNearestPointOnEntity");
    RS_Vector ret(false);

    if (entity!=NULL) {
        *entity = this;
    }

    double step;
    double a1;
    double a2;
    double d;
    double minDist = RS_MAXDOUBLE;

    if (!onEntity) {
        a1 = 0.0;
        a2 = 2*M_PI;
    } else {
        if (!data.reversed) {
            a1 = data.angle1;
            a2 = data.angle2;
        } else {
            a1 = data.angle2;
            a2 = data.angle1;
        }
    }

    // find closest point (approximate)
    RS_Vector vp;
    double bestMatch = 0.0;
    step = 0.01;
    double a = a1+step;
	int eternal = 0;
    do {
		// point on elllipse (wanders from a1 to a2)
        vp.set(data.center.x+cos(a)*getMajorRadius(),
               data.center.y+sin(a)*getMinorRadius());
        vp.rotate(data.center, getAngle());

        d = vp.distanceTo(coord);
        if (d<minDist) {
            minDist = d;
            bestMatch = a;
            ret = vp;
        }

        a += step;
		eternal++;
    } while (eternal<10000 && 
	    RS_Math::isAngleBetween(RS_Math::correctAngle(a), a1, a2, false) &&
		(onEntity || a<2*M_PI));

    // correct:
	/*
    a = bestMatch;
    step = 0.03;
    do {
        vp.set(data.center.x+cos(a)*getMajorRadius(),
               data.center.y+sin(a)*getMinorRadius());
        vp.rotate(data.center, getAngle());

        d = vp.distanceTo(coord);
        if (d<minDist) {
            minDist = d;
            bestMatch = a;
            ret = vp;
        } else {
            // change direction and decrease step amount
            step*=-0.3;
        }

        a += step;
    } while (fabs(step)>1.0e-6);
	*/

    // check endpoints:
    if (onEntity) {
        d = getStartpoint().distanceTo(coord);
        if (d<minDist) {
            ret = getStartpoint();
        }
        d = getEndpoint().distanceTo(coord);
        if (d<minDist) {
            ret = getEndpoint();
        }
    }

    if (dist!=NULL) {
        if (ret.valid) {
            *dist = ret.distanceTo(coord);
        } else {
            *dist = RS_MAXDOUBLE;
        }
    }
	RS_DEBUG->print("RS_Ellipse::getNearestPointOnEntity: OK");

    return ret;
}
Example #26
0
RS_VectorSolutions RS_Ellipse::getRefPoints() {
    RS_VectorSolutions ret(getStartpoint(), getEndpoint(), data.center);
    return ret;
}
Example #27
0
/**
 * Calculates the boundary box of this ellipse.
 */
void RS_Ellipse::calculateBorders() {
    RS_DEBUG->print("RS_Ellipse::calculateBorders");

    double radius1 = getMajorRadius();
    double radius2 = getMinorRadius();
    double angle = getAngle();
    //double a1 = ((!isReversed()) ? data.angle1 : data.angle2);
    //double a2 = ((!isReversed()) ? data.angle2 : data.angle1);
    RS_Vector startpoint = getStartpoint();
    RS_Vector endpoint = getEndpoint();

    double minX = std::min(startpoint.x, endpoint.x);
    double minY = std::min(startpoint.y, endpoint.y);
    double maxX = std::max(startpoint.x, endpoint.x);
    double maxY = std::max(startpoint.y, endpoint.y);

    RS_Vector vp;
    // kind of a brute force. TODO: exact calculation
//    double a = a1;

//    do {
//        vp.set(data.center.x + radius1 * cos(a),
//               data.center.y + radius2 * sin(a));
//        vp.rotate(data.center, angle);
//
//        minX = std::min(minX, vp.x);
//        minY = std::min(minY, vp.y);
//        maxX = std::max(maxX, vp.x);
//        maxY = std::max(maxY, vp.y);
//
//        a += 0.03;
//    } while (RS_Math::isAngleBetween(RS_Math::correctAngle(a), a1, a2, false) &&
//             a<4*M_PI);
//    std::cout<<"a1="<<a1<<"\ta2="<<a2<<std::endl<<"Old algorithm:\nminX="<<minX<<"\tmaxX="<<maxX<<"\nminY="<<minY<<"\tmaxY="<<maxY<<std::endl;

    // Exact algorithm, based on rotation:
    // ( r1*cos(a), r2*sin(a)) rotated by angle to
    // (r1*cos(a)*cos(angle)-r2*sin(a)*sin(angle),r1*cos(a)*sin(angle)+r2*sin(a)*cos(angle))
    // both coordinates can be further reorganized to the form rr*cos(a+ theta),
    // with rr and theta angle defined by the coordinates given above
    double amin,amax;
//      x range
    vp.set(radius1*cos(angle),radius2*sin(angle));

    amin=RS_Math::correctAngle(getAngle1()+vp.angle()); // to the range of 0 to 2*M_PI
    amax=RS_Math::correctAngle(getAngle2()+vp.angle()); // to the range of 0 to 2*M_PI
    if( RS_Math::isAngleBetween(M_PI,amin,amax,isReversed()) ) {
        //if( (amin<=M_PI && delta_a >= M_PI - amin) || (amin > M_PI && delta_a >= 3*M_PI - amin)) {
        minX= data.center.x-vp.magnitude();
    }
    //    else

//       minX=data.center.x +vp.magnitude()*std::min(cos(amin),cos(amin+delta_a));
    if( RS_Math::isAngleBetween(2.*M_PI,amin,amax,isReversed()) ) {
        //if( delta_a >= 2*M_PI - amin ) {
        maxX= data.center.x+vp.magnitude();
    }//    else
//       maxX= data.center.x+vp.magnitude()*std::max(cos(amin),cos(amin+delta_a));
//      y range
    vp.set(radius1*sin(angle),-radius2*cos(angle));
    amin=RS_Math::correctAngle(getAngle1()+vp.angle()); // to the range of 0 to 2*M_PI
    amax=RS_Math::correctAngle(getAngle2()+vp.angle()); // to the range of 0 to 2*M_PI
    if( RS_Math::isAngleBetween(M_PI,amin,amax,isReversed()) ) {
        //if( (amin<=M_PI &&delta_a >= M_PI - amin) || (amin > M_PI && delta_a >= 3*M_PI - amin)) {
        minY= data.center.y-vp.magnitude();
    }//    else
//        minY=data.center.y +vp.magnitude()*std::min(cos(amin),cos(amin+delta_a));
    if( RS_Math::isAngleBetween(2.*M_PI,amin,amax,isReversed()) ) {
        //if( delta_a >= 2*M_PI - amin ) {
        maxY= data.center.y+vp.magnitude();
    }
    //    else
//        maxY= data.center.y+vp.magnitude()*std::max(cos(amin),cos(amin+delta_a));
//std::cout<<"New algorithm:\nminX="<<minX<<"\tmaxX="<<maxX<<"\nminY="<<minY<<"\tmaxY="<<maxY<<std::endl;

    minV.set(minX, minY);
    maxV.set(maxX, maxY);
    RS_DEBUG->print("RS_Ellipse::calculateBorders: OK");
}
Example #28
0
void RS_Line::draw(RS_Painter* painter, RS_GraphicView* view, double& patternOffset) {
    if (painter==NULL || view==NULL) {
        return;
    }
    //visible in grahic view
    if(isVisibleInWindow(view)==false) return;
    RS_Vector pStart(view->toGui(getStartpoint()));
    RS_Vector pEnd(view->toGui(getEndpoint()));

    //    std::cout<<"draw line: "<<pStart<<" to "<<pEnd<<std::endl;
    RS_Vector direction=pEnd-pStart;
    if(isHelpLayer(true) && direction.squared() > RS_TOLERANCE){
        //extend line on a help layer to fill the whole view
        RS_Vector lb(0,0);
        RS_Vector rt(view->getWidth(),view->getHeight());
        QList<RS_Vector> rect;
        rect<<lb<<RS_Vector(rt.x,lb.y);
        rect<<rt<<RS_Vector(lb.x,rt.y);
        rect<<lb;
        RS_VectorSolutions sol;
        RS_Line dLine(pStart,pEnd);
        for(int i=0;i<4;i++){
            RS_Line bLine(rect.at(i),rect.at(i+1));
            RS_VectorSolutions sol2=RS_Information::getIntersection(&bLine, &dLine);
            if( sol2.getNumber()>0 && bLine.isPointOnEntity(sol2.get(0),RS_TOLERANCE)) {
                sol.push_back(sol2.get(0));
            }
        }
        switch(sol.getNumber()){
        case 2:
            pStart=sol.get(0);
            pEnd=sol.get(1);
            break;
        case 3:
        case 4:
            pStart=sol.get(0);
            pEnd=sol.get(2);
            break;
        default:
            return;
        }
        direction=pEnd-pStart;
    }
    double  length=direction.magnitude();
    patternOffset -= length;
    if (( !isSelected() && (
              getPen().getLineType()==RS2::SolidLine ||
              view->getDrawingMode()==RS2::ModePreview)) ) {
        //if length is too small, attempt to draw the line, could be a potential bug
        painter->drawLine(pStart,pEnd);
        return;
    }
    //    double styleFactor = getStyleFactor(view);


    // Pattern:
    RS_LineTypePattern* pat;
    if (isSelected()) {
//        styleFactor=1.;
        pat = &patternSelected;
    } else {
        pat = view->getPattern(getPen().getLineType());
    }
    if (pat==NULL) {
//        patternOffset -= length;
        RS_DEBUG->print(RS_Debug::D_WARNING,
                        "RS_Line::draw: Invalid line pattern");
        painter->drawLine(pStart,pEnd);
        return;
    }
//    patternOffset = remainder(patternOffset - length-0.5*pat->totalLength,pat->totalLength)+0.5*pat->totalLength;
    if(length<=RS_TOLERANCE){
        painter->drawLine(pStart,pEnd);
        return; //avoid division by zero
    }
    direction/=length; //cos(angle), sin(angle)
    // Pen to draw pattern is always solid:
    RS_Pen pen = painter->getPen();

    pen.setLineType(RS2::SolidLine);
    painter->setPen(pen);

    // index counter
    int i;

    // pattern segment length:
    double patternSegmentLength = pat->totalLength;

    // create pattern:
    RS_Vector* dp=new RS_Vector[pat->num > 0?pat->num:0];
    double* ds=new double[pat->num > 0?pat->num:0];
    if (pat->num >0 ){
        for (i=0; i<pat->num; ++i) {
            //        ds[j]=pat->pattern[i] * styleFactor;
            //fixme, styleFactor support needed
            ds[i]=pat->pattern[i] ;
            dp[i] = direction*fabs(ds[i]);
        }
    }else {
        delete[] dp;
        delete[] ds;
        RS_DEBUG->print(RS_Debug::D_WARNING,"invalid line pattern for line, draw solid line instread");
        painter->drawLine(view->toGui(getStartpoint()),
                          view->toGui(getEndpoint()));
        return;
    }
    double total= remainder(patternOffset-0.5*patternSegmentLength,patternSegmentLength) -0.5*patternSegmentLength;
    //    double total= patternOffset-patternSegmentLength;

    RS_Vector p1,p2,p3;
    RS_Vector curP(pStart+direction*total);
    double t2;
    for(int j=0;total<length;j=(j+1)%i) {

        // line segment (otherwise space segment)
        t2=total+fabs(ds[j]);
        p3=curP+dp[j];
        if (ds[j]>0.0 && t2 > 0.0) {
            // drop the whole pattern segment line, for ds[i]<0:
            // trim end points of pattern segment line to line
            p1 =(total > -0.5)? curP:pStart;
            p2 =(t2<length+0.5)?p3:pEnd;
            painter->drawLine(p1,p2);
        }
        total=t2;
        curP=p3;
    }
    delete[] dp;
    delete[] ds;

}
Example #29
0
RS_Vector  RS_Line::getTangentDirection(const RS_Vector& /*point*/)const{
        return getEndpoint() - getStartpoint();
}
Example #30
0
void RS_Line::draw(RS_Painter* painter, RS_GraphicView* view, double& patternOffset) {
    if (painter==NULL || view==NULL) {
        return;
    }

    //only draw the visible portion of line
    QVector<RS_Vector> endPoints(0);
        RS_Vector vpMin(view->toGraph(0,view->getHeight()));
        RS_Vector vpMax(view->toGraph(view->getWidth(),0));
         QPolygonF visualBox(QRectF(vpMin.x,vpMin.y,vpMax.x-vpMin.x, vpMax.y-vpMin.y));
    if( getStartpoint().isInWindowOrdered(vpMin, vpMax) ) endPoints<<getStartpoint();
    if( getEndpoint().isInWindowOrdered(vpMin, vpMax) ) endPoints<<getEndpoint();
    if(endPoints.size()<2){

         QVector<RS_Vector> vertex;
         for(unsigned short i=0;i<4;i++){
             const QPointF& vp(visualBox.at(i));
             vertex<<RS_Vector(vp.x(),vp.y());
         }
         for(unsigned short i=0;i<4;i++){
             RS_Line line(NULL,RS_LineData(vertex.at(i),vertex.at((i+1)%4)));
             auto&& vpIts=RS_Information::getIntersection(static_cast<RS_Entity*>(this), &line, true);
             if( vpIts.size()==0) continue;
             endPoints<<vpIts.get(0);
         }
    }
    if(endPoints.size()<2) return;
    if( (endPoints[0] - getStartpoint()).squared() >
            (endPoints[1] - getStartpoint()).squared() ) std::swap(endPoints[0],endPoints[1]);

    RS_Vector pStart(view->toGui(endPoints.at(0)));
    RS_Vector pEnd(view->toGui(endPoints.at(1)));
    //    std::cout<<"draw line: "<<pStart<<" to "<<pEnd<<std::endl;
    RS_Vector direction=pEnd-pStart;
    if(isHelpLayer(true) && direction.squared() > RS_TOLERANCE){
        //extend line on a help layer to fill the whole view
        RS_Vector lb(0,0);
        RS_Vector rt(view->getWidth(),view->getHeight());
        QList<RS_Vector> rect;
        rect<<lb<<RS_Vector(rt.x,lb.y);
        rect<<rt<<RS_Vector(lb.x,rt.y);
        rect<<lb;
        RS_VectorSolutions sol;
        RS_Line dLine(pStart,pEnd);
        for(int i=0;i<4;i++){
            RS_Line bLine(rect.at(i),rect.at(i+1));
            RS_VectorSolutions sol2=RS_Information::getIntersection(&bLine, &dLine);
            if( sol2.getNumber()>0 && bLine.isPointOnEntity(sol2.get(0),RS_TOLERANCE)) {
                sol.push_back(sol2.get(0));
            }
        }
        switch(sol.getNumber()){
        case 2:
            pStart=sol.get(0);
            pEnd=sol.get(1);
            break;
        case 3:
        case 4:
            pStart=sol.get(0);
            pEnd=sol.get(2);
            break;
        default:
            return;
        }
        direction=pEnd-pStart;
    }
    double  length=direction.magnitude();
    patternOffset -= length;
    if (( !isSelected() && (
              getPen().getLineType()==RS2::SolidLine ||
              view->getDrawingMode()==RS2::ModePreview)) ) {
        //if length is too small, attempt to draw the line, could be a potential bug
        painter->drawLine(pStart,pEnd);
        return;
    }
    //    double styleFactor = getStyleFactor(view);


    // Pattern:
    RS_LineTypePattern* pat;
    if (isSelected()) {
//        styleFactor=1.;
        pat = &patternSelected;
    } else {
        pat = view->getPattern(getPen().getLineType());
    }
    if (pat==NULL) {
//        patternOffset -= length;
        RS_DEBUG->print(RS_Debug::D_WARNING,
                        "RS_Line::draw: Invalid line pattern");
        painter->drawLine(pStart,pEnd);
        return;
    }
//    patternOffset = remainder(patternOffset - length-0.5*pat->totalLength,pat->totalLength)+0.5*pat->totalLength;
    if(length<=RS_TOLERANCE){
        painter->drawLine(pStart,pEnd);
        return; //avoid division by zero
    }
    direction/=length; //cos(angle), sin(angle)
    // Pen to draw pattern is always solid:
    RS_Pen pen = painter->getPen();

    pen.setLineType(RS2::SolidLine);
    painter->setPen(pen);

    // index counter
    int i;

    // pattern segment length:
    double patternSegmentLength = pat->totalLength;

    // create pattern:
    RS_Vector* dp=new RS_Vector[pat->num > 0?pat->num:0];
    double* ds=new double[pat->num > 0?pat->num:0];
    if (pat->num >0 ){
        double dpmm=static_cast<RS_PainterQt*>(painter)->getDpmm();
        for (i=0; i<pat->num; ++i) {
            //        ds[j]=pat->pattern[i] * styleFactor;
            //fixme, styleFactor support needed

            ds[i]=dpmm*pat->pattern[i];
            if( fabs(ds[i]) < 1. ) ds[i] = (ds[i]>=0.)?1.:-1.;
            dp[i] = direction*fabs(ds[i]);
        }
    }else {
        delete[] dp;
        delete[] ds;
        RS_DEBUG->print(RS_Debug::D_WARNING,"invalid line pattern for line, draw solid line instread");
        painter->drawLine(view->toGui(getStartpoint()),
                          view->toGui(getEndpoint()));
        return;
    }
    double total= remainder(patternOffset-0.5*patternSegmentLength,patternSegmentLength) -0.5*patternSegmentLength;
    //    double total= patternOffset-patternSegmentLength;

    RS_Vector p1,p2,p3;
    RS_Vector curP(pStart+direction*total);
    double t2;
    for(int j=0;total<length;j=(j+1)%i) {

        // line segment (otherwise space segment)
        t2=total+fabs(ds[j]);
        p3=curP+dp[j];
        if (ds[j]>0.0 && t2 > 0.0) {
            // drop the whole pattern segment line, for ds[i]<0:
            // trim end points of pattern segment line to line
            p1 =(total > -0.5)? curP:pStart;
            p2 =(t2<length+0.5)?p3:pEnd;
            painter->drawLine(p1,p2);
        }
        total=t2;
        curP=p3;
    }
    delete[] dp;
    delete[] ds;

}