1 // $Id: selection.cxx,v 1.11 2003/07/28 22:46:48 grumbel Exp $
3 // Construo - A wire-frame construction gamee
4 // Copyright (C) 2002 Ingo Ruhnke <grumbel@gmx.de>
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #include "selection.hxx"
26 #include "particle.hxx"
27 #include "particle_factory.hxx"
28 #include "controller.hxx"
30 Selection::Selection ()
36 Selection::get_center ()
40 Rect
<float> rot_box ((*selection
.begin ())->pos
.x
,
41 (*selection
.begin ())->pos
.y
,
42 (*selection
.begin ())->pos
.x
,
43 (*selection
.begin ())->pos
.y
);
45 for (Selection::iterator i
= selection
.begin (); i
!= selection
.end (); ++i
)
47 rot_box
.x1
= Math::min(rot_box
.x1
, (*i
)->pos
.x
);
48 rot_box
.y1
= Math::min(rot_box
.y1
, (*i
)->pos
.y
);
50 rot_box
.x2
= Math::max(rot_box
.x2
, (*i
)->pos
.x
);
51 rot_box
.y2
= Math::max(rot_box
.y2
, (*i
)->pos
.y
);
54 return rot_box
.get_center ();
58 Selection::scale (float factor
, Vector2d center
)
62 if (!selection
.empty())
64 for (SelectionLst::iterator i
= selection
.begin (); i
!= selection
.end (); ++i
)
66 (*i
)->pos
= center
+ (((*i
)->pos
- center
) * factor
);
68 std::vector
<Spring
*>& springs
= world
->get_spring_mgr ();
69 for (std::vector
<Spring
*>::iterator s
= springs
.begin(); s
!= springs
.end(); ++s
)
71 if ((*s
)->particles
.first
== (*i
) || ((*s
)->particles
.second
== (*i
)))
73 (*s
)->recalc_length();
81 Selection::set_velocity (const Vector2d vel
)
83 for (SelectionLst::iterator i
= selection
.begin (); i
!= selection
.end (); ++i
)
92 if (!selection
.empty())
94 float midpoint
= 0.0f
;
95 for (SelectionLst::iterator i
= selection
.begin (); i
!= selection
.end (); ++i
)
97 midpoint
+= (*i
)->pos
.x
;
99 midpoint
/= selection
.size ();
101 for (SelectionLst::iterator i
= selection
.begin (); i
!= selection
.end (); ++i
)
103 (*i
)->pos
.x
= midpoint
- ((*i
)->pos
.x
- midpoint
);
109 Selection::select_particles (Vector2d p1
, Vector2d p2
)
111 world
= Controller::instance()->get_world ();
113 std::vector
<Particle
*> particles
= world
->get_particles (p1
.x
, p1
.y
,
116 selection
= SelectionLst(particles
.begin(),
121 Selection::duplicate ()
125 Controller::instance()->push_undo();
127 // particle translation table
128 std::map
<Particle
*, Particle
*> p_trans_table
;
130 SelectionLst new_selection
;
132 std::cout
<< "Trying to duplicate the selection" << std::endl
;
133 for (SelectionLst::iterator i
= selection
.begin (); i
!= selection
.end (); ++i
)
135 Particle
* p
= world
->get_particle_mgr()->add_particle(**i
);
136 p
->pos
+= Vector2d (50,50);
137 new_selection
.push_back(p
);
138 p_trans_table
[*i
] = p
;
140 //std::cout << "P: " << (*i)->get_id () << " New: " << p->get_id () << std::endl;
143 // FIXME: Warning, make sure that iterators stays intact while modifing the container
144 std::vector
<Spring
*> springs
= world
->get_spring_mgr ();
145 for (std::vector
<Spring
*>::iterator i
= springs
.begin (); i
!= springs
.end (); ++i
)
147 // both particles of the spring are in the current selection
148 if (std::find (selection
.begin (), selection
.end (), (*i
)->particles
.first
) != selection
.end ()
150 std::find (selection
.begin (), selection
.end (), (*i
)->particles
.second
) != selection
.end ())
152 world
->add_spring (p_trans_table
[(*i
)->particles
.first
],
153 p_trans_table
[(*i
)->particles
.second
]);
157 selection
= new_selection
;
161 Selection::empty() const
163 return selection
.empty();
174 Selection::rotate (float rot_angle
, Vector2d rotate_center
)
178 for (SelectionLst::iterator i
= selection
.begin (); i
!= selection
.end (); ++i
)
180 Vector2d
& pos
= (*i
)->pos
;
182 pos
.x
-= rotate_center
.x
;
183 pos
.y
-= rotate_center
.y
;
185 float angle
= atan2(pos
.y
, pos
.x
) + rot_angle
;
186 float length
= pos
.norm ();
188 pos
.x
= (cos (angle
)*length
) + rotate_center
.x
;
189 pos
.y
= (sin (angle
)*length
) + rotate_center
.y
;
194 Selection::validate()
196 if (world
!= Controller::instance()->get_world ())
198 //std::cout << "World changed; " << world << " " << Controller::instance()->get_world () << std::endl;
204 Selection::join_doubles(float toleranz
)
206 // FIXME: Undo add undo, if stuff is going to change
207 Controller::instance()->push_undo();
208 World
& world
= *Controller::instance()->get_world ();
210 for (SelectionLst::iterator i
= selection
.begin (); i
!= selection
.end (); ++i
)
212 SelectionLst::iterator j
= i
;
214 for (; j
!= selection
.end (); ++j
)
216 if (Vector2d::distance((*j
)->pos
, (*i
)->pos
) < toleranz
)
218 // Join two particles
219 std::cout
<< "joining particles: " << (*j
)->pos
<< " " << (*i
)->pos
<< std::endl
;
220 (*j
)->pos
= ((*j
)->pos
+ (*i
)->pos
) * 0.5f
;
221 (*j
)->velocity
= ((*j
)->velocity
+ (*i
)->velocity
) * 0.5f
;
223 //selection.remove(*i);
225 { // Everything that is connected to the particle 'i'
226 // which should get removed, needs to get connected to
228 std::vector
<Spring
*>& springs
= world
.get_spring_mgr ();
229 for (std::vector
<Spring
*>::iterator s
= springs
.begin(); s
!= springs
.end(); ++s
)
231 if ((*s
)->particles
.first
== (*i
))
232 (*s
)->particles
.first
= (*j
);
234 if ((*s
)->particles
.second
== (*i
))
235 (*s
)->particles
.second
= (*j
);
239 world
.remove_particle(*i
);