GL::Matrix matrix;
matrix.translate(track.get_position());
matrix.rotate(track.get_rotation(), 0, 0, 1);
- matrix.rotate(track.get_slope()/track.get_type().get_total_length(), 0, -1, 0);
+ matrix.rotate(track.get_tilt(), 0, -1, 0);
return matrix;
}
string info = format("%d %s", otype.get_article_number(), otype.get_description());
if(Track *track = dynamic_cast<Track *>(obj))
{
- const TrackType &ttype = track->get_type();
- if(mode!=CATALOGUE && abs(track->get_slope())>1e-4)
- info += format(" (slope %.1f%%)", abs(track->get_slope()/ttype.get_total_length()*100));
+ if(mode!=CATALOGUE && abs(track->get_tilt()).radians()>1e-4)
+ info += format(" (slope %.1f%%)", abs(tan(track->get_tilt())*100));
if(track->get_turnout_id())
info += format(" (turnout %d)", track->get_turnout_id());
else if(track->get_sensor_id())
float z = 0;
for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
{
- z += i->object->get_position().z;
- if(Track *track = dynamic_cast<Track *>(i->object))
- z += track->get_slope()/2;
+ unsigned nsn = i->object->get_n_snap_nodes();
+ for(unsigned j=0; j<nsn; ++j)
+ z += i->object->get_snap_node(j).position.z/nsn;
}
z /= static_cast<int>(objects.size());
Vector p = i->object->get_position();
i->object->set_position(Vector(p.x, p.y, z));
if(Track *track = dynamic_cast<Track *>(i->object))
- track->set_slope(0);
+ track->set_tilt(Angle::zero());
}
update_objects();
while((end_z-start_z)*dir/total_len>cur_slope+0.025 && order.size()>2)
{
cur_slope += 0.025;
+ Angle tilt = Geometry::atan(cur_slope);
+
+ set_slope(order.front(), start_z, tilt);
+ start_z += order.front().track->get_type().get_path_length(0)*dir*cur_slope;
+ total_len -= order.front().track->get_type().get_path_length(0);
+ order.pop_front();
- float dz = order.front().track->get_type().get_total_length()*dir*cur_slope;
- set_slope(order.front(), start_z, dz);
- start_z += dz;
- total_len -= order.front().track->get_type().get_total_length();
- order.erase(order.begin());
-
- dz = order.back().track->get_type().get_total_length()*dir*cur_slope;
- set_slope(order.back(), end_z-dz, dz);
- end_z -= dz;
- total_len -= order.back().track->get_type().get_total_length();
- order.erase(--order.end());
+ end_z -= order.back().track->get_type().get_path_length(0)*dir*cur_slope;
+ set_slope(order.back(), end_z, tilt);
+ total_len -= order.back().track->get_type().get_path_length(0);
+ order.pop_back();
}
}
float cur_z = start_z;
+ Angle tilt = Geometry::atan((end_z-start_z)/total_len);
for(list<TrackOrder>::iterator i=order.begin(); i!=order.end(); ++i)
{
- float dz = i->track->get_type().get_total_length()*(end_z-start_z)/total_len;
- set_slope(*i, cur_z, dz);
- cur_z += dz;
+ set_slope(*i, cur_z, tilt);
+ cur_z += i->track->get_type().get_path_length(0)*(end_z-start_z)/total_len;
}
update_objects();
}
}
-void Manipulator::set_slope(TrackOrder &track, float z, float dz)
+void Manipulator::set_slope(TrackOrder &track, float z, const Angle &tilt)
{
const Vector &p = track.track->get_position();
+ float dz = tan(tilt)*track.track->get_type().get_path_length(0);
if(track.rev)
{
track.track->set_position(Vector(p.x, p.y, z+dz));
- track.track->set_slope(-dz);
+ track.track->set_tilt(-tilt);
}
else
{
track.track->set_position(Vector(p.x, p.y, z));
- track.track->set_slope(dz);
+ track.track->set_tilt(tilt);
}
}
void selection_changed();
void update_objects();
void update_neighbors();
- void set_slope(TrackOrder &, float, float);
+ void set_slope(TrackOrder &, float, const R2C2::Angle &);
std::vector<R2C2::Track *> create_straight(const R2C2::Vector &, const R2C2::Angle &, float, float);
};
Layout &layout;
Vector position;
Angle rotation;
+ Angle tilt;
Object(Layout &l): layout(l) { }
public:
Layout &get_layout() const { return layout; }
virtual void set_position(const Vector &) = 0;
virtual void set_rotation(const Angle &) = 0;
+ virtual void set_tilt(const Angle &) = 0;
const Vector &get_position() const { return position; }
const Angle &get_rotation() const { return rotation; }
+ const Angle &get_tilt() const { return tilt; }
virtual Object *get_parent() const { return 0; }
virtual unsigned get_n_snap_nodes() const { return 0; }
void set_address(unsigned);
virtual void set_position(const Vector &);
virtual void set_rotation(const Angle &);
+ virtual void set_tilt(const Angle &) { }
private:
void update_location();
public:
void Track::set_position(const Vector &p)
{
position = p;
- for(vector<Track *>::const_iterator i=links.begin(); i!=links.end(); ++i)
- if(*i)
- (*i)->check_slope();
+ propagate_slope();
}
void Track::set_rotation(const Angle &r)
rotation = wrap_positive(r);
}
-void Track::set_slope(float s)
+void Track::set_tilt(const Angle &t)
{
if(links.size()!=2)
return;
- slope = s;
+ tilt = t;
+ slope = tan(tilt)*type.get_path_length(0);
+ propagate_slope();
}
void Track::set_flex(bool f)
flex = f;
}
+void Track::propagate_slope()
+{
+ for(vector<Track *>::const_iterator i=links.begin(); i!=links.end(); ++i)
+ if(*i)
+ (*i)->check_slope();
+}
+
void Track::check_slope()
{
if(links.size()!=2)
Vector epp1 = links[1]->get_snap_node(links[1]->get_link_slot(*this)).position;
position.z = epp0.z;
slope = epp1.z-position.z;
+ tilt = Geometry::atan(slope/type.get_path_length(0));
}
else
{
p.dir += rotation;
if(type.get_endpoints().size()==2)
{
- float len = type.get_path_length(path);
- float grade = slope/len;
+ float grade = tan(tilt);
if(epi==0)
{
p.pos.z += grade*d;
{
st.push_back((DataFile::Statement("position"), position.x, position.y, position.z));
st.push_back((DataFile::Statement("rotation"), rotation.radians()));
- st.push_back((DataFile::Statement("slope"), slope));
+ st.push_back((DataFile::Statement("tilt"), tilt.radians()));
if(turnout_id)
st.push_back((DataFile::Statement("turnout_id"), turnout_id));
if(sensor_id)
{
add("position", &Loader::position);
add("rotation", &Loader::rotation);
- add("slope", &Track::slope);
+ add("tilt", &Loader::tilt);
add("turnout_id", &Loader::turnout_id);
add("sensor_id", &Loader::sensor_id);
add("flex", &Track::flex);
+
+ // deprecated
+ add("slope", &Loader::slope);
}
void Track::Loader::position(float x, float y, float z)
obj.set_sensor_id(id);
}
+void Track::Loader::slope(float s)
+{
+ tilt(atan(s/obj.type.get_path_length(0)));
+}
+
+void Track::Loader::tilt(float t)
+{
+ if(obj.links.size()!=2)
+ return;
+
+ obj.tilt = Angle::from_radians(t);
+ obj.slope = tan(t)*obj.type.get_path_length(0);
+}
+
void Track::Loader::turnout_id(unsigned id)
{
obj.set_turnout_id(id);
void position(float, float, float);
void rotation(float);
void sensor_id(unsigned);
+ void slope(float);
+ void tilt(float);
void turnout_id(unsigned);
};
Block &get_block() const;
virtual void set_position(const Vector &);
virtual void set_rotation(const Angle &);
- void set_slope(float);
+ virtual void set_tilt(const Angle &);
void set_flex(bool);
- float get_slope() const { return slope; }
bool get_flex() const { return flex; }
private:
+ void propagate_slope();
void check_slope();
public:
// TODO implement these - should call place() with suitable parameters
virtual void set_position(const Vector &) { }
virtual void set_rotation(const Angle &) { }
+ virtual void set_tilt(const Angle &) { }
void place(const TrackIter &, float, PlaceMode = CENTER);
void unplace();
void advance(float);