This machine mirrors various open-source projects.
20 Gbit/s uplink.
If there are any issues or you want another project mirrored, please contact
mirror-service -=AT=- netcologne DOT de !
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 */