]> git.tdb.fi Git - r2c2.git/blobdiff - source/designer/manipulator.cpp
Make use of the mspmath library
[r2c2.git] / source / designer / manipulator.cpp
index 5b95d5c4bddab072fbdce0c4d3b0588aa1925e70..8620fe7af8a6a53e8c0a43fd960d509805fa736f 100644 (file)
@@ -14,8 +14,7 @@ Manipulator::Manipulator(Designer &d, Input::Mouse &m, Selection &s):
        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));
@@ -37,7 +36,7 @@ void Manipulator::start_rotate()
        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;
 }
@@ -83,12 +82,8 @@ void Manipulator::duplicate()
        for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
        {
                Object *obj = i->object->clone(&designer.get_layout());
-               if(Track *track = dynamic_cast<Track *>(obj))
-               {
-                       for(list<Object *>::iterator j=new_objs.begin(); j!=new_objs.end(); ++j)
-                               if(Track *track2 = dynamic_cast<Track *>(*j))
-                                       track->snap_to(*track2, true);
-               }
+               for(list<Object *>::iterator j=new_objs.begin(); j!=new_objs.end(); ++j)
+                       obj->link_to(**j);
                new_objs.push_back(obj);
        }
 
@@ -120,9 +115,6 @@ void Manipulator::flatten()
                        track->set_slope(0);
        }
 
-       for(set<Track *>::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
-               (*i)->check_slope();
-
        update_objects();
 }
 
@@ -135,9 +127,8 @@ void Manipulator::even_slope(bool smooth)
                return;
 
        for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
-               if(Track *track = dynamic_cast<Track *>(i->object))
-                       if(track->get_type().get_endpoints().size()!=2)
-                               return;
+               if(i->object->get_n_link_slots()!=2)
+                       return;
 
        list<Track *> tracks2;
        for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
@@ -147,7 +138,7 @@ void Manipulator::even_slope(bool smooth)
        float total_len = 0;
 
        list<TrackOrder> order;
-       Track *cur = *neighbors.begin();
+       Track *cur = dynamic_cast<Track *>(*neighbors.begin());
        while(tracks2.size())
        {
                bool rev = false;
@@ -172,12 +163,12 @@ void Manipulator::even_slope(bool smooth)
                total_len += cur->get_type().get_total_length();
        }
 
-       set<Track *>::iterator nb = neighbors.begin();
-       int epi = (*nb)->get_endpoint_by_link(*order.front().track);
-       float start_z = (*nb)->get_endpoint_position(epi).z;
+       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;
-       epi = (*nb)->get_endpoint_by_link(*order.back().track);
-       float end_z = (*nb)->get_endpoint_position(epi).z;
+       epi = (*nb)->get_link_slot(*order.back().track);
+       float end_z = (*nb)->get_snap_node(epi).position.z;
 
        if(smooth)
        {
@@ -209,9 +200,6 @@ void Manipulator::even_slope(bool smooth)
                cur_z += dz;
        }
 
-       for(set<Track *>::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
-               (*i)->check_slope();
-
        update_objects();
 }
 
@@ -233,8 +221,7 @@ void Manipulator::connect()
 
        float limit = designer.get_layout().get_catalogue().get_gauge()/10;
 
-       Vector pos1;
-       float dir1;
+       Snap sn1;
        bool ok = false;
        float gap = 0;
        for(unsigned i=0; i<track1->get_type().get_endpoints().size(); ++i)
@@ -242,37 +229,28 @@ void Manipulator::connect()
                if(track1->get_link(i))
                        continue;
 
-               pos1 = track1->get_endpoint_position(i);
-               dir1 = track1->get_endpoint_direction(i);
+               sn1 = track1->get_snap_node(i);
 
                for(unsigned j=0; j<track2->get_type().get_endpoints().size(); ++j)
                {
                        if(track2->get_link(j))
                                continue;
 
-                       Vector pos2 = track2->get_endpoint_position(j);
-                       float dir2 = track2->get_endpoint_direction(j);
+                       Snap sn2 = track2->get_snap_node(j);
 
-                       float dz = pos2.z-pos1.z;
+                       float dz = sn2.position.z-sn1.position.z;
                        if(abs(dz)>0.02)
                                continue;
 
-                       float adiff = dir1+M_PI-dir2;
-                       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(dir1);
-                       float s = sin(dir1);
-                       float dx = pos2.x-pos1.x;
-                       float dy = pos2.y-pos1.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;
 
@@ -289,7 +267,7 @@ void Manipulator::connect()
                return;
        }
 
