]> git.tdb.fi Git - r2c2.git/blob - libr2c2/object.cpp
Don't crash if a train has no router
[r2c2.git] / libr2c2 / object.cpp
1 #include <stdexcept>
2 #include "object.h"
3
4 using namespace std;
5
6 namespace R2C2 {
7
8 Object::Object(Layout &l):
9         layout(l),
10         shape(0)
11 { }
12
13 Snap Object::get_snap_node(unsigned) const
14 {
15         throw out_of_range("Object::get_snap_node");
16 }
17
18 bool Object::snap(Snap &sn, float limit, SnapType what) const
19 {
20         if(what&SNAP_NODE)
21         {
22                 unsigned nsn = get_n_snap_nodes();
23                 for(unsigned i=0; i<nsn; ++i)
24                 {
25                         Snap node = get_snap_node(i);
26                         Vector span = sn.position-node.position;
27                         if(dot(span, span)<limit*limit)
28                         {
29                                 sn = node;
30                                 return true;
31                         }
32                 }
33         }
34
35         return false;
36 }
37
38 bool Object::snap_to(const Object &other, float limit, SnapType what)
39 {
40         if(what==SNAP_DEFAULT)
41                 what = get_default_snap_type_to(other);
42
43         if(!what)
44                 return false;
45
46         unsigned nsn = get_n_snap_nodes();
47         for(unsigned i=0; i<nsn; ++i)
48         {
49                 Snap sn = get_snap_node(i);
50                 Snap ssn = sn;
51                 if(other.snap(ssn, limit, what))
52                 {
53                         if(what==SNAP_NODE)
54                                 set_rotation(rotation+ssn.rotation-sn.rotation-Angle::half_turn());
55                         else
56                         {
57                                 Angle adiff = wrap_balanced((ssn.rotation-sn.rotation)*2.0f)/2.0f;
58                                 set_rotation(rotation+adiff);
59                         }
60                         sn = get_snap_node(i);
61                         set_position(position+ssn.position-sn.position);
62                         return true;
63                 }
64         }
65
66         return false;
67 }
68
69 Object *Object::get_link(unsigned) const
70 {
71         throw out_of_range("Object::get_link");
72 }
73
74 bool Object::break_link(Object &other)
75 {
76         unsigned nls = get_n_link_slots();
77         for(unsigned i=0; i<nls; ++i)
78                 if(get_link(i)==&other)
79                         return break_link(i);
80
81         return false;
82 }
83
84 void Object::break_links()
85 {
86         unsigned nls = get_n_link_slots();
87         for(unsigned i=0; i<nls; ++i)
88                 break_link(i);
89 }
90
91 const Shape *Object::get_shape() const
92 {
93         if(shape)
94                 return shape;
95         return get_type().get_shape();
96 }
97
98 bool Object::collide_ray(const Ray &ray) const
99 {
100         const Shape *s = get_shape();
101         if(!s)
102                 return false;
103
104         Transform reverse_trans = Transform::rotation(rotation, Vector(0, 0, -1))*
105                 Transform::translation(-position);
106         return s->check_intersection(reverse_trans.transform(ray));
107 }
108
109 BoundingBox Object::get_bounding_box() const
110 {
111         const Shape *s = get_shape();
112         if(!s)
113                 return BoundingBox();
114
115         Transform trans = Transform::translation(position)*
116                 Transform::rotation(rotation, Vector(0, 0, 1));
117         return trans.transform(s->get_axis_aligned_bounding_box());
118 }
119
120 } // namespace R2C2