prev(0),
direction(0),
bogie_dirs(type.get_bogies().size()),
+ axle_angles(1),
+ rods(type.get_rods().size()),
front_sensor(0),
back_sensor(0)
{
layout.add_vehicle(*this);
+
+ axle_angles.front().resize(type.get_axles().size(), 0.0f);
+ const vector<VehicleType::Bogie> &bogies = type.get_bogies();
+ for(vector<VehicleType::Bogie>::const_iterator i=bogies.begin(); i!=bogies.end(); ++i)
+ axle_angles.push_back(vector<float>(i->axles.size(), 0.0f));
}
Vehicle::~Vehicle()
{
track_pos.advance(d);
update_position();
+ turn_axles(d);
propagate_position();
}
return bogie_dirs[i];
}
+float Vehicle::get_axle_angle(unsigned i) const
+{
+ if(i>=axle_angles[0].size())
+ throw InvalidParameterValue("Axle index out of range");
+ return axle_angles[0][i];
+}
+
+float Vehicle::get_bogie_axle_angle(unsigned i, unsigned j) const
+{
+ if(i+1>=axle_angles.size())
+ throw InvalidParameterValue("Bogie index out of range");
+ if(j>=axle_angles[i+1].size())
+ throw InvalidParameterValue("Axle index out of range");
+ return axle_angles[i+1][j];
+}
+
+const Point &Vehicle::get_rod_position(unsigned i) const
+{
+ if(i>=rods.size())
+ throw InvalidParameterValue("Rod index out of range");
+ return rods[i].position;
+}
+
+float Vehicle::get_rod_angle(unsigned i) const
+{
+ if(i>=rods.size())
+ throw InvalidParameterValue("Rod index out of range");
+ return rods[i].angle;
+}
+
void Vehicle::update_position()
{
TrackPoint tp;
track_pos.advance(sign*(tdist-dist));
update_position();
+ turn_axles(sign*(tdist-dist));
}
void Vehicle::propagate_position()
}
}
+void Vehicle::turn_axles(float d)
+{
+ const vector<VehicleType::Axle> &axles = type.get_axles();
+ const vector<VehicleType::Bogie> &bogies = type.get_bogies();
+ for(unsigned i=0; i<axle_angles.size(); ++i)
+ for(unsigned j=0; j<axle_angles[i].size(); ++j)
+ {
+ const VehicleType::Axle &axle = (i==0 ? axles[j] : bogies[i-1].axles[j]);
+ axle_angles[i][j] += d*2/axle.wheel_dia;
+ }
+
+ update_rods();
+}
+
+void Vehicle::update_rods()
+{
+ const vector<VehicleType::Rod> &trods = type.get_rods();
+ for(unsigned i=0; i<trods.size(); ++i)
+ {
+ const VehicleType::Rod &rod = trods[i];
+ if(rod.pivot==VehicleType::Rod::BODY)
+ rods[i].position = rod.pivot_point;
+ else if(rod.pivot==VehicleType::Rod::AXLE)
+ {
+ const VehicleType::Axle &axle = type.get_axles()[rod.pivot_index];
+ float angle = axle_angles[0][rod.pivot_index];
+ float c = cos(angle);
+ float s = sin(angle);
+ const Point &pp = rod.pivot_point;
+ rods[i].position = Point(axle.position+pp.x*c+pp.z*s, pp.y, axle.wheel_dia/2+pp.z*c-pp.x*s);
+ }
+ else if(rod.pivot==VehicleType::Rod::ROD)
+ {
+ float angle = rods[rod.pivot_index].angle;
+ float c = cos(angle);
+ float s = sin(angle);
+ const Point &pos = rods[rod.pivot_index].position;
+ const Point &off = rod.pivot_point;
+ rods[i].position = Point(pos.x+off.x*c-off.z*s, pos.y+off.y, pos.z+off.z*c+off.x*s);
+ }
+
+ if(rod.connect_index>=0)
+ {
+ const VehicleType::Rod &crod = trods[rod.connect_index];
+ if(rod.limit==VehicleType::Rod::ROTATE && crod.limit==VehicleType::Rod::SLIDE_X)
+ {
+ float dx = (rods[rod.connect_index].position.x+rod.connect_offset.x)-rods[i].position.x;
+ float dz = (rods[rod.connect_index].position.z+rod.connect_offset.z)-rods[i].position.z;
+ float cd = sqrt(rod.connect_point.x*rod.connect_point.x+rod.connect_point.z*rod.connect_point.z);
+ float ca = atan2(rod.connect_point.z, rod.connect_point.x);
+ dx = sqrt(cd*cd-dz*dz)*(dx>0 ? 1 : -1);
+ rods[i].angle = atan2(dz, dx)-ca;
+ rods[rod.connect_index].position.x = rods[i].position.x+dx-rod.connect_offset.x;
+ }
+ else if(rod.limit==VehicleType::Rod::ROTATE && crod.limit==VehicleType::Rod::ROTATE)
+ {
+ float dx = rods[rod.connect_index].position.x-rods[i].position.x;
+ float dz = rods[rod.connect_index].position.z-rods[i].position.z;
+ float d = sqrt(dx*dx+dz*dz);
+ float cd1 = sqrt(rod.connect_point.x*rod.connect_point.x+rod.connect_point.z*rod.connect_point.z);
+ float cd2 = sqrt(rod.connect_offset.x*rod.connect_offset.x+rod.connect_offset.z*rod.connect_offset.z);
+ float a = (d*d+cd1*cd1-cd2*cd2)/(2*d);
+ float b = sqrt(cd1*cd1-a*a);
+ float sign = (dx*rod.connect_point.z-dz*rod.connect_point.x>0 ? 1 : -1);
+ float cx = (dx*a-dz*b*sign)/d;
+ float cz = (dz*a+dx*b*sign)/d;
+ float ca1 = atan2(rod.connect_point.z, rod.connect_point.x);
+ float ca2 = atan2(rod.connect_offset.z, rod.connect_offset.x);
+ rods[i].angle = atan2(cz, cx)-ca1;
+ rods[rod.connect_index].angle = atan2(cz-dz, cx-dx)-ca2;
+ }
+ }
+ }
+}
+
void Vehicle::adjust_for_distance(TrackPosition &front, TrackPosition &back, float tdist, float ratio) const
{
float margin = 0.01*layout.get_catalogue().get_scale();
return TrackPoint();
}
+
+Vehicle::Rod::Rod():
+ angle(0)
+{ }
+
} // namespace R2C2