OpenLayers.Layer.LineDirections =
  OpenLayers.Class(OpenLayers.Layer.Vector, {
    /**
     * TODO Kommentieren
     */
    initialize: function(options) {
	  // Zun?chst den Konstruktor der Elternklasse aufrufen
	  OpenLayers.Layer.Vector.prototype.initialize.apply(this, arguments);
	  this.sourceLayer.events.on({
        featuresadded: this.rebuildDirections,
        featuresremoved: this.rebuildDirections,
        afterfeaturemodified: this.rebuildDirections,
        loadend: this.rebuildDirections,
        refresh: this.rebuildDirections,
        scope: this
      });
      // Die Richtungsfeatures erzeugen
      this.buildDirections();
    },
    /**
     * TODO Kommentieren
     */
    rebuildDirections: function() {
      this.destroyFeatures();
      this.buildDirections();
    },
    /**
     * TODO Kommentieren
     */
    buildDirections: function() {
      var directionFeatures
      for(var i = 0,len = this.sourceLayer.features.length; i < len; i++){
          var feature_geom = this.sourceLayer.features[i].geometry;
          directionFeatures = this.getDirectionFeatures(feature_geom);
          this.addFeatures( directionFeatures );
      }
    },

    /**
     * Die einzelnen Features aus einem Linestring extrahieren
     */
    getDirectionFeatures: function(line_geometry) {
      var directionFeatures = [];
      var vertices = line_geometry.getVertices();
      for (var i=0, len = vertices.length; i < len; i++) {
        if (i+1 < len) {
          var line = new OpenLayers.Geometry.LineString([
            vertices[i],
            vertices[i+1]
          ]);
          var p_geom = this.getLineCentroid(line);
          var lineangle = this.determineDirection( line );
          var p_feature = new OpenLayers.Feature.Vector(
            p_geom,
            {
              angle: lineangle
            }
          );
          directionFeatures.push( p_feature );
        }
      }
      return directionFeatures;
    },
    /**
     * TODO Kommentieren
     */
    determineDirection: function(line) {
      var endpoints = line.getVertices(true);
      var piHalf = Math.PI / 2;
      var radian;
      if (endpoints.length === 2) {
        var delta_x = endpoints[0].x - endpoints[1].x;
        var delta_y = endpoints[0].y - endpoints[1].y;
        if (delta_y != 0) {
          if (delta_x != 0) {
            var relation = delta_y / delta_x;
            // Wir m?ssen den arctan noch
            // mit -1 multiplizieren, da im
            // Uhrzeigersinn gedreht wird!
            radian = Math.atan( relation ) * -1;
            // Korrigieren:
            if (delta_x > 0) {
                // zeigt nach links
                radian += Math.PI;
            }
          } else {
            // pfeil zeigt nach oben oder unten...
            if ( delta_y > 0 ) {
              // ... nach unten
              radian = piHalf;
            } else {
              // ... nach oben
              radian = Math.PI + piHalf;
            }
          }
        } else {
          // pfeil zeigt nach rechts oder links...
          if ( delta_x > 0 ) {
             // ... nach links
             radian = Math.PI;
          } else {
             // ... nach rechts
             radian = 0;
          }
        }
      }
      // return as degree
      return (radian * (180 / Math.PI));
    },

    /**
     * Bestimmt den Schwerpunkt / die Mitte einer
     * Liniengeometrie mit zwei Punkten
     */
    getLineCentroid: function(line){
      var endpoints = line.getVertices( );
      var centroid;
      if (endpoints.length === 2) {
        var x = ( endpoints[0].x + endpoints[1].x ) / 2;
        var y = ( endpoints[0].y + endpoints[1].y ) / 2;
        centroid = new OpenLayers.Geometry.Point( x, y );
      }
      return centroid;
    },
    CLASS_NAME: "OpenLayers.Layer.LineDirections2"
});

