Fixed autotools stuff
[construo.git] / selection.cxx
blobde564e61132578058a3c5f4967c7c38d85fca147
1 // $Id: selection.cxx,v 1.11 2003/07/28 22:46:48 grumbel Exp $
2 //
3 // Construo - A wire-frame construction gamee
4 // Copyright (C) 2002 Ingo Ruhnke <grumbel@gmx.de>
5 //
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.
20 #include <config.h>
21 #include <algorithm>
22 #include <math.h>
23 #include <map>
24 #include "rect.hxx"
25 #include "selection.hxx"
26 #include "particle.hxx"
27 #include "particle_factory.hxx"
28 #include "controller.hxx"
30 Selection::Selection ()
32 world = 0;
35 Vector2d
36 Selection::get_center ()
38 validate();
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 ();
57 void
58 Selection::scale (float factor, Vector2d center)
60 validate();
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();
80 void
81 Selection::set_velocity (const Vector2d vel)
83 for (SelectionLst::iterator i = selection.begin (); i != selection.end (); ++i)
84 (*i)->velocity = vel;
87 void
88 Selection::flip ()
90 validate();
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);
108 void
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,
114 p2.x, p2.y);
116 selection = SelectionLst(particles.begin(),
117 particles.end());
120 void
121 Selection::duplicate ()
123 validate();
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;
160 bool
161 Selection::empty() const
163 return selection.empty();
166 void
167 Selection::clear()
169 selection.clear();
170 world = 0;
173 void
174 Selection::rotate (float rot_angle, Vector2d rotate_center)
176 validate();
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;
193 void
194 Selection::validate()
196 if (world != Controller::instance()->get_world ())
198 //std::cout << "World changed; " << world << " " << Controller::instance()->get_world () << std::endl;
199 clear();
203 void
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;
213 ++j;
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
227 // 'j'
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);
243 clear();
246 /* EOF */