void snlSurfaceOfRevolution::vertexNet ( snlVertexNet* vNet, double tolerance, bool parametric )
{
    // Return approximation to surface.
    // --------------------------------
    // tolerance:    Tolerance to approximate to.
    // parametric:   Do a parametric analysis as opposed to knot refinement.
    // vNet:         Vertex net to fill with data.
    
    snlCurve* profileCopy = new snlCurve ( *profile );
    
    if ( tolerance > 0.0 )
        profileCopy -> refine ( tolerance );    
    
    const snlCtrlPoint* ctrlPts = profileCopy -> controlPointNet().getCtrlPts();
    
    int numPts = profileCopy -> controlPointNet().size();
    
    vNet -> vertexNet ( ctrlPts, numPts );
    
    // Find angle step to use.
    
    snlPoint axis_start_norm ( *axis_start );
    axis_start_norm.normalise();
    
    snlPoint axis_end_norm ( *axis_end );
    axis_end_norm.normalise();    
    
    // Get largest radius
    
    double maxRadius = 0.0;
    
    for ( int index = 0; index < numPts; index ++ )
    {        
        double dist = distToLine ( axis_start_norm, axis_end_norm, ctrlPts [ index ] );
        
        if ( dist > maxRadius )
            maxRadius = dist;        
    }
    
    // Calculate steps based on tolerance and maximum radius.
    
    double angleStep = 2 * acos ( 1.0 - ( tolerance / maxRadius ) );
    
    int numSteps = (int ) ( rot_angle / angleStep ) + 1;
    
    angleStep = rot_angle / (double) numSteps;
    
    // Rotate and append points at discrete angle steps.   
    
    snlTransform transf;
    
    transf.rotate ( angleStep, axis_start_norm, axis_end_norm );
    
    for ( int step = 0; step < numSteps; step ++ )
    {
        profileCopy -> controlPointNet().transform ( transf );
        
        vNet -> appendRow ( ctrlPts );
    }
}
예제 #2
0
// Closest point to line segment between a and b (OK if a == b)
double distToLineSegment(point p, point a, point b, point &c) {
    vec ap = toVec(a, p), ab = toVec(a, b);
    double u = dot(ap, ab) / norm_sq(ab);
    if (u < 0.0) { c = point(a.x, a.y); return dist(p, a); }
    if (u > 1.0) { c = point(b.x, b.y); return dist(p, b); }
    return distToLine(p, a, b, c);
}
예제 #3
0
파일: geometry.cpp 프로젝트: c-a/Impa
// returns the distance from p to the line segment ab defined by two points a and b. The closest point is stored in c.
ftype distToLineSegment(const Point& p, const Point& a, const Point& b, Point& c) {
  Vec ap(a, p), ab(a, b);
  ftype u = ap.dot(ab) / ab.norm_sq();
  if (u < 0.0) { // closer to a
    c = a; return dist(p, a); // Euclidean distance between p and a
  }
  else if (u > 1.0) { // closer to b
    c = b; return dist(p, b); // Euclidean distance between p and b
  }
  return distToLine(p, a, b, c);
}
// Distance from a point to a line segment
// Returns the distance from p to the line segment ab.
// The closest point on ab is returned through (cpx, cpy).
// Works correctly for degenerate line segments (a == b).
// REQUIRES: #include <math.h>, #define EPS ..., dist(), distToLine()
double distToLineSegment(double ax, double ay, double bx, double by, double px, double py, double *cpx, double *cpy) {
	if ((bx - ax) * (px - ax) + (by - ay) * (py - ay) < EPS) {
		*cpx = ax;
		*cpy = ay;
		return dist(ax, ay, px, py);
	}
	if ((ax - bx) * (px - bx) + (ay - by) * (py - by) < EPS) {
		*cpx = bx;
		*cpy = by;
		return dist(bx, by, px, py);
	}
	return distToLine(ax, ay, bx, by, px, py, cpx, cpy);
}
예제 #5
0
void NodeConnectionControl::onDrag(APoint m_pos, AVec d_pos)
{
	if(fromNode && toNode)
	{
		APoint m_pos_grid = m_pos + pos;
		float dist = distToLine(m_pos);
		
		//std::cout << dist << "\n";
		//std::cout << "(" << pTo.x << ", " << pTo.y << "), (" << pFrom.x << ", " << pFrom.y << "), (" << m_pos.x << ", " << m_pos.y << ")\n";
			
		
		//std::cout << dist << " (" << disconnectRadius << ")\n";

		if(dist > disconnectRadius || !pointInside(m_pos))
		{
			AVec	d_pos_from = pFrom - m_pos,
					d_pos_to = pTo - m_pos;
			float	to_dist_2 = d_pos_to.x*d_pos_to.x + d_pos_to.y*d_pos_to.y,
					from_dist_2 = d_pos_from.x*d_pos_from.x + d_pos_from.y*d_pos_from.y;
			
			AStatus status = fromNc->disconnect(toNc);

			if(!statusGood(status))
			{
				std::cout << status << "\n";
				return;
			}

			if(to_dist_2 < from_dist_2)
			{
				toNode = nullptr;
				toNc = nullptr;
				ngd_parent->restartConnectingNodes(this, fromNode, fromNc->getId());
			}
			else
			{
				fromNode = nullptr;
				fromNc = nullptr;
				ngd_parent->restartConnectingNodes(this, toNode, toNc->getId());
			}

			setHangingPos(m_pos);
		}
	}
}
void snlCircularOffsetCurve::applyOffset ( snlPoint& point, snlPoint chordOffset, snlPoint angleOffset, snlPoint tangentOffset ) const
{
    // Rotate point about axis by circular offset.
    // -------------------------------------------
    // point:          Point to rotate.
    // chordOffset:    Point containing weighted chord offset.
    // angleOffset:    Point containing weighted angle offset.
    // tangentOffset:  Point containing weighted tangent offset.    
    
    chordOffset.normalise();
    angleOffset.normalise();
    tangentOffset.normalise();
    
    double angle = 0.0;
    
    // Calculate angle to rotate by by adding all offsets together.
    
    double dist = distToLine ( *axis_start, *axis_end, point );
    
    // CHORD.
    
    if ( chordOffset.x() != 0.0 )
        angle = chordOffset.x() / dist;    
    
    // ANGLE.    
    angle += angleOffset.x();
    
    // TANGENT.
    
    if ( tangentOffset.x() != 0.0 )
    {
        angle += asin ( tangentOffset.x() / dist );
    }
    
    // Apply angle.
    
    if ( angle != 0.0 )
    {
        snlTransform transf;    
    
        transf.rotate ( angle, *axis_start, *axis_end );
    
        transf.transform ( point );
    }
}
예제 #7
0
bool NodeConnectionControl::respondToClick(APoint m_pos, MouseButton b)
{
	return fromNode && toNode && (distToLine(m_pos) <= activeRadius);
	//return (controlState == ControlState::HOVERING);
}
예제 #8
0
bool NodeConnectionControl::respondToMouse(APoint m_pos)
{
	return controlState == ControlState::CLICKING || controlState == ControlState::DRAGGING ||
			(fromNode && toNode && (distToLine(m_pos) <= activeRadius));
}
예제 #9
0
void Level::fixCoordsWithObj(LevelObj& obj, Actor* act)// f32& xx, f32& yy, f32& vx, f32& vy, f32& gx, f32& gy)
{	
	obj.state = 1;
	f32 px = act->x+act->gvx*2;
	f32 py = act->y+act->gvy*2;
	
	int dists[4];
	dists[0] = distToLine(px, py, obj.x[0], obj.y[0], obj.x[1], obj.y[1]).toint();
	dists[1] = distToLine(px, py, obj.x[1], obj.y[1], obj.x[2], obj.y[2]).toint();
	dists[2] = distToLine(px, py, obj.x[2], obj.y[2], obj.x[3], obj.y[3]).toint();
	dists[3] = distToLine(px, py, obj.x[3], obj.y[3], obj.x[0], obj.y[0]).toint();

	int best1 = -1;
	int bestd;
	for(int i = 0; i < 4; i++)
		if((dists[i] < bestd || best1 == -1)) bestd=dists[i], best1 = i;
		
	int best2 = -1;
	for(int i = 0; i < 4; i++)
		if((dists[i] < bestd || best2 == -1) && i != best1) bestd=dists[i], best2 = i;
	
	bool invalid1 = obj.neighbors[best1] != -1;
	bool invalid2 = obj.neighbors[best2] != -1;
	
	if(invalid1 && invalid2) //Corner: Just collide with the neighbor
		fixCoordsWithObj(objs->objs[obj.neighbors[best1]], act);
	else
	{
		if(invalid1)
		{
			best1 = best2;
			invalid1 = invalid2;
		}
		
		int n = best1;
		int n2 = (n+1)%4;

		f32 oldx = act->x;
		projectToLine(act->x, act->y, obj.x[n], obj.y[n], obj.x[n2], obj.y[n2]);

		f32 fx, fy;
		fx = act->vx;
		fy = act->vy;
		projectVecToLine(fx, fy, obj.y[n2], obj.x[n], obj.y[n], obj.x[n2]);

		bool bounce = obj.type == BEH_BOUNCY || (fabs(fx)+fabs(fy))>8;
		if(!bounce)
		{
			projectVecToLine(act->vx, act->vy, obj.x[n], obj.y[n], obj.x[n2], obj.y[n2]);
			
			fx = -(obj.y[n2]-obj.y[n]);
			fy = obj.x[n2]-obj.x[n];
			vecNormalize(fx, fy);
			
			act->gx = fx;
			act->gy = fy;
			
			if(fabs(act->gx) < 0.4) 
			{
				act->gx = 0;
//				act->vx = 0;
				act->x = oldx;
			}
			
			act->x += act->gx;
			act->y += act->gy;
		}
		else
		{
			addSparkles(obj);
			fx = act->vx;
			fy = act->vy;
			
			f32 nx = -(obj.y[n2]-obj.y[n]);
			f32 ny = obj.x[n2]-obj.x[n];
			vecNormalize(nx, ny);
			
			f32 dotp = -fx*nx-fy*ny;
			
			fx = fx+nx*dotp*2;
			fy = fy+ny*dotp*2;
			
			if(obj.type != BEH_BOUNCY)
			{
				fx /= 2;
				fy /= 2;
			}
			else
			{
				fx *= f32(1.7);
				fy *= f32(1.7);
			}
			
			act->vx = fx + nx/2;
			act->vy = fy + ny/2;
			
			act->x += nx*3;
			act->y += ny*3;
		}
	}
}