Login   Register  
PHP Classes
elePHPant
Icontem

File: vertex.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Brenor Brophy  >  Polygon  >  vertex.php  >  Download  
File: vertex.php
Role: Class source
Content type: text/plain
Description: vertex and segment objects used by polygon
Class: Polygon
Perform geometric operations on polygons
Author: By
Last change: Just updated revision number in file. No changes to code.
Date: 4 years ago
Size: 11,333 bytes
 

Contents

Class file image Download
<?php
/*------------------------------------------------------------------------------
** File:        vertex.php
** Description: PHP class for a polygon vertex. Used as the base object to
**              build a class of polygons. 
** Version:     1.6
** Author:      Brenor Brophy
** Email:       brenor dot brophy at gmail dot com
** Homepage:    www.brenorbrophy.com 
**------------------------------------------------------------------------------
** COPYRIGHT (c) 2005-2010 BRENOR BROPHY
**
** The source code included in this package 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. This license can be
** read at:
**
** http://www.opensource.org/licenses/gpl-license.php
**
** 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. 
**------------------------------------------------------------------------------
**
** Based on the paper "Efficient Clipping of Arbitary Polygons" by Gunther
** Greiner (greiner at informatik dot uni-erlangen dot de) and Kai Hormann
** (hormann at informatik dot tu-clausthal dot de), ACM Transactions on Graphics
** 1998;17(2):71-83.
**
** Available at:
**
**      http://www2.in.tu-clausthal.de/~hormann/papers/Greiner.1998.ECO.pdf
**
** Another useful site describing the algorithm and with some example
** C code by Ionel Daniel Stroe is at:
**
**              http://davis.wpi.edu/~matt/courses/clipping/
**
** The algorithm is extended by Brenor Brophy to allow polygons with
** arcs between vertices.
**
** Rev History
** -----------------------------------------------------------------------------
** 1.0  08/25/2005      Initial Release
** 1.1  09/04/2005      Added software license language to header comments
** 1.2  09/07/2005      Minor fix to polygon.php - no change to this file
** 1.3  04/16/2006      Minor fix to polygon.php - no change to this file
** 1.4  03/19/2009      Minor change to comments in this file. Significant
**                      change to polygon.php
** 1.5  07/16/2009      No change to this file
** 1.6  15/05/2010      No change to this file
*/

class segment
{
/*------------------------------------------------------------------------------
** This class contains the information about the segments between vetrices. In
** the original algorithm these were just lines. In this extended form they
** may also be arcs. By creating a separate object for the segment and then
** referencing to it forward & backward from the two vertices it links it is
** easy to track in various directions through the polygon linked list.
*/
        var     $xc, $yc;               // Coordinates of the center of the arc
        var $d;                         // Direction of the arc, -1 = clockwise, +1 = anti-clockwise,
                                        // A 0 indicates this is a line
        /*
        ** Construct a segment
        */
        function segment ($xc=0, $yc=0, $d=0)
        {
                $this->xc = $xc; $this->yc = $yc; $this->d = $d;
        }       
        /*
        ** Return the contents of a segment
        */
        function Xc () { return $this->xc ;}
        function Yc () { return $this->yc ;}
        function d () { return $this->d ;}
        /*
        ** Set Xc/Yc
        */
        function setXc ($xc) { $this->xc = $xc; }
        function setYc ($yc) { $this->yc = $yc; }
} // end of class segment

class vertex
{
/*------------------------------------------------------------------------------
** This class is almost exactly as described in the paper by Gunter/Greiner
** with some minor additions for segments. Basically it is a node in a doubly
** linked list with a few extra control variables used by the algorithm
** for boolean operations. The only methods in the class are used to encapsulate
** the properties.
*/
        var $x, $y;                 // Coordinates of the vertex
        var $nextV, $prevV;         // References to the next and previous vetices in the polygon
        var $nSeg, $pSeg;           // References to next & previous segments
        var $nextPoly;              // Reference to another polygon in a list
        var $intersect;             // TRUE if vertex is an intersection (with another polgon)
        var $neighbor;              // Ref to the corresponding intersection vertex in another polygon 
        var $alpha;                 // Intersection points relative distance from previous vertex
        var $entry;                 // TRUE if intersection is an entry point to another polygon
                                    // FALSE if it is an exit point
        var $checked;               // Boolean - TRUE if vertex has been checked
        var $id;                    // A random ID assigned to make the vertex unique

