using namespace Msp;
using namespace R2C2;
-ExtendTool::ExtendTool(Designer &d, Input::Mouse &m, const set<Object *> &o):
+ExtendTool::ExtendTool(Designer &d, Input::Mouse &m, const set<Object *> &objects):
Tool(d, m),
- objects(o),
accepted(false)
{
- bool ok = false;
- for(set<Object *>::const_iterator i=objects.begin(); (!ok && i!=objects.end()); ++i)
- if(Track *track = dynamic_cast<Track *>(*i))
+ for(set<Object *>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
+ if(Track *t = dynamic_cast<Track *>(*i))
{
- const vector<Track *> &links = track->get_links();
- for(vector<Track *>::const_iterator j=links.begin(); (!ok && j!=links.end()); ++j)
- ok = !*j;
+ unsigned nls = t->get_n_link_slots();
+ for(unsigned j=0; j<nls; ++j)
+ if(!t->get_link(j))
+ unlinked_endpoints.push_back(TrackIter(t, j));
}
- if(!ok)
+ if(unlinked_endpoints.empty())
{
done = true;
set_status("No free endpoints");
void ExtendTool::connect()
{
- if(objects.size()!=2)
- {
- signal_status.emit("Exactly two tracks must be selected");
- return;
- }
-
- Track *track1 = dynamic_cast<Track *>(*objects.begin());
- Track *track2 = dynamic_cast<Track *>(*--objects.end());
- if(!track1 || !track2)
- {
- signal_status.emit("Exactly two tracks must be selected");
- return;
- }
-
float limit = designer.get_layout().get_catalogue().get_gauge()/10;
- Snap sn1;
+ Track *start_track = 0;
+ Track *end_track = 0;
+ Snap start_sn;
bool ok = false;
float gap = 0;
- unsigned nls1 = track1->get_n_link_slots();
- unsigned nls2 = track2->get_n_link_slots();
- for(unsigned i=0; i<nls1; ++i)
+ for(vector<TrackIter>::const_iterator i=unlinked_endpoints.begin(); i!=unlinked_endpoints.end(); ++i)
{
- if(track1->get_link(i))
- continue;
-
- sn1 = track1->get_snap_node(i);
+ start_sn = (*i)->get_snap_node(i->entry());
- for(unsigned j=0; j<nls2; ++j)
+ for(vector<TrackIter>::const_iterator j=i; ++j!=unlinked_endpoints.end(); )
{
- if(track2->get_link(j))
- continue;
+ Snap end_sn = (*j)->get_snap_node(j->entry());
- Snap sn2 = track2->get_snap_node(j);
-
- float dz = sn2.position.z-sn1.position.z;
+ float dz = end_sn.position.z-start_sn.position.z;
if(abs(dz)>0.02)
continue;
- Angle adiff = wrap_balanced(sn1.rotation+Angle::half_turn()-sn2.rotation);
+ Angle adiff = wrap_balanced(start_sn.rotation+Angle::half_turn()-end_sn.rotation);
if(abs(adiff).radians()>0.01)
continue;
- Vector delta = rotated_vector(sn2.position-sn1.position, -sn1.rotation);
+ Vector delta = rotated_vector(end_sn.position-start_sn.position, -start_sn.rotation);
if(abs(delta.y)>limit)
continue;
return;
}
- extend_tracks = create_straight(sn1.position, sn1.rotation, gap, limit);
+ extend_tracks = create_straight(start_sn.position, start_sn.rotation, gap, limit);
if(extend_tracks.empty())
{
return;
}
- extend_tracks.front()->link_to(*track1);
- extend_tracks.back()->link_to(*track2);
+ extend_tracks.front()->link_to(*start_track);
+ extend_tracks.back()->link_to(*end_track);
accepted = true;
set_done();
{
if(btn==1)
{
- for(set<Object *>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
+ for(vector<TrackIter>::const_iterator i=unlinked_endpoints.begin(); i!=unlinked_endpoints.end(); ++i)
if(extend_tracks.front()->link_to(**i))
break;
accepted = true;
Angle dir;
float length = 0;
- for(set<Object *>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
+ for(vector<TrackIter>::const_iterator i=unlinked_endpoints.begin(); i!=unlinked_endpoints.end(); ++i)
{
- unsigned nls = (*i)->get_n_link_slots();
- for(unsigned j=0; j<nls; ++j)
- {
- if((*i)->get_link(j))
- continue;
-
- Snap sn = (*i)->get_snap_node(j);
- Vector delta = rotated_vector(ground_pointer-sn.position, -sn.rotation);
+ Snap sn = (*i)->get_snap_node(i->entry());
+ Vector delta = rotated_vector(ground_pointer-sn.position, -sn.rotation);
- if(delta.x<length)
- continue;
+ if(delta.x<length)
+ continue;
- pos = sn.position;
- dir = sn.rotation;
- length = delta.x;
- }
+ pos = sn.position;
+ dir = sn.rotation;
+ length = delta.x;
}
if(length)
#include <set>
#include <vector>
-#include "libr2c2/track.h"
+#include "libr2c2/object.h"
+#include "libr2c2/trackiter.h"
#include "tool.h"
class ExtendTool: public Tool
{
private:
- std::set<R2C2::Object *> objects;
+ std::vector<R2C2::TrackIter> unlinked_endpoints;
std::vector<R2C2::Track *> extend_tracks;
bool accepted;
MoveTool::MoveTool(Designer &d, Input::Mouse &m, const set<Object *> &o):
Manipulator(d, m, o),
origin(ground_pointer)
-{ }
+{
+ for(ObjectArray::iterator i=objects.begin(); i!=objects.end(); ++i)
+ {
+ unsigned nls = i->object->get_n_link_slots();
+ for(unsigned j=0; j<nls; ++j)
+ if(!o.count(i->object->get_link(j)))
+ boundaries.push_back(Boundary(&*i, j));
+ }
+
+ snap_targets = designer.get_layout().get_all<Object>();
+ for(ObjectArray::const_iterator i=objects.begin(); i!=objects.end(); ++i)
+ snap_targets.erase(i->object);
+}
void MoveTool::axis_motion(unsigned axis, float value, float rel)
{
i->object->set_rotation(i->original_rotation);
}
- const set<Track *> <racks = designer.get_layout().get_all<Track>();
float limit = max(designer.get_layout().get_catalogue().get_gauge(),
designer.get_camera_controller().get_view_scale()/100.0f);
MObject *snapped = 0;
- for(set<Track *>::const_iterator i=ltracks.begin(); (i!=ltracks.end() && !snapped); ++i)
+ for(list<Boundary>::iterator i=boundaries.begin(); (!snapped && i!=boundaries.end()); ++i)
{
- bool ok = true;
- for(ObjectArray::iterator j=objects.begin(); (j!=objects.end() && ok); ++j)
- ok = (j->object!=*i);
- if(!ok)
- continue;
-
- for(ObjectArray::iterator j=objects.begin(); (j!=objects.end() && !snapped); ++j)
- if(j->object->snap_to(**i, limit))
- snapped = &*j;
+ for(set<Object *>::const_iterator j=snap_targets.begin(); (!snapped && j!=snap_targets.end()); ++j)
+ if((*i)->snap_to(**j, limit))
+ snapped = i->object;
}
if(snapped)
}
}
}
+
+
+MoveTool::Boundary::Boundary(MObject *o, unsigned i):
+ object(o),
+ index(i)
+{ }
class MoveTool: public Manipulator
{
private:
+ struct Boundary
+ {
+ MObject *object;
+ unsigned index;
+
+ Boundary(MObject *, unsigned);
+
+ R2C2::Object *operator->() const { return object->object; }
+ };
+
+ std::list<Boundary> boundaries;
+ std::set<R2C2::Object *> snap_targets;
R2C2::Vector origin;
public:
+#include "libr2c2/track.h"
#include "slopetool.h"
using namespace std;
total_length(0)
{
for(set<Object *>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
- {
- unsigned nls = (*i)->get_n_link_slots();
- if(nls!=2 || !dynamic_cast<Track *>(*i))
+ if(!dynamic_cast<Track *>(*i) || (*i)->get_n_link_slots()!=2)
{
set_status("Must have linear tracks only");
return;
}
- }
-
- for(set<Object *>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
- {
- unsigned nls = (*i)->get_n_link_slots();
- for(unsigned j=0; j<nls; ++j)
- if(Track *link = dynamic_cast<Track *>((*i)->get_link(j)))
- if(!objects.count(link))
- neighbors.push_back(link);
- }
-
- list<Track *> tmp_tracks;
- for(set<Object *>::iterator i=objects.begin(); i!=objects.end(); ++i)
- if(Track *track = dynamic_cast<Track *>(*i))
- tmp_tracks.push_back(track);
- Track *cur = neighbors.front();
- while(!tmp_tracks.empty())
- {
- bool rev = false;
- for(list<Track *>::iterator i=tmp_tracks.begin(); i!=tmp_tracks.end(); ++i)
+ TrackIter track;
+ for(set<Object *>::const_iterator i=objects.begin(); (!track && i!=objects.end()); ++i)
+ if(Track *t = dynamic_cast<Track *>(*i))
{
- const vector<Track *> &links = (*i)->get_links();
- if(links[0]==cur)
- {
- cur = *i;
- tmp_tracks.erase(i);
- break;
- }
- else if(links[1]==cur)
- {
- cur = *i;
- rev = true;
- tmp_tracks.erase(i);
- break;
- }
+ unsigned nls = t->get_n_link_slots();
+ for(unsigned j=0; (!track && j<nls); ++j)
+ if(!objects.count((*i)->get_link(j)))
+ track = TrackIter(t, j);
}
- tracks.push_back(TrackOrder(cur, rev));
- total_length += cur->get_type().get_total_length();
+
+ total_length = 0;
+ while(track && objects.count(track.track()))
+ {
+ tracks.push_back(track);
+ total_length += track->get_type().get_path_length(0);
+ track = track.next();
}
}
void SlopeTool::even_slope(bool smooth)
{
- list<Track *>::iterator nb = neighbors.begin();
- int epi = (*nb)->get_link_slot(*tracks.front().track);
- float start_z = (*nb)->get_snap_node(epi).position.z;
- ++nb;
- epi = (*nb)->get_link_slot(*tracks.back().track);
- float end_z = (*nb)->get_snap_node(epi).position.z;
+ float start_z = tracks.front()->get_snap_node(tracks.front().entry()).position.z;
+ float end_z = tracks.back()->get_snap_node(tracks.back().reverse().entry()).position.z;
float length = total_length;
if(smooth)
Angle tilt = Geometry::atan(cur_slope);
set_slope(tracks.front(), start_z, tilt);
- start_z += tracks.front().track->get_type().get_path_length(0)*dir*cur_slope;
- length -= tracks.front().track->get_type().get_path_length(0);
+ start_z += tracks.front()->get_type().get_path_length(0)*dir*cur_slope;
+ length -= tracks.front()->get_type().get_path_length(0);
tracks.pop_front();
- end_z -= tracks.back().track->get_type().get_path_length(0)*dir*cur_slope;
+ end_z -= tracks.back()->get_type().get_path_length(0)*dir*cur_slope;
set_slope(tracks.back(), end_z, tilt);
- length -= tracks.back().track->get_type().get_path_length(0);
+ length -= tracks.back()->get_type().get_path_length(0);
tracks.pop_back();
}
}
float cur_z = start_z;
Angle tilt = Geometry::atan((end_z-start_z)/length);
- for(list<TrackOrder>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(list<TrackIter>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
set_slope(*i, cur_z, tilt);
- cur_z += i->track->get_type().get_path_length(0)*(end_z-start_z)/length;
+ cur_z += (*i)->get_type().get_path_length(0)*(end_z-start_z)/length;
}
}
void SlopeTool::flatten()
{
float z = 0;
- for(list<TrackOrder>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(list<TrackIter>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
- unsigned nsn = i->track->get_n_snap_nodes();
+ unsigned nsn = (*i)->get_n_snap_nodes();
for(unsigned j=0; j<nsn; ++j)
- z += i->track->get_snap_node(j).position.z/nsn;
+ z += (*i)->get_snap_node(j).position.z/nsn;
}
z /= static_cast<int>(tracks.size());
- for(list<TrackOrder>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(list<TrackIter>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
- Vector p = i->track->get_position();
- i->track->set_position(Vector(p.x, p.y, z));
- i->track->set_tilt(Angle::zero());
+ Vector p = (*i)->get_position();
+ (*i)->set_position(Vector(p.x, p.y, z));
+ (*i)->set_tilt(Angle::zero());
}
}
-void SlopeTool::set_slope(TrackOrder &track, float z, const Angle &tilt)
+void SlopeTool::set_slope(const TrackIter &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)
+ const Vector &p = track->get_position();
+ float dz = tan(tilt)*track->get_type().get_path_length(0);
+ if(track.entry()==1)
{
- track.track->set_position(Vector(p.x, p.y, z+dz));
- track.track->set_tilt(-tilt);
+ track->set_position(Vector(p.x, p.y, z+dz));
+ track->set_tilt(-tilt);
}
else
{
- track.track->set_position(Vector(p.x, p.y, z));
- track.track->set_tilt(tilt);
+ track->set_position(Vector(p.x, p.y, z));
+ track->set_tilt(tilt);
}
}
#ifndef SLOPETOOL_H_
#define SLOPETOOL_H_
+#include "libr2c2/object.h"
+#include "libr2c2/trackiter.h"
#include "tool.h"
-#include "libr2c2/track.h"
class SlopeTool: public Tool
{
private:
- struct TrackOrder
- {
- R2C2::Track *track;
- bool rev;
-
- TrackOrder(R2C2::Track *t, bool r): track(t), rev(r) { }
- };
-
- std::list<R2C2::Track *> neighbors;
- std::list<TrackOrder> tracks;
+ std::list<R2C2::TrackIter> tracks;
float total_length;
public:
void even_slope(bool =false);
void flatten();
private:
- void set_slope(TrackOrder &, float, const R2C2::Angle &);
+ void set_slope(const R2C2::TrackIter &, float, const R2C2::Angle &);
};
#endif