All pastes #270747 Raw Edit

Something

public text v1 · immutable
·published 2006-12-07 18:03 UTC
rendered paste body
<?php

class LineSet {

	var $lines = array();

	var $min = false;
	var $max = false;

	function Image_GIS_LineSet($color = 'black') {
		$this->color = $color;
	}

	function addLine($x1, $y1, $x2, $y2) {
		$this->lines[] = array($x1, $y1, $x2, $y2);

		if ($this->min == false) {
			$this->min['x'] = min($x1, $x2);
			$this->min['y'] = min($y1, $y2);
			$this->max['x'] = max($x1, $x2);
			$this->max['y'] = max($y1, $y2);
		} else {
			$this->min['x'] = min($this->min['x'], $x1, $x2);
			$this->min['y'] = min($this->min['y'], $y1, $y2);
			$this->max['x'] = max($this->max['x'], $x1, $x2);
			$this->max['y'] = max($this->max['y'], $y1, $y2);
		}
	}
}

class Map_Core extends GtkDrawingArea {
	# prefix class attributes with "_" to avoid collisions
	# with GtkDrawingArea attributes.
	protected $_pixmap;
	protected $_gc;
	protected $_realized;

	function __construct() {
		parent::__construct();

		$this->connect('expose_event',
		array($this, 'expose_event'));
		$this->connect('configure_event',
		array($this, 'configure_event'));
		$this->connect('realize',
		array($this, 'realize'));
		$this->set_events(Gdk::EXPOSURE_MASK
		| Gdk::LEAVE_NOTIFY_MASK);

		$this->_pixmap = null;
		$this->_gc = null;
		$this->_realized = false;
	}

	function realize() {
		$this->_realized = true;
	}

	function realized() {
		return $this->_realized;
	}

	function configure_event($widget, $event) {
		$w = $this->width();
		$h = $this->height();

		# allocate a new pixmap of the requested size ($this->allocation)
		$this->_pixmap = new GdkPixmap($this->window, $w, $h, -1);

		# clear pixmap (white color)
		$this->_pixmap->draw_rectangle($this->style->white_gc, true,
		0, 0, $w, $h);

		return true;
	}

	function expose_event($widget, $event) {
		$this->window->draw_drawable($this->style->fg_gc[$this->state],
		$this->pixmap(),
		$event->area->x, $event->area->y,
		$event->area->x, $event->area->y,
		$event->area->width, $event->area->height
		);
		return false;
	}

	function set_color($color) {
		$col = $this->colormap()->alloc_color($color);
		if ($col === false)
		return $this->foreground('black');
		return $this->gc()->set_foreground($col);
	}

	function colormap() {
		return $this->gc()->get_colormap();
	}

	function pixmap() {
		if (!$this->realized()) {
			trigger_error("Widget not realized ; can't get pixmap");
			return null;
		}
		return $this->_pixmap;
	}

	function gc() {
		if (!$this->realized()) {
			trigger_error("Widget not realized ; can't get GC");
			return null;
		}
		if ($this->_gc == null)
		$this->_gc = new GdkGc($this->pixmap());
		return $this->_gc;
	}

	function width() {
		return $this->allocation->width;
	}

	function height() {
		return $this->allocation->height;
	}

	function w() {
		return $this->width();
	}

	function h() {
		return $this->height();
	}
}


class Map extends Map_Core{

	protected $zoom = 1;
	protected $layers = array('world.e00' => 'black');/*, 'river.e00' => 'blue','river.e01' => 'blue','rlroad.e00' => 'red');*/
	protected $linesets = array();
	protected $message_handle = false;

	public function __construct(){
		parent::__construct();
		$this->set_size_request((310*$this->zoom), (155*$this->zoom));
	}

	public function send_message($message){
		if ($this->message_handle !== false) {
			call_user_func($this->message_handle,$message);
		}
	}

	public function set_message_handle($usrfunc){
		$this->message_handle = $usrfunc;
	}

