original_points[] = new Vector($point->latitude, $point->longitude); } /*----- Include first and last points -----*/ $this->original_points[0]->include = true; $this->original_points[count($this->original_points)-1]->include = true; } /** * Returns a list of GeoPoints for the simplest polyline that leaves * no original point more than $tolerance away from it. * * @param float $tolerance * @return Geopoint array */ public function SimplerLine($tolerance = 0.5) { $this->tolerance = $tolerance; $this->tolerance_squared = $tolerance * $tolerance; $this->DouglasPeucker(0, count($this->original_points) - 1); foreach ($this->original_points as $point) { if ($point->include) { $out[] = new GeoPoint($point->x, $point->y); } } return $out; } /** * Douglas-Peuker polyline simplification algorithm. First draws single line * from start to end. Then finds largest deviation from this straight line, and if * greater than tolerance, includes that point, splitting the original line into * two new lines. Repeats recursively for each new line created. * * @param int $start_vertex_index * @param int $end_vertex_index */ private function DouglasPeucker($start_vertex_index, $end_vertex_index) { if ($end_vertex_index <= $start_vertex_index + 1) // there is nothing to simplify return; // Make line from start to end $line = new Line($this->original_points[$start_vertex_index], $this->original_points[$end_vertex_index]); // Find largest distance from intermediate points to this line $max_dist_to_line_squared = 0; for ($index = $start_vertex_index+1; $index < $end_vertex_index; $index++) { $dist_to_line_squared = $line->DistanceToPointSquared($this->original_points[$index]); if ($dist_to_line_squared>$max_dist_to_line_squared) { $max_dist_to_line_squared = $dist_to_line_squared; $max_dist_index = $index; } } // Check max distance with tolerance if ($max_dist_to_line_squared > $this->tolerance_squared) {// error is worse than the tolerance // split the polyline at the farthest vertex from S $this->original_points[$max_dist_index]->include = true; // recursively simplify the two subpolylines $this->DouglasPeucker($start_vertex_index,$max_dist_index); $this->DouglasPeucker($max_dist_index,$end_vertex_index); } // else the approximation is OK, so ignore intermediate vertices } } ?>