-/* $Id$
-
-This file is part of R²C²
-Copyright © 2006-2010 Mikkosoft Productions, Mikko Rasa
-Distributed under the GPL
-*/
-
#include <cmath>
#include "trackpart.h"
float s = sin(a);
float rx = radius*sin(dir);
float ry = -radius*cos(dir);
- result.pos = Point(pos.x+c*rx-s*ry-rx, pos.y+c*ry+s*rx-ry);
+ result.pos = Vector(pos.x+c*rx-s*ry-rx, pos.y+c*ry+s*rx-ry);
result.dir = dir+a;
}
else
{
- result.pos = Point(pos.x+cos(dir)*d, pos.y+sin(dir)*d);
+ result.pos = Vector(pos.x+cos(dir)*d, pos.y+sin(dir)*d);
result.dir = dir;
}
return result;
}
+TrackPoint TrackPart::get_nearest_point(const Vector &p) const
+{
+ TrackPoint tp;
+ float c = cos(dir);
+ float s = sin(dir);
+ if(radius)
+ {
+ Vector v(p.x-pos.x+radius*s, p.y-pos.y-radius*c);
+ float a = atan2(v.y, v.x)+M_PI/2-dir;
+ if(radius<0)
+ a = M_PI-a;
+ while(a<length/2-M_PI)
+ a += M_PI*2;
+ while(a>length/2+M_PI)
+ a -= M_PI*2;
+ a = min(max(a, 0.0f), length);
+ if(radius<0)
+ a = -a;
+ tp.pos = Vector(pos.x+radius*(sin(dir+a)-s), pos.y+radius*(c-cos(dir+a)));
+ tp.dir = dir+a;
+ }
+ else
+ {
+ Vector v(p.x-pos.x, p.y-pos.y);
+ float d = min(max(c*v.x+s*v.y, 0.0f), length);
+ tp.pos = Vector(pos.x+c*d, pos.y+s*d);
+ tp.dir = dir;
+ }
+ return tp;
+}
+
void TrackPart::check_link(TrackPart &other)
{
unsigned n_eps = (dead_end ? 1 : 2);
TrackPart *TrackPart::get_link(unsigned i) const
{
if(i>=2)
- throw InvalidParameterValue("Index out of range");
+ throw out_of_range("TrackPart::get_link");
return links[i];
}
+bool TrackPart::collide_ray(const Vector &start, const Vector &ray, float width) const
+{
+ Vector local_start(start.x-pos.x, start.y-pos.y, start.z);
+ float c = cos(dir);
+ float s = sin(dir);
+ local_start = Vector(c*local_start.x+s*local_start.y, c*local_start.y-s*local_start.x, local_start.z);
+ Vector local_ray(c*ray.x+s*ray.y, c*ray.y-s*ray.x, ray.z);
+
+ float d = -local_start.z/local_ray.z;
+ if(d<0)
+ return false;
+
+ Vector base(local_start.x+d*local_ray.x, local_start.y+d*local_ray.y);
+
+ if(radius)
+ {
+ base.y -= radius;
+ if(radius<0)
+ base.y = -base.y;
+ float r = sqrt(base.x*base.x+base.y*base.y)-abs(radius);
+ float a = atan2(base.x, -base.y);
+ return (a>=0 && a<=length && r>=-width/2 && r<=width/2);
+ }
+ else
+ return (base.x>=0 && base.x<=length && base.y>=-width/2 && base.y<=width/2);
+}
+
TrackPart::Loader::Loader(TrackPart &p):
- Msp::DataFile::BasicLoader<TrackPart>(p)
+ Msp::DataFile::ObjectLoader<TrackPart>(p)
{
add("start", &Loader::start);
add("length", &TrackPart::length);
void TrackPart::Loader::start(float x, float y, float d)
{
- obj.pos = Point(x, y);
+ obj.pos = Vector(x, y);
obj.dir = d;
}