Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

selection.cxx

Go to the documentation of this file.
00001 //  $Id: selection.cxx,v 1.7 2003/01/12 19:06:08 grumbel Exp $
00002 //
00003 //  Construo - A wire-frame construction gamee
00004 //  Copyright (C) 2002 Ingo Ruhnke <grumbel@gmx.de>
00005 //
00006 //  This program is free software; you can redistribute it and/or
00007 //  modify it under the terms of the GNU General Public License
00008 //  as published by the Free Software Foundation; either version 2
00009 //  of the License, or (at your option) any later version.
00010 //
00011 //  This program is distributed in the hope that it will be useful,
00012 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //  GNU General Public License for more details.
00015 //
00016 //  You should have received a copy of the GNU General Public License
00017 //  along with this program; if not, write to the Free Software
00018 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019 
00020 #include <config.h>
00021 #include <algorithm>
00022 #include <math.h>
00023 #include <map>
00024 #include "rect.hxx"
00025 #include "selection.hxx"
00026 #include "particle.hxx"
00027 #include "particle_factory.hxx"
00028 #include "controller.hxx"
00029 
00030 Selection::Selection ()
00031 {
00032   world = 0;
00033 }
00034 
00035 Vector2d
00036 Selection::get_center ()
00037 {
00038   validate();
00039 
00040   Rect<float> rot_box ((*selection.begin ())->pos.x,
00041                        (*selection.begin ())->pos.y,
00042                        (*selection.begin ())->pos.x,
00043                        (*selection.begin ())->pos.y);
00044 
00045   for (Selection::iterator i = selection.begin (); i != selection.end (); ++i)
00046     {
00047       rot_box.x1 = Math::min(rot_box.x1, (*i)->pos.x);
00048       rot_box.y1 = Math::min(rot_box.y1, (*i)->pos.y);
00049 
00050       rot_box.x2 = Math::max(rot_box.x2, (*i)->pos.x);
00051       rot_box.y2 = Math::max(rot_box.y2, (*i)->pos.y);
00052     }
00053  
00054   return rot_box.get_center ();
00055 }
00056 
00057 void
00058 Selection::scale (float factor)
00059 {
00060   validate();
00061 
00062   if (!selection.empty())
00063     {
00064       Particle& p = **selection.begin();
00065       Rect<float> selection_box (p.pos.x, p.pos.y, p.pos.x, p.pos.y);
00066       
00067       for (SelectionLst::iterator i = selection.begin (); i != selection.end (); ++i)
00068         {
00069           selection_box.x1 = Math::min(selection_box.x1, (*i)->pos.x);
00070           selection_box.y1 = Math::min(selection_box.y1, (*i)->pos.y);
00071 
00072           selection_box.x2 = Math::max(selection_box.x2, (*i)->pos.x);
00073           selection_box.y2 = Math::max(selection_box.y2, (*i)->pos.y);
00074         }
00075       Vector2d midpoint = selection_box.get_center ();
00076       
00077       for (SelectionLst::iterator i = selection.begin (); i != selection.end (); ++i)
00078         {
00079           (*i)->pos = (midpoint - (*i)->pos) * factor;
00080         }
00081     }
00082 }
00083 
00084 void
00085 Selection::set_velocity (const Vector2d vel)
00086 {
00087   for (SelectionLst::iterator i = selection.begin (); i != selection.end (); ++i)
00088     (*i)->velocity = vel;
00089 }
00090 
00091 void
00092 Selection::flip ()
00093 {
00094   validate();
00095 
00096   if (!selection.empty())
00097     {
00098       float midpoint = 0.0f;
00099       for (SelectionLst::iterator i = selection.begin (); i != selection.end (); ++i)
00100         {
00101           midpoint += (*i)->pos.x;
00102         }
00103       midpoint /= selection.size ();
00104 
00105       for (SelectionLst::iterator i = selection.begin (); i != selection.end (); ++i)
00106         {
00107           (*i)->pos.x = midpoint - ((*i)->pos.x - midpoint);
00108         }
00109     }
00110 }
00111 
00112 void
00113 Selection::select_particles (Vector2d p1, Vector2d p2)
00114 {
00115   world = Controller::instance()->get_world ();
00116   
00117   selection = world->get_particles (p1.x, p1.y,
00118                                     p2.x, p2.y);
00119 }
00120 
00121 void
00122 Selection::duplicate ()
00123 {
00124   validate();
00125 
00126   Controller::instance()->push_undo();
00127   
00128   // particle translation table
00129   std::map<Particle*, Particle*> p_trans_table;
00130 
00131   SelectionLst new_selection;
00132 
00133   std::cout << "Trying to duplicate the selection" << std::endl;
00134   for (SelectionLst::iterator i = selection.begin (); i != selection.end (); ++i)
00135     {
00136       Particle* p = world->get_particle_mgr()->add_particle(**i);
00137       p->pos += Vector2d (50,50);
00138       new_selection.push_back(p);
00139       p_trans_table[*i] = p;
00140 
00141       //std::cout << "P: " << (*i)->get_id () << " New: " << p->get_id () << std::endl;
00142     }
00143 
00144   // FIXME: Warning, make sure that iterators stays intact while modifing the container
00145   std::vector<Spring*> springs = world->get_spring_mgr ();
00146   for (std::vector<Spring*>::iterator i = springs.begin (); i != springs.end (); ++i)
00147     {
00148       // both particles of the spring are in the current selection
00149       if (std::find (selection.begin (), selection.end (), (*i)->particles.first) != selection.end ()
00150           && 
00151           std::find (selection.begin (), selection.end (), (*i)->particles.second) != selection.end ())
00152         {
00153           world->add_spring (p_trans_table[(*i)->particles.first],
00154                              p_trans_table[(*i)->particles.second]);
00155         }
00156     }
00157 
00158   selection = new_selection;
00159 }
00160 
00161 bool
00162 Selection::empty() const
00163 {
00164   return selection.empty();
00165 }
00166 
00167 void
00168 Selection::clear() 
00169 {
00170   selection.clear();
00171   world = 0;
00172 }
00173 
00174 void
00175 Selection::rotate (float rot_angle, Vector2d rotate_center)
00176 {
00177   validate();
00178 
00179   for (SelectionLst::iterator i = selection.begin (); i != selection.end (); ++i)
00180     {
00181       Vector2d& pos = (*i)->pos;
00182       
00183       pos.x -= rotate_center.x;
00184       pos.y -= rotate_center.y;
00185       
00186       float angle  = atan2(pos.y, pos.x) + rot_angle;
00187       float length = pos.norm ();
00188 
00189       pos.x = (cos (angle)*length) + rotate_center.x;
00190       pos.y = (sin (angle)*length) + rotate_center.y;
00191     }
00192 }
00193 
00194 void
00195 Selection::validate()
00196 {
00197   if (world != Controller::instance()->get_world ())
00198     {
00199       std::cout << "World changed; " << world << " " << Controller::instance()->get_world () << std::endl;
00200       clear();
00201     }
00202 }
00203 
00204 /* EOF */

Generated on Thu Jul 24 10:24:31 2003 for Construo by doxygen1.3-rc3