1: <?php
2:
3: /**
4: *
5: * Maintains the geometry for a tree node
6: *
7: * @package alpha::util::graphs
8: * @since 1.0
9: * @author John Collins <dev@alphaframework.org>
10: * @version $Id: AlphaGraphNode.inc 1496 2012-02-12 20:32:21Z alphadev $
11: * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
12: * @copyright Copyright (c) 2012, John Collins (founder of Alpha Framework).
13: * All rights reserved.
14: *
15: * <pre>
16: * Redistribution and use in source and binary forms, with or
17: * without modification, are permitted provided that the
18: * following conditions are met:
19: *
20: * * Redistributions of source code must retain the above
21: * copyright notice, this list of conditions and the
22: * following disclaimer.
23: * * Redistributions in binary form must reproduce the above
24: * copyright notice, this list of conditions and the
25: * following disclaimer in the documentation and/or other
26: * materials provided with the distribution.
27: * * Neither the name of the Alpha Framework nor the names
28: * of its contributors may be used to endorse or promote
29: * products derived from this software without specific
30: * prior written permission.
31: *
32: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
33: * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
34: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
35: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36: * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
37: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
38: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
39: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
40: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
42: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
43: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
44: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45: * </pre>
46: *
47: */
48: class AlphaGraphNode {
49: /**
50: * The id of the node
51: *
52: * @var integer
53: * @since 1.0
54: */
55: private $id = 0;
56:
57: /**
58: * The height of the node
59: *
60: * @var integer
61: * @since 1.0
62: */
63: private $height = 0;
64:
65: /**
66: * The width of the node
67: *
68: * @var integer
69: * @since 1.0
70: */
71: private $width = 0;
72:
73: /**
74: * The x position of the node
75: *
76: * @var integer
77: * @since 1.0
78: */
79: private $x = 0;
80:
81: /**
82: * The y position of the node
83: *
84: * @var integer
85: * @since 1.0
86: */
87: private $y = 0;
88:
89: /**
90: * The node to the left of this one
91: *
92: * @var AlphaGraphNode
93: * @since 1.0
94: */
95: private $leftNode;
96:
97: /**
98: * The node to the right of this one
99: *
100: * @var AlphaGraphNode
101: * @since 1.0
102: */
103: private $rightNode;
104:
105: /**
106: * An array of child nodes of this node
107: *
108: * @var array
109: * @since 1.0
110: */
111: private $children = array();
112:
113: /**
114: * The margin offset of the current node
115: *
116: * @var integer
117: * @since 1.0
118: */
119: private $offset = 0;
120:
121: /**
122: * Optional positional modifier
123: *
124: * @var integer
125: * @since 1.0
126: */
127: private $modifier = 0;
128:
129: /**
130: * Parent node of this node (if any)
131: *
132: * @var AlphaGraphNode
133: * @since 1.0
134: */
135: private $parentNode;
136:
137: /**
138: * The text message to display on the node
139: *
140: * @var string
141: * @since 1.0
142: */
143: private $message;
144:
145: /**
146: * A 2D array of the coordinates of the endpoints for connectots on this node
147: *
148: * @var array
149: * @since 1.0
150: */
151: private $links = array();
152:
153: /**
154: * An array containing the R,G,B values for the colour of this node
155: *
156: * @var array
157: * @since 1.0
158: */
159: private $nodeColour;
160:
161: /**
162: * If the node is clickable in an image map, use this property to hold the target URL
163: *
164: * @var string
165: * @since 1.0
166: */
167: private $URL;
168:
169: /**
170: * Constructor
171: *
172: * @param integer $id
173: * @param integer $width
174: * @param integer $height
175: * @param string $message
176: * @param array $nodeColour
177: * @param string $URL
178: */
179: public function __construct($id, $width, $height, $message = '', $nodeColour = null, $URL = null) {
180: $this->id = $id;
181: $this->width = $width;
182: $this->height = $height;
183: $this->message = $message;
184: $this->nodeColour = $nodeColour;
185: $this->URL = $URL;
186: }
187:
188: /**
189: * Get the node colour array
190: *
191: * @return array
192: * @since 1.0
193: */
194: public function getNodeColour() {
195: return $this->nodeColour;
196: }
197:
198: /**
199: * Set the node colour array
200: *
201: * @param array $nodeColour
202: * @throws IllegalArguementException
203: * @since 1.0
204: */
205: public function setNodeColour($nodeColour) {
206: if(is_array($nodeColour) && count($nodeColour) == 3)
207: $this->nodeColour = $nodeColour;
208: else
209: throw new IllegalArguementException('The nodeColour value passed ['.$nodeColour.'] is not a valid array!');
210: }
211:
212: /**
213: * Get the node URL
214: *
215: * @return string
216: * @since 1.0
217: */
218: public function getURL() {
219: return $this->URL;
220: }
221:
222: /**
223: * Set the node ULR
224: *
225: * @param string $URL
226: * @since 1.0
227: */
228: public function setURL($URL) {
229: $this->URL = $URL;
230: }
231:
232: /**
233: * Get the node text message
234: *
235: * @return string
236: * @since 1.0
237: */
238: public function getMessage() {
239: return $this->message;
240: }
241:
242: /**
243: * Set the node text message
244: *
245: * @param string $message
246: * @since 1.0
247: */
248: public function setMessage($message) {
249: $this->message = $message;
250: }
251:
252: /**
253: * Get the node offset
254: *
255: * @return string
256: * @since 1.0
257: */
258: public function getOffset() {
259: return $this->offset;
260: }
261:
262: /**
263: * Set the node offset
264: *
265: * @param integer $offset
266: * @since 1.0
267: */
268: public function setOffset($offset) {
269: $this->offset = $offset;
270: }
271:
272: /**
273: * Get the node modifier
274: *
275: * @return integer
276: * @since 1.0
277: */
278: public function getModifier() {
279: return $this->modifier;
280: }
281:
282: /**
283: * Set the node modifier
284: *
285: * @param integer $modifier
286: * @since 1.0
287: */
288: public function setModifier($modifier) {
289: $this->modifier = $modifier;
290: }
291:
292: /**
293: * Get the number of child nodes attached to this node
294: *
295: * @return integer
296: * @since 1.0
297: */
298: public function childCount() {
299: return count($this->children);
300: }
301:
302: /**
303: * Get the parent node of this node (if any)
304: *
305: * @return AlphaGraphNode
306: * @since 1.0
307: */
308: public function getParentNode() {
309: return $this->parentNode;
310: }
311:
312: /**
313: * Set the parent node
314: *
315: * @param AlphaGraphNode $node
316: * @throws IllegalArguementException
317: * @since 1.0
318: */
319: public function setParentNode($node) {
320: if($node instanceof AlphaGraphNode)
321: $this->parentNode = $node;
322: else
323: throw new IllegalArguementException('The node object passed to setParentNode is not a valid AlphaGraphNode instance!');
324: }
325:
326: /**
327: * Get the node to the left of this one (if any)
328: *
329: * @return AlphaGraphNode
330: * @since 1.0
331: */
332: public function getLeftSibling() {
333: if($this->leftNode){
334: return $this->leftNode;
335: }else{
336: return null;
337: }
338: }
339:
340: /**
341: * Sets the node to the left of this node
342: *
343: * @param AlphaGraphNode $node
344: * @throws IllegalArguementException
345: * @since 1.0
346: */
347: public function setLeftSibling($node) {
348: if($node instanceof AlphaGraphNode)
349: $this->leftNode = $node;
350: else
351: throw new IllegalArguementException('The node object passed to setLeftSibling is not a valid AlphaGraphNode instance!');
352: }
353:
354: /**
355: * Get the node to the right of this one (if any)
356: *
357: * @return AlphaGraphNode
358: * @since 1.0
359: */
360: public function getRightSibling() {
361: if($this->rightNode) {
362: return $this->rightNode;
363: }else{
364: return null;
365: }
366: }
367:
368: /**
369: * Sets the node to the right of this node
370: *
371: * @param AlphaGraphNode $node
372: * @throws IllegalArguementException
373: * @since 1.0
374: */
375: public function setRightSibling($node) {
376: if($node instanceof AlphaGraphNode)
377: $this->rightNode = $node;
378: else
379: throw new IllegalArguementException('The node object passed to setRightSibling is not a valid AlphaGraphNode instance!');
380: }
381:
382: /**
383: * Gets the child node at the index provided, or returns false if none is found
384: *
385: * @param integer $i
386: * @return mixed
387: * @since 1.0
388: */
389: public function getChildAt($i) {
390: if(isset($this->children[$i])) {
391: return $this->children[$i];
392: }else{
393: return false;
394: }
395: }
396:
397: /**
398: * Calculates and returns the midpoint X coordinate of the children of this node
399: *
400: * @return integer
401: * @since 1.0
402: */
403: public function getChildrenCenter() {
404: $node = $this->getChildAt(0);
405: $node1 = $this->getChildAt(count($this->children)-1);
406: return $node->getOffset() + (($node1->getOffset() - $node->getOffset()) + $node1->getWidth()) / 2;
407: }
408:
409: /**
410: * Returns the array of child AlphaGraphNode objects
411: *
412: * @return array
413: * @since 1.0
414: */
415: public function getChildren() {
416: return $this->children;
417: }
418:
419: /**
420: * Add a new node to the children array of this node
421: *
422: * @param AlphaGraphNode $node
423: * @throws IllegalArguementException
424: * @since 1.0
425: */
426: public function addChild($node) {
427: if($node instanceof AlphaGraphNode)
428: array_push($this->children, $node);
429: else
430: throw new IllegalArguementException('The node object passed to addChild is not a valid AlphaGraphNode instance!');
431: }
432:
433: /**
434: * Returns the links array
435: *
436: * @return array
437: * @since 1.0
438: */
439: public function getLinks() {
440: return $this->links;
441: }
442:
443: /**
444: * Sets up the array of connector endpoints
445: *
446: * @since 1.0
447: */
448: public function setUpLinks() {
449: $xa = 0; $ya = 0; $xb = 0; $yb = 0; $xc = 0; $yc = 0; $xd = 0; $yd = 0;
450: $xa = $this->x + ($this->width / 2);
451: $ya = $this->y + $this->height;
452:
453: foreach($this->children as $child) {
454: $xd = $xc = $child->getX() + ($child->getWidth() / 2);
455: $yd = $child->getY();
456: $xb = $xa;
457: $yb = $yc = $ya + ($yd - $ya) / 2;
458: $this->links[$child->id]['xa'] = $xa;
459: $this->links[$child->id]['ya'] = $ya;
460: $this->links[$child->id]['xb'] = $xb;
461: $this->links[$child->id]['yb'] = $yb;
462: $this->links[$child->id]['xc'] = $xc;
463: $this->links[$child->id]['yc'] = $yc;
464: $this->links[$child->id]['xd'] = $xd;
465: $this->links[$child->id]['yd'] = $yd;
466: }
467: }
468:
469: /**
470: * Returns the node height
471: *
472: * @return integer
473: * @since 1.0
474: */
475: public function getHeight() {
476: return $this->height;
477: }
478:
479: /**
480: * Returns the node width
481: *
482: * @return integer
483: * @since 1.0
484: */
485: public function getWidth() {
486: return $this->width;
487: }
488:
489: /**
490: * Returns the node X-coordinate
491: *
492: * @return integer
493: * @since 1.0
494: */
495: public function getX() {
496: return $this->x;
497: }
498:
499: /**
500: * Returns the node Y-coordinate
501: *
502: * @return integer
503: * @since 1.0
504: */
505: public function getY() {
506: return $this->y;
507: }
508:
509: /**
510: * Sets the node X-coordinate
511: *
512: * @param integer $x
513: * @since 1.0
514: */
515: public function setX($x) {
516: $this->x = $x;
517: }
518:
519: /**
520: * Sets the node Y-coordinate
521: *
522: * @param integer $y
523: * @since 1.0
524: */
525: public function setY($y) {
526: $this->y = $y;
527: }
528: }
529:
530: ?>