--- /dev/null
+#include <cmath>
+#include "tracktype.h"
+
+using namespace std;
+
+namespace Marklin {
+
+TrackType::TrackType(unsigned a):
+ art_nr(a)
+{ }
+
+float TrackType::get_total_length() const
+{
+ float len=0;
+ for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
+ {
+ float l=i->length;
+ if(i->radius)
+ l*=i->radius;
+ len+=l;
+ }
+ return len;
+}
+
+unsigned TrackType::get_n_routes() const
+{
+ unsigned n=1;
+ for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
+ if(i->route>=n)
+ n=i->route+1;
+ return n;
+}
+
+void TrackType::collect_endpoints()
+{
+ endpoints.clear();
+
+ for(vector<TrackPart>::iterator i=parts.begin(); i!=parts.end(); ++i)
+ i->collect_endpoints(endpoints);
+
+ for(vector<Endpoint>::iterator i=endpoints.begin(); i!=endpoints.end();)
+ {
+ bool rm=false;
+ for(vector<Endpoint>::iterator j=i+1; j!=endpoints.end();)
+ {
+ float dx=i->x-j->x;
+ float dy=i->y-j->y;
+ if(dx*dx+dy*dy<0.0001)
+ {
+ float da=i->dir-j->dir;
+ if(da<-M_PI)
+ da+=M_PI*2;
+ if(da>M_PI)
+ da-=M_PI*2;
+ if(da<-3.1 || da>3.1)
+ rm=true;
+ i->routes|=j->routes;
+ j=endpoints.erase(j);
+ }
+ else
+ ++j;
+ }
+
+ if(rm)
+ i=endpoints.erase(i);
+ else
+ ++i;
+ }
+}
+
+
+TrackType::Loader::Loader(TrackType &t):
+ ttype(t)
+{
+ add("description", &TrackType::description);
+ add("part", &Loader::part);
+}
+
+void TrackType::Loader::finish()
+{
+ ttype.collect_endpoints();
+}
+
+void TrackType::Loader::part()
+{
+ TrackPart p;
+ load_sub(p);
+ ttype.parts.push_back(p);
+}
+
+} // namespace Marklin