double Span::Parameter(const Point& p)const { double t; if(m_v.m_type == 0) { Point v0 = p - m_p; Point vs = m_v.m_p - m_p; double length = vs.length(); vs.normalize(); t = vs * v0; t = t / length; } else { // true if p lies on arc span sp (p must be on circle of span) Point vs = ~(m_p - m_v.m_c); Point v = ~(p - m_v.m_c); vs.normalize(); v.normalize(); if(m_v.m_type == -1){ vs = -vs; v = -v; } double ang = ::IncludedAngle(vs, v, m_v.m_type); double angle = IncludedAngle(); t = ang / angle; } return t; }
double Span::Length()const { if(m_v.m_type) { double radius = m_p.dist(m_v.m_c); return fabs(IncludedAngle()) * radius; } return m_p.dist(m_v.m_p); }
double Span::GetArea()const { if(m_v.m_type) { double angle = IncludedAngle(); double radius = m_p.dist(m_v.m_c); return ( 0.5 * ((m_v.m_c.x - m_p.x) * (m_v.m_c.y + m_p.y) - (m_v.m_c.x - m_v.m_p.x) * (m_v.m_c.y + m_v.m_p.y) - angle * radius * radius)); } return 0.5 * (m_v.m_p.x - m_p.x) * (m_p.y + m_v.m_p.y); }
Point CArc::MidParam(double param)const { /// returns a point which is 0-1 along arc if(fabs(param) < 0.00000000000001)return m_s; if(fabs(param - 1.0) < 0.00000000000001)return m_e; Point p; Point v = m_s - m_c; v.Rotate(param * IncludedAngle()); p = v + m_c; return p; }
Point Span::MidParam(double param)const { /// returns a point which is 0-1 along span if(fabs(param) < 0.00000000000001)return m_p; if(fabs(param - 1.0) < 0.00000000000001)return m_v.m_p; Point p; if(m_v.m_type == 0) { Point vs = m_v.m_p - m_p; p = vs * param + m_p; } else { Point v = m_p - m_v.m_c; v.Rotate(param * IncludedAngle()); p = v + m_v.m_c; } return p; }
bool Span::OnSpan(const Point& p, double* t)const { // FAST OnSpan test - assumes that p lies ON the unbounded span #if _DEBUG if(this->returnSpanProperties == false) { FAILURE(L"OnSpan - properties no set, incorrect calling code"); } #endif #if 0 if(NullSpan) { *t = 0.0; return (p == p0); } if(p == p0) { *t = 0.0; return true; } if(p == p1) { *t = 1.0; return true; } #endif bool ret; // if(p == this->p0 || p == this->p1) return true; if(dir == LINEAR) { #if 1 #if _DEBUG // check p is on line CLine cl(*this); double d = fabs(cl.Dist(p)); if( d > geoff_geometry::TOLERANCE) { FAILURE(L"OnSpan - point not on linear span, incorrect calling code"); } #endif #endif Vector2d v0(p0, p); *t = vs * v0; // ret = (*t > - geoff_geometry::TOLERANCE && *t < length + geoff_geometry::TOLERANCE); *t = *t / length; ret = (*t >= 0 && *t <= 1.0 ); } else { // true if p lies on arc span sp (p must be on circle of span) #if 1 #if _DEBUG // check that p lies on the arc double d = p.Dist(pc); if(FNE(d, radius, geoff_geometry::TOLERANCE)) { FAILURE(L"OnSpan - point not on circular span, incorrect calling code"); } #endif #endif #if 0 // alt method (faster, but doesn't provide t) Vector2d v0(p0, p); Vector2d v1(p0, p1); // check angle to point from start double cp; ret = ((cp = (dir * (v0 ^ v1))) > 0); *t = 0.0;// incorrect !!! #else Vector2d v = ~Vector2d(pc, p); v.normalise(); if(dir == CW) v = -v; double ang = IncludedAngle(vs, v, dir); *t = ang / angle; ret = (*t >= 0 && *t <= 1.0); #endif } return ret; }