211 lines
6.8 KiB
Text
211 lines
6.8 KiB
Text
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// Name: geometry.cpp
|
||
|
// Author: John Labenski
|
||
|
// Created: 07/01/02
|
||
|
// Copyright: John Labenski, 2002
|
||
|
// License: wxWidgets v2
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
|
||
|
#pragma implementation "geometry.h"
|
||
|
#endif
|
||
|
|
||
|
// For compilers that support precompilation, includes "wx/wx.h".
|
||
|
#include <wx/wxprec.h>
|
||
|
|
||
|
#ifdef __BORLANDC__
|
||
|
#pragma hdrstop
|
||
|
#endif
|
||
|
|
||
|
#include "wx/things/geometry.h"
|
||
|
|
||
|
/*
|
||
|
2.4 : How do I generate a circle through three points?
|
||
|
Let the three given points be a, b, c. Use _0 and _1 to represent x and y coordinates. The coordinates of the center p=(p_0,p_1) of the circle determined by a, b, and c are:
|
||
|
A = b_0 - a_0; B = b_1 - a_1; C = c_0 - a_0; D = c_1 - a_1;
|
||
|
E = A*(a_0 + b_0) + B*(a_1 + b_1); F = C*(a_0 + c_0) + D*(a_1 + c_1);
|
||
|
G = 2.0*(A*(c_1 - b_1)-B*(c_0 - b_0));
|
||
|
p_0 = (D*E - B*F) / G; p_1 = (A*F - C*E) / G;
|
||
|
If G is zero then the three points are collinear and no finite-radius circle through them exists. Otherwise, the radius of the circle is:
|
||
|
r^2 = (a_0 - p_0)^2 + (a_1 - p_1)^2
|
||
|
[O' Rourke (C)] p. 201. Simplified by Jim Ward.
|
||
|
*/
|
||
|
|
||
|
wxCircleDouble::wxCircleDouble(const wxPoint2DDouble &p1,
|
||
|
const wxPoint2DDouble &p2,
|
||
|
const wxPoint2DDouble &p3)
|
||
|
{
|
||
|
wxDouble A = p2.m_x - p1.m_x,
|
||
|
B = p2.m_y - p1.m_y,
|
||
|
C = p3.m_x - p1.m_x,
|
||
|
D = p3.m_y - p1.m_y;
|
||
|
|
||
|
wxDouble E = A*(p1.m_x + p2.m_x) + B*(p1.m_y + p2.m_y),
|
||
|
F = C*(p1.m_x + p3.m_x) + D*(p1.m_y + p3.m_y),
|
||
|
G = 2.0*(A*(p3.m_y - p2.m_y)-B*(p3.m_x - p2.m_x));
|
||
|
|
||
|
if (G == 0)
|
||
|
{
|
||
|
m_x = m_y = m_r = 0;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_x = (D*E - B*F) / G,
|
||
|
m_y = (A*F - C*E) / G;
|
||
|
m_r = sqrt( (p1.m_x - m_x)*(p1.m_x - m_x) + (p1.m_y - m_y)*(p1.m_y - m_y) );
|
||
|
}
|
||
|
|
||
|
int wxCircleDouble::IntersectLine( const wxRay2DDouble &line,
|
||
|
wxPoint2DDouble *pt1,
|
||
|
wxPoint2DDouble *pt2 ) const
|
||
|
{
|
||
|
//if (line.GetDistanceToPoint(m_origin) > m_r) return 0;
|
||
|
|
||
|
wxDouble l1_x = m_x-m_r, l1_y = line.GetYFromX(l1_x);
|
||
|
wxDouble l2_x = m_x+m_r, l2_y = line.GetYFromX(l2_x);
|
||
|
|
||
|
// quick check to see it it intersects at all
|
||
|
//wxDouble top = m_origin.m_y-m_r, bot = m_origin.m_y+m_r;
|
||
|
//if (((l1_y < top)&&(l2_y < top))||((l1_y > bot)&&(l2_y > bot))) return 0;
|
||
|
|
||
|
wxDouble l2_l1_x = l2_x - l1_x, l2_l1_y = l2_y - l1_y;
|
||
|
|
||
|
wxDouble a = l2_l1_x*l2_l1_x + l2_l1_y*l2_l1_y;
|
||
|
wxDouble b = 2.0 * (l2_l1_x * (l1_x - m_x) + l2_l1_y * (l1_y - m_y) );
|
||
|
|
||
|
wxDouble c = m_x*m_x + m_y*m_y + l1_x*l1_x + l1_y*l1_y - 2.0*(m_x*l1_x + m_y*l1_y) - m_r*m_r;
|
||
|
wxDouble det = b*b - 4.0*a*c;
|
||
|
|
||
|
if ( det < 0 )
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
else if ( det == 0 )
|
||
|
{
|
||
|
if (pt1)
|
||
|
{
|
||
|
wxDouble u = -b/(2.0*a);
|
||
|
pt1->m_x = l2_x + u*l2_l1_x;
|
||
|
pt1->m_y = l2_y + u*l2_l1_y;
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
// else det > 0 so 2 points intersect
|
||
|
wxDouble e = sqrt(det);
|
||
|
|
||
|
if (pt1)
|
||
|
{
|
||
|
wxDouble u1 = (-b - e)/( 2.0*a );
|
||
|
pt1->m_x = l1_x + u1*l2_l1_x;
|
||
|
pt1->m_y = l1_y + u1*l2_l1_y;
|
||
|
}
|
||
|
if (pt2)
|
||
|
{
|
||
|
wxDouble u2 = (-b + e)/( 2.0*a );
|
||
|
pt2->m_x = l1_x + u2*l2_l1_x;
|
||
|
pt2->m_y = l1_y + u2*l2_l1_y;
|
||
|
}
|
||
|
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
int wxEllipseInt::IntersectLine( const wxLine2DInt &line,
|
||
|
wxPoint2DInt &pt1,
|
||
|
wxPoint2DInt &pt2 ) const
|
||
|
{
|
||
|
|
||
|
//Intersection.intersectEllipseLine = function(c, rx, ry, a1, a2) {
|
||
|
//var result;
|
||
|
//line.m_pt // var origin = new Vector2D(a1.x, a1.y);
|
||
|
wxPoint2DInt dir = pt2 - p21; // var dir = Vector2D.fromPoints(a1, a2);
|
||
|
//m_origin //var center = new Vector2D(c.x, c.y);
|
||
|
wxPoint2DInt diff = line.m_pt - m_origin; //var diff = origin.subtract(center);
|
||
|
|
||
|
//var mDir = new Vector2D( dir.x/(rx*rx), dir.y/(ry*ry) );
|
||
|
wxPoint2DDouble mDir = wxPoint2DDouble(wxDouble(dir.m_x)/(m_radius.m_x*m_radius.m_x),
|
||
|
wxDouble(dir.m_y)/(m_radius.m_y*m_radius.m_y));
|
||
|
//var mDiff = new Vector2D( diff.x/(rx*rx), diff.y/(ry*ry) );
|
||
|
wxPoint2DDouble mDiff = wxPoint2DDouble(wxDouble(diff.m_x)/(m_radius.m_x*m_radius.m_x),
|
||
|
wxDouble(diff.m_y)/(m_radius.m_y*m_radius.m_y));
|
||
|
|
||
|
wxDouble a = dir.GetDotProduct(mDir); //var a = dir.dot(mDir);
|
||
|
wxDouble b = dir.GetDotProduct(mDiff); //var b = dir.dot(mDiff);
|
||
|
wxDouble c = diff.GetDotProduct(m_diff); //var c = diff.dot(mDiff) - 1.0;
|
||
|
wxDouble d = b*b - a*c; //var d = b*b - a*c;
|
||
|
|
||
|
if ( d < 0 )
|
||
|
{
|
||
|
return 0; //result = new Intersection("Outside");
|
||
|
}
|
||
|
else if ( d > 0 )
|
||
|
{
|
||
|
wxDouble root = sqrt(d); //var root = Math.sqrt(d);
|
||
|
wxDouble t_a = (-b - root)/a; //var t_a = (-b - root) / a;
|
||
|
wxDouble t_b = (-b + root)/a; //var t_b = (-b + root) / a;
|
||
|
|
||
|
if ( (t_a < 0 || 1 < t_a) && (t_b < 0 || 1 < t_b) )
|
||
|
{
|
||
|
if ( (t_a < 0 && t_b < 0) || (t_a > 1 && t_b > 1) )
|
||
|
result = new Intersection("Outside");
|
||
|
else
|
||
|
result = new Intersection("Inside");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
result = new Intersection("Intersection");
|
||
|
if ( 0 <= t_a && t_a <= 1 )
|
||
|
result.appendPoint( a1.lerp(a2, t_a) );
|
||
|
if ( 0 <= t_b && t_b <= 1 )
|
||
|
result.appendPoint( a1.lerp(a2, t_b) );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
var t = -b/a;
|
||
|
if ( 0 <= t && t <= 1 )
|
||
|
{
|
||
|
result = new Intersection("Intersection");
|
||
|
result.appendPoint( a1.lerp(a2, t) );
|
||
|
} else
|
||
|
{
|
||
|
result = new Intersection("Outside");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
*/
|
||
|
/*
|
||
|
> I am looking for the algorithm to calculate the intersection of a line
|
||
|
with
|
||
|
> an ellipse, that is not necessarily parrallel to x,y axis.
|
||
|
>
|
||
|
> I cannot find anything that is easy to understand.
|
||
|
|
||
|
The ellipse can be represented by a quadratic polynomial,
|
||
|
a00+a10*x+a01*y+a20*x^2+a11*x*y+a02*y^2 = 0.
|
||
|
The line is b0+b1*x+b2*y = 0 where one of b1 or b2 is
|
||
|
not zero. For the sake of argument, suppose b2 is not
|
||
|
zero. Solve for y = -(b0+b1*x)/b2. Replace this in the
|
||
|
quadratic equation and multiply through by b2^2 to get
|
||
|
Q(x) = c0 + c1*x + c2*x^2 = 0 where
|
||
|
c0 = a02*b0^2-a01*b0*b2+a00*b2^2
|
||
|
c1 = 2*a02*b0*b1-a11*b0*b2-a01*b1*b2+a10*b2^2
|
||
|
c2 = a02*b1^2-a11*b1*b2+a02*b2^2
|
||
|
If Q(x) has no real roots, the line and ellipse do not intersect.
|
||
|
If Q(x) has a single, repeated real root x0, the line and ellipse
|
||
|
are tangent. The y-value is y0 = -(b0+b1*x0)/b2. If Q(x)
|
||
|
has two distinct real roots x0 and x1, the line and ellipse
|
||
|
intersect in two points (x0,y0) and (x1,y1) where
|
||
|
y0 = -(b0+b1*x0)/b2 and y1 = -(b0+b1*x1)/b2.
|
||
|
|
||
|
*/
|