-       vector<Track *> trks = create_straight(pos1, dir1, gap, limit);
+       vector<Track *> trks = create_straight(sn1.position, sn1.rotation, gap, limit);
 
        if(trks.empty())
        {
@@ -297,8 +275,8 @@ void Manipulator::connect()
                return;
        }
 
-       trks.front()->snap_to(*track1, true);
-       trks.back()->snap_to(*track2, true);
+       trks.front()->link_to(*track1);
+       trks.back()->link_to(*track2);
 
        selection.replace(trks.begin(), trks.end());
 }
@@ -311,18 +289,15 @@ void Manipulator::cancel()
 
        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);
 }
@@ -338,14 +313,13 @@ void Manipulator::button_press(unsigned btn)
        {
                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)
-                                       if(Track *track = dynamic_cast<Track *>(j->object))
-                                               track->break_link(**i);
+                                       j->object->break_link(**i);
                }
 
                const set<Track *> &ltracks = designer.get_layout().get_tracks();
@@ -357,8 +331,7 @@ void Manipulator::button_press(unsigned btn)
                        if(!ok) continue;
 
                        for(vector<MObject>::iterator j=objects.begin(); j!=objects.end(); ++j)
-                               if(Track *track = dynamic_cast<Track *>(j->object))
-                                       track->snap_to(**i, true);
+                               j->object->link_to(**i);
                }
 
                if(m==EXTEND)
@@ -386,11 +359,10 @@ void Manipulator::axis_motion(unsigned axis, float value, float)
 
        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);
                }
 
@@ -407,39 +379,35 @@ void Manipulator::axis_motion(unsigned axis, float value, float)
                                continue;
 
                        for(vector<MObject>::iterator j=objects.begin(); (j!=objects.end() && !snapped); ++j)
-                               if(Track *track = dynamic_cast<Track *>(j->object))
-                                       if(track->snap_to(**i, false, limit))
-                                               snapped = &*j;
+                               if(j->object->snap_to(**i, limit))
+                                       snapped = &*j;
                }
 
                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);
                }
        }
@@ -450,42 +418,30 @@ void Manipulator::axis_motion(unsigned axis, float value, float)
                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)
                {
-                       Track *track = dynamic_cast<Track *>(i->object);
-                       if(!track)
-                               continue;
-
-                       unsigned n_endpoints = track->get_type().get_endpoints().size();
-                       for(unsigned j=0; j<n_endpoints; ++j)
+                       unsigned nls = i->object->get_n_link_slots();
+                       for(unsigned j=0; j<nls; ++j)
                        {
-                               if(track->get_link(j))
+                               if(i->object->get_link(j))
                                        continue;
 
-                               Vector ep_pos = track->get_endpoint_position(j);
-                               float ep_dir = track->get_endpoint_direction(j);
-                               float c = cos(ep_dir);
-                               float s = sin(ep_dir);
-                               float dx = gpointer.x-ep_pos.x;
-                               float dy = gpointer.y-ep_pos.y;
+                               Snap sn = i->object->get_snap_node(j);
+                               Vector delta = rotated_vector(gpointer-sn.position, -sn.rotation);
 
-                               float len = dx*c+dy*s;
-                               if(len<length)
+                               if(delta.x<length)
                                        continue;
 
-                               pos = ep_pos;
-                               dir = ep_dir;
-                               length = len;
+                               pos = sn.position;
+                               dir = sn.rotation;
+                               length = delta.x;
                        }
                }
 
@@ -557,7 +513,7 @@ void Manipulator::update_objects()
                        unsigned n_endpoints = track->get_type().get_endpoints().size();
                        for(unsigned j=0; j<n_endpoints; ++j)
                        {
-                               Vector p = track->get_endpoint_position(j);
+                               Vector p = track->get_snap_node(j).position;
                                if(i==objects.begin() && j==0)
                                        minp = maxp = p;
                                else
@@ -581,11 +537,11 @@ void Manipulator::update_objects()
                }
        }
 
-       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();
        }
 }
@@ -595,24 +551,21 @@ void Manipulator::update_neighbors()
        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);
                }
        }
 }
@@ -632,7 +585,7 @@ void Manipulator::set_slope(TrackOrder &track, float z, float dz)
        }
 }
 
-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;
@@ -693,8 +646,7 @@ vector<Track *> Manipulator::create_straight(const R2C2::Vector &start, float di
        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));
@@ -702,11 +654,10 @@ vector<Track *> Manipulator::create_straight(const R2C2::Vector &start, float di
                        track->set_rotation(dir);
 
                        if(!trks.empty())
-                               track->snap_to(*trks.back(), true);
+                               track->link_to(*trks.back());
                        trks.push_back(track);
 
-                       pos.x += c**i;
-                       pos.y += s**i;
+                       pos += trans.transform(Vector(*i, 0, 0));
                }
        }