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