Location: PHPKode > projects > Lame Node System > lns-0.6-11/include/NodeMap.php
<?php

/************************************************************************
 *																		*
 * Copyright (C) 2001 Stuart Reeves										*
 *																		*
 * This program is free software; you can redistribute it and/or		*
 * modify it under the terms of the GNU General Public License			*
 * as published by the Free Software Foundation; either version 2		*
 * of the License, or (at your option) any later version.				*
 *																		*
 * This program is distributed in the hope that it will be useful,		*	
 * but WITHOUT ANY WARRANTY; without even the implied warranty of		*
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the			*
 * GNU General Public License for more details.							*
 * 																		*
 * The GNU General Public License is available from:					*
 * http://www.gnu.org/copyleft/gpl.html									*
 *																		*
 ************************************************************************/

/* Stuart's lns (lame node system) */


define(LINKS_MATCH, "|<a.+>(.*)</a>|U");
define(TWO_M_PI, 2 * M_PI);
define(FONT_ID, 2);
define(MSEC_IN_SEC, 1000000);
define(NODE_POS_DEV, 50);


/* The $mapdata array holds all the nodes and their associated links in place. The nodes are 
 * ordered in terms of the number of node links they have, and then placed on the image 
 * accordingly. */

class NodeMap
{


	var $mapdata;

	// Constructor
	function NodeMap(){
		$this->mapdata  = array();
	}



	function getMapdata() {
		return $this->mapdata;
	}


	function createNodeGraph($host, $user, $passwd, $db, $table) {
				
		// Get a list of the distinct nodenames
		$query = "SELECT DISTINCT nodename FROM $table WHERE link = '' AND protected != 't'";
	
		$link 			  = mysql_connect($host, $user, $passwd);
		$dbselect		  = mysql_select_db($db, $link);
		$dbqueryNodenames = mysql_query($query, $link);

		$n = 0;					// Counter for our array

		/* Each node has the following data attached:
		 *  	nodename 	-- the name of the actual node
		 *		links	 	-- an array of the links to other nodes it has
		 *		x		 	-- x location it has been plotted to
		 *  	y 		 	-- y location it has been plotted to
		 *		x_linkpt	-- x location point to link a line to
		 *  	y_linkpt	-- y location point to link a line to
		 */
		
		// Go through each distinct nodename
		while ($nodenameList = mysql_fetch_object($dbqueryNodenames)) {

			// Get all the links in this particular node's writeups
			$query   			= "SELECT text FROM $table
								   WHERE nodename = '$nodenameList->nodename'";
			$dbqueryTextbodies  = mysql_query($query, $link);
		
			$linksList 			= array();
			
			if (mysql_num_rows($dbqueryTextbodies) < 1)
				echo "Num rows less than 1, nodename = " . $nodenameList->nodename;
				
			while ($textList = mysql_fetch_object($dbqueryTextbodies)) {
				preg_match_all(LINKS_MATCH, $textList->text, $links);
				$linksList = array_merge($links[1], $linksList);
			}
			
			$this->mapdata[$n++] = array("nodename" => $nodenameList->nodename,
								   		 "links"	=> $linksList,
								   		 "x"		=> 0,
								   		 "y"		=> 0,
								   		 "x_linkpt"	=> 0,
								   	 	 "y_linkpt"	=> 0);
			
		}
		
		mysql_close($link);
		
		
		/* This is the compare function for the sort method used, and is created to sort the array 
		 * based on the number of links a particular node contains. */
		function cmp ($a, $b) {
			if (sizeof($b["links"]) == sizeof($a["links"]))
				return (0);
			else
				return (sizeof($b["links"]) > sizeof($a["links"])) ? 1 : -1;
		}
		usort($this->mapdata, "cmp");
		
			
	
	}



	/* Creates the nodemap PNG image and the nodemap imagemap file.
	 * 
	 * Args:	$args (array)		- settings for picture generation (width, height, step, spacing 
	 *								  and index size)
	 *			$path (string)		- path to place generated picture and imagemap files in
	 *
	 * Returns: true (boolean)		- succeeded to create PNG and imagemap files 
	 *			false (boolean) 	- failed to create one or both files */