        /*
        ** Construct a vertex
        */
        function vertex ($x, $y, $xc=0, $yc=0, $d=0,
                         $nextV=NULL, $prevV=NULL, $nextPoly=NULL,
                         $intersect = FALSE, $neighbor=NULL, $alpha=0, $entry=TRUE, $checked=FALSE)
        {
                $this->x = $x; $this->y = $y;
                $this->nextV = $nextV; $this->prevV = $prevV; $this->nextPoly = $nextPoly;
                $this->intersect = $intersect; $this->neighbor = $neighbor; $this->alpha = $alpha;
                $this->entry = $entry; $this->checked = $checked;
                $this->id = mt_rand(0,1000000);
                /*
                ** Create a new segment and set a reference to it. Segments are always
                ** placed after the vertex
                */
                $this->nSeg =& new segment ($xc, $yc, $d);
                $this->pSeg = NULL;
        }
        /*
        ** Get id
        */
        function id() { return $this->id; }
        /*
        ** Get/Set x/y
        */
        function X() { return $this->x; }
        function setX($x) { $this->x = $x; }
        function Y() { return $this->y; }
        function setY($y) { $this->y = $y; }
        /*
        ** Return contents of a segment. Default is to always return the next
        ** segment, unless previous is specified. The special case is where
        ** the vertex is an intersection, in that case the contents of the
        ** neighbor vertex's next or prev segment is returned. Whether next
        ** or previous is returned depends upon the entry value of the vertex
        ** This method ensures that the correct segment data is returned when
        ** a result polygon is being constructed.
        **
        ** For $g Next == TRUE and Prev == FALSE
        */
        function Xc ($g = TRUE)
        {
                if ($this->isIntersect())
                {
                        if ($this->neighbor->isEntry())
                                return $this->neighbor->nSeg->Xc();
                        else
                                return $this->neighbor->pSeg->Xc();
                }
                else
                        if ($g) return $this->nSeg->Xc(); else return $this->pSeg->Xc();
        }
        function Yc ($g = TRUE)
        {
                if ($this->isIntersect())
                {
                        if ($this->neighbor->isEntry())
                                return $this->neighbor->nSeg->Yc();
                        else
                                return $this->neighbor->pSeg->Yc();
                }
                else
                        if ($g) return $this->nSeg->Yc(); else return $this->pSeg->Yc();
        }
        function d ($g = TRUE)
        {
                if ($this->isIntersect())
                {
                        if ($this->neighbor->isEntry())
                                return $this->neighbor->nSeg->d();
                        else
                                return (-1*$this->neighbor->pSeg->d());
                }
                else
                        if ($g) return $this->nSeg->d(); else return (-1*$this->pSeg->d());
        }
        /*
        ** Set Xc/Yc (Only for segment pointed to by Nseg)
        */
        function setXc ($xc) { $this->nSeg->setXc($xc); }
        function setYc ($yc) { $this->nSeg->setYc($yc); }
        /*
        ** Set/Get the reference to the next vertex
        */
        function setNext (&$nextV){ $this->nextV =& $nextV; }
        function &Next (){ return $this->nextV; }
        /*
        ** Set/Get the reference to the previous vertex
        */
        function setPrev (&$prevV){ $this->prevV =& $prevV; }
        function &Prev (){ return $this->prevV; }
        /*
        ** Set/Get the reference to the next segment
        */
        function setNseg (&$nSeg){ $this->nSeg =& $nSeg; }
        function &Nseg (){ return $this->nSeg; }
        /*
        ** Set/Get the reference to the previous segment
        */
        function setPseg (&$pSeg){ $this->pSeg =& $pSeg; }
        function &Pseg (){ return $this->pSeg; }
        /*
        ** Set/Get reference to the next Polygon
        */
        function setNextPoly (&$nextPoly){ $this->nextPoly =& $nextPoly; }
        function &NextPoly (){ return $this->nextPoly; }
        /*
        ** Set/Get reference to neighbor polygon
        */
        function setNeighbor (&$neighbor){ $this->neighbor =& $neighbor; }
        function &Neighbor (){ return $this->neighbor; }
        /*
        ** Get alpha
        */
        function Alpha (){ return $this->alpha; }
        /*
        ** Test for intersection
        */
        function isIntersect (){ return $this->intersect; }
        /*
        ** Set/Test for checked flag
        */      
        function setChecked($check = TRUE)
        {
                $this->checked = $check;
                if ($this->neighbor && !$this->neighbor->isChecked())
                        $this->neighbor->setChecked();
        }
        function isChecked () { return $this->checked; }
        /*
        ** Set/Test entry
        */
        function setEntry ($entry = TRUE){ $this->entry = $entry; }
        function isEntry (){ return $this->entry; }
        /*
        ** Print Vertex used for debugging
        */
        function print_vertex()
        {
                print("(".$this->x.")(".$this->y.") ");
                if ($this->nSeg->d() != 0)
                        print(" c(".$this->nSeg->Xc().")(".$this->nSeg->Yc().")(".$this->nSeg->d().") ");
                if ($this->intersect) {
                        print("Intersection with alpha=".$this->alpha." ");
                        if ($this->entry)
                                print(" Entry");
                        else
                                print(" Exit");}
                if ($this->checked)
                        print(" Checked");
                else
                        print(" Unchecked");
                print("<br>");
        }
} //end of class vertex
?>