designer(d),
mouse(m),
selection(s),
- mode(NONE),
- angle(0)
+ mode(NONE)
{
mouse.signal_button_press.connect(sigc::bind_return(sigc::mem_fun(this, &Manipulator::button_press), false));
mouse.signal_axis_motion.connect(sigc::bind_return(sigc::mem_fun(this, &Manipulator::axis_motion), false));
if(mode)
cancel();
- rot_origin = atan2(gpointer.y-center.y, gpointer.x-center.x);
+ rot_origin = Geometry::atan2(gpointer.y-center.y, gpointer.x-center.x);
mode = ROTATE;
}
track->set_slope(0);
}
- for(set<Track *>::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
- (*i)->check_slope();
-
update_objects();
}
float total_len = 0;
list<TrackOrder> order;
- Track *cur = *neighbors.begin();
+ Track *cur = dynamic_cast<Track *>(*neighbors.begin());
while(tracks2.size())
{
bool rev = false;
total_len += cur->get_type().get_total_length();
}
- set<Track *>::iterator nb = neighbors.begin();
+ set<Object *>::iterator nb = neighbors.begin();
int epi = (*nb)->get_link_slot(*order.front().track);
float start_z = (*nb)->get_snap_node(epi).position.z;
++nb;
cur_z += dz;
}
- for(set<Track *>::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
- (*i)->check_slope();
-
update_objects();
}
if(abs(dz)>0.02)
continue;
- float adiff = sn1.rotation+M_PI-sn2.rotation;
- while(adiff<-M_PI)
- adiff += M_PI*2;
- while(adiff>M_PI)
- adiff -= M_PI*2;
- if(abs(adiff)>0.01)
+ Angle adiff = wrap_balanced(sn1.rotation+Angle::half_turn()-sn2.rotation);
+ if(abs(adiff).radians()>0.01)
continue;
- float c = cos(sn1.rotation);
- float s = sin(sn1.rotation);
- float dx = sn2.position.x-sn1.position.x;
- float dy = sn2.position.y-sn1.position.y;
- if(abs(dx*s-dy*c)>limit)
+ Vector delta = rotated_vector(sn2.position-sn1.position, -sn1.rotation);
+ if(abs(delta.y)>limit)
continue;
- gap = dx*c+dy*s;
+ gap = delta.x;
if(gap<0)
continue;
for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
{
- i->object->set_position(Vector(center.x+i->pos.x, center.y+i->pos.y, center.z+i->pos.z));
+ i->object->set_position(center+i->pos);
i->object->set_rotation(i->rot);
}
- for(set<Track *>::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
- (*i)->check_slope();
-
for(vector<Track *>::iterator i=extend_tracks.begin(); i!=extend_tracks.end(); ++i)
delete *i;
extend_tracks.clear();
- angle = 0;
+ angle = Angle::zero();
signal_done.emit(false);
}
{
Mode m = mode;
mode = NONE;
- angle = 0;
+ angle = Angle::zero();
if(m!=EXTEND)
{
- for(set<Track *>::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
+ for(set<Object *>::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
for(vector<MObject>::iterator j=objects.begin(); j!=objects.end(); ++j)
j->object->break_link(**i);
}
- const set<Track *> <racks = designer.get_layout().get_tracks();
+ const set<Track *> <racks = designer.get_layout().get_all<Track>();
for(set<Track *>::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i)
{
bool ok = true;
if(mode==MOVE)
{
- Vector delta(gpointer.x-move_origin.x, gpointer.y-move_origin.y, 0);
- Vector offset(center.x+delta.x, center.y+delta.y, center.z);
+ Vector offset = center+gpointer-move_origin;
for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
{
- i->object->set_position(Vector(offset.x+i->pos.x, offset.y+i->pos.y, offset.z+i->pos.z));
+ i->object->set_position(offset+i->pos);
i->object->set_rotation(i->rot);
}
- const set<Track *> <racks = designer.get_layout().get_tracks();
+ 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;
if(snapped)
{
- float da = snapped->object->get_rotation()-snapped->rot;
- float c = cos(da);
- float s = sin(da);
+ Angle da = snapped->object->get_rotation()-snapped->rot;
+ Transform trans = Transform::rotation(da, Vector(0, 0, 1));
const Vector &sp = snapped->object->get_position();
for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
{
if(&*i==snapped)
continue;
- Vector dp(i->pos.x-snapped->pos.x, i->pos.y-snapped->pos.y, 0);
- i->object->set_position(Vector(sp.x+c*dp.x-s*dp.y, sp.y+s*dp.x+c*dp.y, sp.z+i->pos.z-snapped->pos.z));
+ i->object->set_position(sp+trans.transform(i->pos-snapped->pos));
i->object->set_rotation(i->rot+da);
}
}
}
else if(mode==ROTATE)
{
- float a = atan2(gpointer.y-center.y, gpointer.x-center.x);
+ Angle a = Geometry::atan2(gpointer.y-center.y, gpointer.x-center.x);
angle += a-rot_origin;
rot_origin = a;
+ Transform trans = Transform::rotation(angle, Vector(0, 0, 1));
for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
{
- float c = cos(angle);
- float s = sin(angle);
- i->object->set_position(Vector(center.x+c*i->pos.x-s*i->pos.y, center.y+s*i->pos.x+c*i->pos.y, center.z+i->pos.z));
+ i->object->set_position(center+trans.transform(i->pos));
i->object->set_rotation(angle+i->rot);
}
}
signal_status.emit(format("Elevation: %+.0fmm (%.0fmm)", dz*1000, (center.z+dz)*1000));
for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
- i->object->set_position(Vector(center.x+i->pos.x, center.y+i->pos.y, center.z+i->pos.z+dz));
-
- for(set<Track *>::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
- (*i)->check_slope();
+ i->object->set_position(center+i->pos+Vector(0, 0, dz));
}
else if(mode==EXTEND)
{
Vector pos;
- float dir = 0;
+ Angle dir;
float length = 0;
for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
{
continue;
Snap sn = i->object->get_snap_node(j);
- float c = cos(sn.rotation);
- float s = sin(sn.rotation);
- float dx = gpointer.x-sn.position.x;
- float dy = gpointer.y-sn.position.y;
+ Vector delta = rotated_vector(gpointer-sn.position, -sn.rotation);
- float len = dx*c+dy*s;
- if(len<length)
+ if(delta.x<length)
continue;
pos = sn.position;
dir = sn.rotation;
- length = len;
+ length = delta.x;
}
}
void Manipulator::update_objects()
{
- Vector minp, maxp;
+ Geometry::BoundingBox<float, 3> bbox;
for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
- {
- // XXX Use generic bounding box when it is implemented
- if(Track *track = dynamic_cast<Track *>(i->object))
- {
- unsigned n_endpoints = track->get_type().get_endpoints().size();
- for(unsigned j=0; j<n_endpoints; ++j)
- {
- Vector p = track->get_snap_node(j).position;
- if(i==objects.begin() && j==0)
- minp = maxp = p;
- else
- {
- minp.x = min(minp.x, p.x);
- maxp.x = max(maxp.x, p.x);
- minp.y = min(minp.y, p.y);
- maxp.y = max(maxp.y, p.y);
- minp.z = min(minp.z, p.z);
- }
- }
- }
- else
- {
- const Vector &p = i->object->get_position();
- minp.x = min(minp.x, p.x);
- maxp.x = max(maxp.x, p.x);
- minp.y = min(minp.y, p.y);
- maxp.y = max(maxp.y, p.y);
- minp.z = min(minp.z, p.z);
- }
- }
+ bbox = bbox|i->object->get_bounding_box();
+
+ const Vector &minp = bbox.get_minimum_point();
+ const Vector &maxp = bbox.get_maximum_point();
- center = Vector((minp.x+maxp.x)/2, (minp.y+maxp.y)/2, minp.z);
+ center = (minp+maxp)/2.0f;
+ center.z = minp.z;
for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
{
- const Vector &p = i->object->get_position();
- i->pos = Vector(p.x-center.x, p.y-center.y, p.z-center.z);
+ i->pos = i->object->get_position()-center;
i->rot = i->object->get_rotation();
}
}
neighbors.clear();
for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
{
- Track *track = dynamic_cast<Track *>(i->object);
- if(!track)
- continue;
-
- const vector<Track *> &links = track->get_links();
- for(vector<Track *>::const_iterator j=links.begin(); j!=links.end(); ++j)
+ unsigned nls = i->object->get_n_link_slots();
+ for(unsigned j=0; j<nls; ++j)
{
- if(!*j)
+ Object *linked = i->object->get_link(j);
+ if(!linked)
continue;
- if(neighbors.count(*j))
+ if(neighbors.count(linked))
continue;
bool ok = true;
for(vector<MObject>::iterator k=objects.begin(); (k!=objects.end() && ok); ++k)
- ok = (k->object!=*j);
+ ok = (k->object!=linked);
if(ok)
- neighbors.insert(*j);
+ neighbors.insert(linked);
}
}
}
}
}
-vector<Track *> Manipulator::create_straight(const R2C2::Vector &start, float dir, float length, float limit)
+vector<Track *> Manipulator::create_straight(const R2C2::Vector &start, const Angle &dir, float length, float limit)
{
const Catalogue::TrackMap &track_types = designer.get_catalogue().get_tracks();
std::map<float, const TrackType *> types_by_length;
if(!lengths.empty())
{
Vector pos = start;
- float c = cos(dir);
- float s = sin(dir);
+ Transform trans = Transform::rotation(dir, Vector(0, 0, 1));
for(vector<float>::iterator i=lengths.begin(); i!=lengths.end(); ++i)
{
Track *track = new Track(designer.get_layout(), *get_item(types_by_length, *i));
track->link_to(*trks.back());
trks.push_back(track);
- pos.x += c**i;
- pos.y += s**i;
+ pos += trans.transform(Vector(*i, 0, 0));
}
}