+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2010 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#include <msp/gl/matrix.h>
+#include <msp/gl/meshbuilder.h>
+#include "3d/tracktype.h"
+#include "designer.h"
+#include "selection.h"
+#include "trackwrap.h"
+
+using namespace std;
+using namespace Msp;
+using namespace Marklin;
+
+TrackWrap::TrackWrap(Designer &d, Selection &s):
+ designer(d),
+ selection(s)
+{
+ selection.signal_changed.connect(sigc::mem_fun(this, &TrackWrap::selection_changed));
+}
+
+void TrackWrap::render(const GL::Tag &) const
+{
+ for(list<Wrap>::const_iterator i=wraps.begin(); i!=wraps.end(); ++i)
+ {
+ GL::PushMatrix _pushm;
+ const Point &pos = i->track->get_position();
+ GL::translate(pos.x, pos.y, pos.z);
+ GL::rotate(i->track->get_rotation()*180/M_PI, 0, 0, 1);
+ i->mesh->draw();
+ }
+}
+
+void TrackWrap::selection_changed()
+{
+ wraps.clear();
+ const set<Track *> &tracks = selection.get_tracks();
+ for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ {
+ Wrap wrap;
+ wrap.track = *i;
+ wrap.mesh = &get_mesh((*i)->get_type());
+ wraps.push_back(wrap);
+ }
+}
+
+GL::Mesh &TrackWrap::get_mesh(const TrackType &type)
+{
+ map<const TrackType *, GL::Mesh *>::iterator j = meshes.find(&type);
+ if(j!=meshes.end())
+ return *j->second;
+
+ const TrackType3D &type3d = designer.get_layout_3d()->get_catalogue().get_track(type);
+
+ float min_area = -1;
+ float angle;
+ Point center;
+ float width;
+ float height;
+ for(float a=0; a<M_PI; a+=0.01)
+ {
+ Point minp, maxp;
+ type3d.get_bounds(a, minp, maxp);
+ float area = (maxp.x-minp.x)*(maxp.y-minp.y);
+ if(area<min_area || min_area<0)
+ {
+ float c = cos(a);
+ float s = sin(a);
+ float x = (minp.x+maxp.x)/2;
+ float y = (minp.y+maxp.y)/2;
+ center = Point(c*x-s*y, s*x+c*y, minp.z);
+ angle = a;
+ width = maxp.x-minp.x+0.01;
+ height = maxp.y-minp.y+0.01;
+
+ min_area = area;
+ }
+ }
+
+ GL::Mesh *mesh = new GL::Mesh((GL::COLOR4_UBYTE, GL::VERTEX2));
+ GL::MeshBuilder bld(*mesh);
+ bld.color(0.0f, 1.0f, 0.0f, 1.0f);
+
+ float c = cos(angle);
+ float s = sin(angle);
+
+ bld.begin(GL::LINE_LOOP);
+ bld.vertex(center.x-c*width/2+s*height/2, center.y-s*width/2-c*height/2);
+ bld.vertex(center.x+c*width/2+s*height/2, center.y+s*width/2-c*height/2);
+ bld.vertex(center.x+c*width/2-s*height/2, center.y+s*width/2+c*height/2);
+ bld.vertex(center.x-c*width/2-s*height/2, center.y-s*width/2+c*height/2);
+ bld.end();
+
+ meshes[&type] = mesh;
+
+ return *mesh;
+}