	protected function parse_E00_file($dataFile) {
		$lineSet = new LineSet();
		$this->send_message("parsing $dataFile");
		if ($fp = @fopen(dirname(__FILE__).'/'.$dataFile, 'r')) {
			$numRecords = 0;
			$ln         = 0;

			while(0 || $line = fgets($fp, 1024)) {
				$ln ++;
				while (Gtk::events_pending()) {
					Gtk::main_iteration();
				}
				//echo "line : $ln\n";
				if ($numRecords == 0 &&
				preg_match("#^\s+([0-9]+)\s+([-0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)#", $line, $a)) {
					$numRecords = $a[7];

					$pl['x'] = -1;
					$pl['y'] = -1;
				}

				else if ($numRecords &&
				preg_match("#^([ -][0-9]\.[0-9]{7}E[-+][0-9]{2})([ -][0-9]\.[0-9]{7}E[-+][0-9]{2})([ -][0-9]\.[0-9]{7}E[-+][0-9]{2})([ -][0-9]\.[0-9]{7}E[-+][0-9]{2})#", $line, $a)) {

					if ($pl['x'] != -1 &&
					$pl['y'] != -1) {
						$lineSet->addLine($pl['x'], $pl['y'], $a[1], $a[2]);
					}

					$numRecords--;

					$lineSet->addLine($a[1], $a[2], $a[3], $a[4]);

					$pl['x'] = $a[3];
					$pl['y'] = $a[4];

					$numRecords--;
				}

				else if ($numRecords &&
				preg_match("#^([ -][0-9]\.[0-9]{7}E[-+][0-9]{2})([ -][0-9]\.[0-9]{7}E[-+][0-9]{2})#", $line, $a)) {
					if ($pl['x'] != -1 &&
					$pl['y'] != -1) {
						$lineSet->addLine($pl['x'], $pl['y'], $a[1], $a[2]);

						$pl['x'] = $a[1];
						$pl['y'] = $a[2];
					}

					$numRecords--;
				}
			}

			@fclose($fp);
			return $lineSet;
		}

		return false;
	}

	public function convert($lineset) {
		$latlon = $lineset->lines;
		$i = 0;
		foreach ($latlon as $line){
			$x_y1 = $this->getlocationcoords($line[0],$line[1],(310*$this->zoom),(155*$this->zoom));
			$lines[$i][0] = $x_y1['x'];
			$lines[$i][1] = $x_y1['y'];
			$x_y2 = $this->getlocationcoords($line[2],$line[3],(310*$this->zoom),(155*$this->zoom));
			$lines[$i][2] = $x_y2['x'];
			$lines[$i][3] = $x_y2['y'];
			while (Gtk::events_pending()) {
				Gtk::main_iteration();
			}
			$i++;
		}
		return $lines;
	}

	public function draw_line($x1, $y1, $x2, $y2){
		$this->pixmap()->draw_line($this->gc(), $x1, $y1, $x2, $y2);
	}

	public function draw_map(){
		foreach ($this->layers as $layer => $color){
			if (!isset($this->linesets[$layer])) {
				$lineset = $this->parse_E00_file($layer);
				$this->linesets[$layer] = $lineset;
			}else{
				$lineset = $this->linesets[$layer];
			}
			$this->send_message("converting $layer");
			$lines = $this->convert($lineset);
			parent::set_color($color);
			$this->send_message("drawing $layer");
			foreach ($lines as $line) {
				$this->draw_line(($line[0]), ($line[1]), ($line[2]), ($line[3]));
				while (Gtk::events_pending()) {
					Gtk::main_iteration();
				}
			}
			$w = $this->w();
			$h = $this->h();
			$this->queue_draw_area(0,0, $w, $h);
		}
		$this->send_message("");
	}

	protected function getlocationcoords($lon, $lat, $width, $height) {
		$x = (($lon + 180) * ($width / 360));
		$y = ((($lat * -1) + 90) * ($height / 180));
		return array("x"=>round($x),"y"=>round($y));
	}

