]> git.tdb.fi Git - r2c2.git/blobdiff - source/libr2c2/vehicle.cpp
Things with different gauges don't go together
[r2c2.git] / source / libr2c2 / vehicle.cpp
index 0316887fded747e90e2d62fa07afa3fd287de499..6615fb25b768cebf6c05003eb1e52fba5d2efcd2 100644 (file)
@@ -33,6 +33,8 @@ Vehicle::Vehicle(Layout &l, const VehicleType &t):
                for(unsigned j=0; j<i->axles.size(); ++j)
                        i->axles[j] = &axles[i->type->first_axle+j];
 
+       update_rods();
+
        layout.add(*this);
 }
 
@@ -104,6 +106,9 @@ void Vehicle::place(const TrackOffsetIter &t, VehiclePlacement::Anchor a)
 {
        if(!t)
                throw invalid_argument("Vehicle::place");
+       float gauge_ratio = t->get_type().get_gauge()/type.get_gauge();
+       if(gauge_ratio<0.99 || gauge_ratio>1.01)
+               throw logic_error("Incompatible gauge");
 
        placement.place(t, a);
 
@@ -173,7 +178,8 @@ void Vehicle::update_position(int sign)
 {
        OrientedPoint p = placement.get_point();
        position = p.position;
-       position.z += layout.get_catalogue().get_rail_elevation();
+       // TODO Move the z adjustment to VehiclePlacement
+       position.z += placement.get_position(VehiclePlacement::FRONT_AXLE)->get_type().get_appearance().get_rail_elevation();
        rotation = p.rotation;
        tilt = p.tilt;
 
@@ -245,7 +251,7 @@ void Vehicle::propagate_backward()
 
 void Vehicle::check_sensor(const TrackOffsetIter &t, unsigned &sensor, bool release)
 {
-       unsigned s = t->get_sensor_id();
+       unsigned s = t->get_sensor_address();
        if(s!=sensor)
        {
                unsigned old = sensor;
@@ -267,55 +273,67 @@ void Vehicle::turn_axles(float d)
 
 void Vehicle::update_rods()
 {
-       for(vector<Rod>::iterator i=rods.begin(); i!=rods.end(); ++i)
-       {
-               if(i->type->pivot==VehicleType::Rod::BODY)
-                       i->position = i->type->pivot_point;
-               else if(i->type->pivot==VehicleType::Rod::AXLE)
-               {
-                       const Axle &axle = get_fixed_axle(i->type->pivot_index);
-                       const Vector &pp = i->type->pivot_point;
-                       Transform trans = Transform::rotation(axle.angle, Vector(0, -1, 0));
-                       i->position = Vector(axle.type->position, 0, axle.type->wheel_dia/2)+trans.transform(pp);
-               }
-               else if(i->type->pivot==VehicleType::Rod::ROD)
-               {
-                       const Rod &prod = get_rod(i->type->pivot_index);
-                       const Vector &pos = prod.position;
-                       const Vector &off = i->type->pivot_point;
-                       Transform trans = Transform::rotation(prod.angle, Vector(0, 1, 0));
-                       i->position = pos+trans.transform(off);
-               }
+       if(rods.empty())
+               return;
 
-               if(i->type->connect_index>=0)
+       for(unsigned n=0; n<10; ++n)
+       {
+               float max_d = 0;
+               for(vector<Rod>::iterator i=rods.begin(); i!=rods.end(); ++i)
                {
-                       Rod &crod = rods[i->type->connect_index];
-                       if(i->type->limit==VehicleType::Rod::ROTATE && crod.type->limit==VehicleType::Rod::SLIDE_X)
-                       {
-                               Vector span = crod.position+i->type->connect_offset-i->position;
-                               float cd = i->type->connect_point.norm();
-                               Angle ca = Geometry::atan2(i->type->connect_point.z, i->type->connect_point.x);
-                               span.x = sqrt(cd*cd-span.z*span.z)*(span.x>0 ? 1 : -1);
-                               i->angle = Geometry::atan2(span.z, span.x)-ca;
-                               crod.position.x = i->position.x+span.x-i->type->connect_offset.x;
-                       }
-                       else if(i->type->limit==VehicleType::Rod::ROTATE && crod.type->limit==VehicleType::Rod::ROTATE)
+                       const vector<VehicleType::RodConstraint> &constraints = i->type->constraints;
+                       for(vector<VehicleType::RodConstraint>::const_iterator j=constraints.begin(); j!=constraints.end(); ++j)
                        {
-                               Vector span = crod.position-i->position;
-                               float d = span.norm();
-                               float cd1 = i->type->connect_point.norm();
-                               float cd2 = i->type->connect_offset.norm();
-                               float a = (d*d+cd1*cd1-cd2*cd2)/(2*d);
-                               float b = sqrt(cd1*cd1-a*a);
-                               float sign = (cross(i->type->connect_point, span).y>0 ? 1 : -1);
-                               Vector conn = Vector(span.x*a-span.z*b, 0, span.z*a+span.x*b)/(d*sign);
-                               Angle ca1 = Geometry::atan2(i->type->connect_point.z, i->type->connect_point.x);
-                               Angle ca2 = Geometry::atan2(i->type->connect_offset.z, i->type->connect_offset.x);
-                               i->angle = Geometry::atan2(conn.z, conn.x)-ca1;
-                               crod.angle = Geometry::atan2(conn.z-span.z, conn.x-span.x)-ca2;
+                               float d = resolve_rod_constraint(*i, *j);
+                               max_d = max(d, max_d);
                        }
                }
+
+               if(max_d<0.0001)
+                       break;
+       }
+}
+
+float Vehicle::resolve_rod_constraint(Rod &rod, const VehicleType::RodConstraint &cns)
+{
+       Vector target;
+       if(cns.target==VehicleType::RodConstraint::BODY)
+               target = cns.target_position;
+       else if(cns.target==VehicleType::RodConstraint::BOGIE)
+               ;  // TODO currently rods must lie in the xz plane of the body
+       else if(cns.target==VehicleType::RodConstraint::AXLE)
+       {
+               const Axle &axle = get_axle(cns.target_index);
+               target = Vector(axle.type->position, 0, axle.type->wheel_dia/2);
+               target += Transform::rotation(axle.angle, Vector(0, 1, 0)).transform(cns.target_position);
+       }
+       else if(cns.target==VehicleType::RodConstraint::ROD)
+       {
+               const Rod &trod = get_rod(cns.target_index);
+               target = trod.position;
+               target += Transform::rotation(trod.angle, Vector(0, -1, 0)).transform(cns.target_position);
+       }
+
+       Vector old_position = rod.position;
+       if(cns.type==VehicleType::RodConstraint::MOVE)
+               rod.position = target-Transform::rotation(rod.angle, Vector(0, -1, 0)).transform(cns.local_position);
+       else if(cns.type==VehicleType::RodConstraint::SLIDE)
+       {
+               Vector d = rod.position-target;
+               rod.position = target+cns.axis*dot(d, cns.axis);
+               rod.angle = Angle::zero();
+       }
+       else if(cns.type==VehicleType::RodConstraint::ROTATE)
+       {
+               Angle old_angle = rod.angle;
+               Vector d = target-rod.position;
+               rod.angle = Geometry::atan2<float>(d.z, d.x);
+               if(cns.local_position.x || cns.local_position.z)
+                       rod.angle -= Geometry::atan2<float>(cns.local_position.z, cns.local_position.x);
+               return abs(rod.angle-old_angle).radians()*cns.local_position.norm();
        }
+
+       return distance(old_position, rod.position);
 }
 
 unsigned Vehicle::get_n_link_slots() const
@@ -341,6 +359,14 @@ int Vehicle::get_link_slot(const Object &other) const
                return -1;
 }
 
+bool Vehicle::collide_ray(const Ray &ray, float *d) const
+{
+       if(is_placed())
+               return Object::collide_ray(ray, d);
+       else
+               return false;
+}
+
 
 Vehicle::Axle::Axle(const VehicleType::Axle &t):
        type(&t)
@@ -354,7 +380,8 @@ Vehicle::Bogie::Bogie(const VehicleType::Bogie &t):
 
 
 Vehicle::Rod::Rod(const VehicleType::Rod &t):
-       type(&t)
+       type(&t),
+       position(t.initial_position)
 { }
 
 } // namespace R2C2