	function createNodeMapImage($args, $path) {
	
		$wid 		= $args[0];
		$hgt 		= $args[1];
		$step 		= $args[2];
		$spacing 	= $args[3];
		$ind_size 	= $args[4];
		

		$imagemap = "base referer\n"; 	// The imagemap data text file
		
		// Create the image space
		$img 		= ImageCreate($wid, $hgt);
		$bgcolour 	= ImageColorAllocate($img, 255, 255, 255);
		$textcolour = ImageColorAllocate($img, 0, 0, 0);
		$rectcolour = ImageColorAllocate($img, 255, 0, 0);
		$linecolour = ImageColorAllocate($img, 0, 0, 255);

		// Make sure that the maximum radius does not exceed the average length
		$max_radius 	= ($wid + $hgt) / 4;
		$theta			= 0;
		$i  			= 0; // counter for nodes
		
		// Make the delta-theta step the maximum radius divided by the number of nodes
		$radius_step	= $max_radius;
		if ($n > 0)
			$radius_step /= $n;
		
		// Make sure the elements in the centre are adequately separated
		$radius_offset  = 10; 
		
		// Put the starting node in the centre
		$x_offset 		= $wid / 2;
		$y_offset 		= $hgt / 2;

		Util::reseed();

		// First pass, create the text and associated boxes
		reset($this->mapdata);
		foreach ($this->mapdata as $node) {
			
			$ls = sizeof($node["links"]);
			
			/* The algorithm for drawing the nodes starts from the centre and spirals outwards. The
			 * step along the radius is increased and then multiplied by the number of links to 
			 * ensure that those at the centre are widely spaced. The extra factor of radius offset
			 * adds to this. */
			 
			if ($ls > 0)			
				$radius += $radius_step;
			else {
				$ls = 1;
				$radius = $max_radius;
			}
			
			// Randomise the plotting to make it more interesting
			$x_rand = rand(-NODE_POS_DEV, NODE_POS_DEV) * ($ls * $spacing);
			$y_rand = rand(-NODE_POS_DEV, NODE_POS_DEV) * ($ls * $spacing);
			
			$x  	= $radius * cos($theta) + $x_offset + $x_rand;
			$y  	= $radius * sin($theta) + $y_offset + $y_rand;
			$len 	= strlen($node["nodename"]);
			
			$t = ($ind_size + $len) / 2;
			
			$rect_x1 = (int)($x - $t);
			$rect_y1 = (int)($y - $t);
			$rect_x2 = (int)($x + $t);
			$rect_y2 = (int)($y + $t);
			
			ImageFilledRectangle($img, $rect_x1, $rect_y1, $rect_x2, $rect_y2, $rectcolour);
			
			// Append the imagemap data text for a link for each index shape
			$conv_nodename = str_replace(array("&gt;", "&lt;", "&#039;", "&quot;", "&amp;"), 
										 array(">", "<", "'", "\"", "&"), 
										 $node["nodename"]);
			$link_nodename = str_replace(" ", "%20", $conv_nodename);
			
			$imagemap .= "rect ../index.php?node=" . $link_nodename . 
						 " $rect_x1,$rect_y1 $rect_x2,$rect_y2\n";
						 
			
			ImageString($img, FONT_ID, $x, $y, $conv_nodename, $textcolour);
			
			// Store the location of the node for linking up later
			$this->mapdata[$i]["x"] = $x;
			$this->mapdata[$i]["y"] = $y;
			$this->mapdata[$i]["x_linkpt"] = ($rect_x1 + $rect_x2) / 2;
			$this->mapdata[$i]["y_linkpt"] = ($rect_y1 + $rect_y2) / 2;
	
			
			++$i;
			
			($theta < TWO_M_PI) ? $theta += $step : $theta = 0;
		}
		
		// Second pass, join the nodes up
		reset($this->mapdata);
		foreach ($this->mapdata as $node) {

			foreach ($node["links"] as $link) {
				
				$i = 0;
				
				while ($i < sizeof($this->mapdata) && $this->mapdata[$i]["nodename"] != $link)
					++$i;
					
				if ($i < sizeof($this->mapdata)) {
					ImageLine ($img, 
							   $node["x_linkpt"], 
							   $node["y_linkpt"], 
							   $this->mapdata[$i]["x_linkpt"], 
							   $this->mapdata[$i]["y_linkpt"], 
							   $linecolour);
				}
			
			}
		
		}
		
		
		// Create the PNG image and imagemap files
		$fp1 = fopen($path . "/image.map", "w+");
		$fp2 = fopen($path . "/image.png", "w+");
		
		if ($fp1 && $fp2) { 
			
			fwrite($fp1, $imagemap);
			ImagePNG($img, $path . "/image.png");
			fclose($fp1);
			fclose($fp2);
			
			return true;
		
		} else
			return false;

	}
	
	
}

?>
Return current item: Lame Node System