      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: ?>