	public function getlocationcoords_inv($x,$y){
		$width = 310 * $this->zoom;
		$height = 155 * $this->zoom;
		$lat = ((($y / $height) * 180) - 90) * -1;
		$lon =(($x / $width) * 360) - 180;
		return array($lat,$lon);
	}

	public function zoom_in(){
		$this->zoom *=1.2;
		$this->set_size_request((310*$this->zoom), (155*$this->zoom));
		$this->draw_map();
	}

	public function zoom_out(){
		if ($this->zoom !== 1) {
			$this->zoom *=0.8;
		}
		$this->set_size_request((310*$this->zoom), (155*$this->zoom));
		$this->draw_map();
	}

}

class Gtk2_Map extends GtkVBox {

	protected $toolbar;
	protected $zoom_in;
	protected $zoom_out;
	protected $scroll;
	protected $fixed;
	protected $map;
	protected $statusbar;

	public function mouse_move(){
		list($x, $y) = $this->map->get_pointer();
		list($lat, $lon) = $this->map->getlocationcoords_inv($x,$y);
		$this->set_message("lat : $lat / lon : $lon");
	}

	public function __construct(){
		parent::__construct();
		$this->toolbar = new GtkToolBar();
		$this->zoom_in = new GtkToolButton();
		$this->zoom_in->set_stock_id(Gtk::STOCK_ZOOM_IN);
		$this->zoom_in->connect_simple('clicked',array($this,'zoom_in'));
		$this->zoom_out = new GtkToolButton();
		$this->zoom_out->set_stock_id(Gtk::STOCK_ZOOM_OUT);
		$this->zoom_out->connect_simple('clicked',array($this,'zoom_out'));
		$this->toolbar->add($this->zoom_in);
		$this->toolbar->add($this->zoom_out);
		$this->scroll = new GtkScrolledWindow();
		$this->fixed = new GtkFixed();
		$this->statusbar = new GtkStatusBar();
		$this->statusbar->set_has_resize_grip(false);
		$this->map = new Map();
		$this->map->set_events(MOUSE_EVENTS);
		$this->map->connect_simple('motion-notify-event',array($this,'mouse_move'));
		$this->map->set_message_handle(array($this,'set_message'));
		$this->fixed->put($this->map,0,0);
		$this->scroll->add_with_viewport($this->fixed);
		$this->pack_start($this->toolbar,false,false);
		$this->pack_start($this->scroll);
		$this->pack_end($this->statusbar,false,false);
		Gtk::timeout_add(1, array($this, 'zoom_out')); // note 2
	}

	public function zoom_in(){
		$this->zoom_in->set_sensitive(false);
		$this->zoom_out->set_sensitive(false);
		$this->map->zoom_in();
		$this->zoom_in->set_sensitive(true);
		$this->zoom_out->set_sensitive(true);
	}

	public function zoom_out(){
		$this->zoom_in->set_sensitive(false);
		$this->zoom_out->set_sensitive(false);
		$this->map->zoom_out();
		$this->zoom_in->set_sensitive(true);
		$this->zoom_out->set_sensitive(true);
	}

	public function set_message($message){
		$this->statusbar->pop(0);
		$this->statusbar->push(0,$message);
		//echo "$message\n";
	}
	
}

define("MOUSE_EVENTS",  Gdk::POINTER_MOTION_MASK
| Gdk::BUTTON_PRESS_MASK
| Gdk::BUTTON_RELEASE_MASK
| Gdk::POINTER_MOTION_HINT_MASK);

$window = new GtkWindow();
$window->connect_simple('destroy', array('gtk', 'main_quit'));
$window->set_title('GIS Maping demo');
$window->set_position(Gtk::WIN_POS_CENTER);
$map = new Gtk2_Map();
$window->add($map);
$window->set_size_request((400), (200));
$window->show_all();

Gtk::main();

?>