X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibr2c2%2Ftrackpart.cpp;h=71845bb73c2c22591d3f99b59aaf4d455b2d7988;hb=e75f12451201fb6540ad2155e8796c2b5aee8d4c;hp=f677c703ee5a7e89f7ffa9d241fbaa69754f433c;hpb=f8a7788cee0261babfc4c804a58515aad6dfbc3d;p=r2c2.git diff --git a/source/libr2c2/trackpart.cpp b/source/libr2c2/trackpart.cpp index f677c70..71845bb 100644 --- a/source/libr2c2/trackpart.cpp +++ b/source/libr2c2/trackpart.cpp @@ -1,10 +1,3 @@ -/* $Id$ - -This file is part of R²C² -Copyright © 2006-2010 Mikkosoft Productions, Mikko Rasa -Distributed under the GPL -*/ - #include #include "trackpart.h" @@ -55,6 +48,37 @@ TrackPoint TrackPart::get_point(float d) const 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(alength/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); @@ -88,13 +112,40 @@ void TrackPart::check_link(TrackPart &other) 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(p) + Msp::DataFile::ObjectLoader(p) { add("start", &Loader::start); add("length", &TrackPart::length);