diff --git a/dev/quux.php b/dev/quux.php index 09ebafd..deb80b8 100644 --- a/dev/quux.php +++ b/dev/quux.php @@ -1,161 +1,161 @@ YubiKey'; if (!array_key_exists('YubiCloud', $Config)) { message_die(GENERAL_ERROR, "YubiCloud authentication not configured. Add \$Config['YubiCloud']['ClientID'] and \$Config['YubiCloud']['SecretKey'] to your config."); } if (!$key = $_GET['OTP']) { message_die(GENERAL_ERROR, "Please add in URL ?OTP=, then put your cursor at right of the = and press your YubiKey button"); } $yubi = new Auth_Yubico($Config['YubiCloud']['ClientID'], $Config['YubiCloud']['SecreyKey']); if (!$data = $yubi->parsePasswordOTP($key)) { message_die(GENERAL_ERROR, "This is not an YubiKey OTP."); } $prefix = $data['prefix']; $auth = $yubi->verify($key); if (@PEAR::isError($auth)) { if ($auth->getMessage() == 'REPLAYED_OTP') { message_die("This OTP has already been used."); } message_die(HACK_ERROR, "

Authentication failed: " . $auth->getMessage() . "

Debug: " . $yubi->getLastResponse() . "

"); } else { print "

You are authenticated!

"; } break; case 'GeoPointPolarZ': require_once('includes/geo/pointPolarZ.php'); echo "

GeoPointPolarZ

"; $point = GeoPointPolarZ::fromString("(48, 30°, 3)"); printf("Secteur T%dC%d, zone %d-%d"); dprint_r($point); break; case 'index_scenes': $time[] = microtime(); require_once('includes/geo/scene.php'); require_once('includes/geo/sceneindex.php'); $cache = Cache::load(); if ($index = $cache->get('GeoSceneIndex')) { $index = unserialize($index); } else { $index = GeoSceneIndex::Load(SCENE_DIR); $cache->set('GeoSceneIndex', serialize($index)); } $time[] = microtime(); echo '

GeoSceneIndex

'; dprint_r($index); echo '

Time (ms)

'; dprint_r(1000 * ($time[1] - $time[0])); dprint_r($time); break; case 'travel': require_once('includes/travel/travel.php'); $travel = Travel::load(); dieprint_r($travel); break; case 'spherical': require_once('includes/geo/galaxy.php'); echo '

Spherical coordinates test

'; echo ''; echo ""; $objects = GeoGalaxy::getCoordinates(); foreach ($objects as $row) { echo ""; $pt = $row[2]; - echo ''; - echo ''; + echo ''; + echo ''; $pt->translate(500, 300, 200, 2); echo ''; echo ''; } echo '
NameTypeCartesian coordsSpherical ISpherical IIPencil coordinates
$row[0]$row[1]$row[2](', implode(', ', $pt->to_spherical()), ')(', implode(', ', $pt->to_spherical2()), ')(', implode(', ', $pt->toSpherical()), ')(', implode(', ', $pt->toSphericalAlternative()), ')', $pt, '
'; break; case 'travel': require_once('includes/travel/travel.php'); require_once('includes/travel/place.php'); $cache = Cache::load(); $travel = $cache->get('zed_travel'); if ($travel == '') { $travel_nocached = new Travel(); $travel_nocached->load_xml("content/travel.xml"); $cache->set('zed_travel', serialize($travel_nocached)); } else { $travel = unserialize($travel); } dieprint_r($travel); break; case 'perso.create.notify': $testperso = Perso::get(4733); $message = new Message(); $message->from = 0; $message->to = invite::who_invited(4733); $url = get_server_url() . get_url('who', $testperso->nickname); $message->text = sprintf(lang_get('InvitePersoCreated'), $testperso->name, $url); $message->send(); dieprint_r($message); break; case 'pushdata'; echo '

/api.php/app/pushdata


'; break; case 'thumbnail': $content = new Content(1); dprint_r($content); $content->generate_thumbnail(); break; case 'port': echo '

Port::from_location test

'; $locations = array("B00002", "B00002123", "B00001001", "xyz: [800, 42, 220]"); foreach ($locations as $location) { dprint_r(Port::from_location($location)); } break; case 'ext': $file = 'dev/foo.tar'; echo "

$file

"; echo "

.tar.bz2

"; echo ereg('\.tar\.bz2$', $file); echo "

.tar

"; echo ereg('\.tar$', $file); break; case 'app': echo Application::from_api_key("37d839ba-f9fc-42ca-a3e8-28053e979b90")->generate_userkey(); break; case '': dieprint_r("No case currently selected."); break; } include('controllers/footer.php'); diff --git a/includes/geo/galaxy.php b/includes/geo/galaxy.php index dd6c1b4..7a274f0 100755 --- a/includes/geo/galaxy.php +++ b/includes/geo/galaxy.php @@ -1,119 +1,119 @@ * @copyright 2010 Sébastien Santoro aka Dereckson * @license http://www.opensource.org/licenses/bsd-license.php BSD * @version 0.1 * @link http://scherzo.dereckson.be/doc/zed * @link http://zed.dereckson.be/ * @filesource */ /** * Geo galaxy class * * This class provides methods to convert coordinate polars. * * @todo create a unit testing file dev/tests/GeoGalaxyTest.php * @todo add unit testing for the normalizeAngle method in dev/tests/GeoGalaxyTest.php */ class GeoGalaxy { /* * ----------------------------------------------------------------------- * * Objects fetchers * ----------------------------------------------------------------------- * */ /** * Gets all the coordinates of the objects in the galaxy. * * @return array An array of array. Each item is [string object_name, string object_type, GeoPoint3D coordinates] */ static function getCoordinates () { global $db; $sql = "SELECT * FROM geo_coordinates"; if (!$result = $db->sql_query($sql)) message_die(SQL_ERROR, "Can't query geo_coordinates view.", '', __LINE__, __FILE__, $sql); $objects = array(); while ($row = $db->sql_fetchrow($result)) { //Demios ship xyz: [-50, 30, 40] //Kaos asteroid xyz: [150, -129, 10] $objects[] = array($row[0], $row[1], GeoPoint3D::fromString($row[2])); } return $objects; } /* * ----------------------------------------------------------------------- * * Helper methods - math * ----------------------------------------------------------------------- * */ /** * Normalizes an angle, so 0 =< angle < 2 PI * * @param float $angle angle in radians (use deg2rad() if you've degrees) * @return an angle in the 0 =< angle < 2 PI interval */ static function normalizeAngle ($angle) { while ($angle < 0) { $angle += 2 * M_PI; } while ($angle >= 2 * M_PI) { $angle -= 2 * M_PI; } return $angle; } /** * Converts (x, y, z) cartesian to (ρ, φ, θ) spherical coordinates * * The algo used is from http://fr.wikipedia.org/wiki/Coordonn%C3%A9es_sph%C3%A9riques#Relation_avec_les_autres_syst.C3.A8mes_de_coordonn.C3.A9es_usuels * * @param int $x the x coordinate * @param int $y the y coordinate * @param int $z the z coordinate * @return array an array of 3 floats number, representing the (ρ, φ, θ) spherical coordinates */ - static function cartesian_to_spherical ($x, $y, $z) { + static function cartesianToSpherical ($x, $y, $z) { $rho = sqrt($x * $x + $y * $y + $z * $z); //ρ = sqrt(x² + y² + z²) $theta= acos($z / $rho); //φ = acos z/φ $phi = acos($x / sqrt($x * $x + $y * $y)); //θ = acos x / sqrt(x² + y²) if (y < 0) $phi = 2 * M_PI - $phi; //∀ y < 0 θ = 2π - θ return array(round($rho, 2), round(rad2deg($theta), 2), round(rad2deg($phi), 2)); } /** * Converts (x, y, z) cartesian to (ρ, φ, θ) spherical coordinates * * The algo used is from http://www.phy225.dept.shef.ac.uk/mediawiki/index.php/Cartesian_to_polar_conversion * * @param int $x the x coordinate * @param int $y the y coordinate * @param int $z the z coordinate * @return array an array of 3 floats number, representing the (ρ, φ, θ) spherical coordinates */ - static function cartesian_to_spherical2 ($x, $y, $z) { + static function cartesianToSphericalAlternative ($x, $y, $z) { $rho = sqrt($x * $x + $y * $y + $z * $z); //ρ = sqrt(x² + y² + z²) $theta= atan2($y, $x); //φ = atan2 $y $x $phi = acos($z / $rho); //θ = acos z/φ return array(round($rho, 2), round(rad2deg($theta), 2), round(rad2deg($phi), 2)); } } diff --git a/includes/geo/location.php b/includes/geo/location.php index 91f1aca..1730620 100755 --- a/includes/geo/location.php +++ b/includes/geo/location.php @@ -1,434 +1,434 @@ * @copyright 2010 Sébastien Santoro aka Dereckson * @license http://www.opensource.org/licenses/bsd-license.php BSD * @version 0.1 * @link http://scherzo.dereckson.be/doc/zed * @link http://zed.dereckson.be/ * @filesource */ require_once('body.php'); require_once('place.php'); require_once('point3D.php'); require_once('includes/objects/ship.php'); /** * Geo location class * * This class contains properties to get, set or compare a location and * explore the geo classes linked to. * * It quickly allow to parse through the location classes in templates and * controllers. * * @todo Initialize $point3D from $body or $ship own locations * @todo Improve GeoLocation documentation (especially magic properties) */ class GeoLocation { /** * An array of strings containing location data. * * In the current class implementation, * the first element is the global location * and the second element is the local location. * * @var Aray */ private $data; /** * A body object * * It contains a GeoBody value when the global location is a body * ie if $this->data[0][0] == 'B' * * Otherwise, its value is null. * * @var GeoBody */ public $body = null; /** * A place object * * It contains a GeoPlacevalue when the global location is a place * ie if $this->data[0][0] == 'B' && strlen($this->data[0]) == 9 * * Otherwise, its value is null. * * @var GeoPlace */ public $place = null; /** * A point identified by x, y, z coordinates * * @var GeoPoint3D */ public $point3D = null; /** * A ship object * * It contains a Ship value when the global location is a ship * ie if $this->data[0][0] == 'S' * * Otherwise, its value is null. * * @var Ship */ public $ship = null; /** * Initializes a new location instance * * @param string $global the global location * @param string local the locallocation * * @todo Improve local location handling */ function __construct ($global = null, $local = null) { if (!$global) { $this->data = array(); } elseif (preg_match("/[BS][0-9]{5}[0-9]{3}/", $global)) { $this->data[0] = $global; } elseif (preg_match("/[BS][0-9]{5}/", $global)) { $this->data[0] = $global; } elseif (preg_match("/^xyz\:/", $global)) { $coords = sscanf($global, "xyz: [%d, %d, %d]"); if (count($coords) == 3) { $this->data[0] = $global; } else { throw new Exception("Invalid expression: $global"); } } else { global $db; $name = $db->sql_escape($global); $sql = "SELECT location_code FROM " . TABLE_LOCATIONS . " WHERE location_name LIKE '$name'"; $code = $db->sql_query_express($sql); if ($code) { $this->data[0] = $code; return; } throw new Exception("Invalid expression: $global"); } //TODO: handle $local in a better way: from the global location, gets //a local location handler. Or a some inheriance, like a class //HypershipGeoLocation extending GeoLocation. if ($local !== null) $this->data[1] = $local; $this->load_classes(); } /** * Gets $place, $body and $ship instances if they're needed */ function load_classes () { //No data, no class to load if (!count($this->data)) return; //Loads global classes $global = $this->data[0]; $code = substr($global, 1, 5); switch ($global[0]) { case 'B': switch (strlen($global)) { case 9: $this->place = GeoPlace::from_code($global); case 6: $this->body = new GeoBody($code); break; } break; case 'S': $this->ship = new Ship($code); break; case 'x': $coords = sscanf($global, "xyz: [%d, %d, %d]"); if (count($coords) == 3) { $this->point3D = new GeoPoint3D($coords[0], $coords[1], $coords[2]); } break; } } /** * Magic method called when a unknown property is get. * * Handles $global, $local, $type, $body_code, $ship_code, $place_code, * $body_kind, $containsGlobalLocation, $containsLocalLocation. */ function __get ($variable) { switch ($variable) { /* main variables */ case 'global': return $this->data[0]; break; case 'local': return (count($this->data) > 1) ? $this->data[1] : null; break; /* global location */ case 'type': return $this->data[0][0]; case 'body_code': if ($this->data[0][0] == 'B') { return substr($this->data[0], 1, 5); } return null; case 'place_code': if ($this->data[0][0] == 'B') { return substr($this->data[0], 6, 3); } return null; case 'ship_code': if ($this->data[0][0] == 'S') { return substr($this->data[0], 1, 5); } return null; case 'body_kind': if ($this->data[0][0] == 'B' && $this->body != null) { if ($kind = $this->body->kind()) { return $kind; } } elseif ($this->data[0][0] == 'S') { return 'ship'; } return 'place'; case 'containsGlobalLocation': return count($this->data) > 0; case 'containsLocalLocation': return count($this->data) > 1; default: throw new Exception("Unknown variable: $variable"); break; } } /** * Checks if the place exists * * @return bool true if the place exists ; otherwise, false. * * @todo Handle alias */ function exists () { $n = count($this->data); //If not defined, it doesn't exist if ($n == 0) return false; //Checks global location switch ($this->data[0][0]) { case 'B': switch (strlen($this->data[0])) { case 9: if (!$place = GeoPlace::from_code($this->data[0])) return false; break; case 6: $body = new GeoBody(substr($this->data[0], 1)); if ($body->lastError) return false; break; default: message_die(GENERAL_ERROR, "Invalid global location expression size: " . $this->data[0], "GeoLocation exists method", __LINE__, __FILE__); } break; case 'S': $ship = new Ship(substr($this->data[0], 1)); if ($body->lastError) return false; break; default: message_die(GENERAL_ERROR, "Invalid global location expression size: " . $this->data[0], "GeoLocation exists method", __LINE__, __FILE__); return false; } if ($n > 1) { if (!isset($place)) { message_die(GENERAL_ERROR, "Can't check if a local place exists for the following location: " . $this->data[0], "GeoLocation exists method", __LINE__, __FILE__); } if (!$place->is_valid_local_location($this->data[1])) { return false; } } return true; } /** * Checks if the place is equals at the specified expression or place * * @return bool true if the places are equals ; otherwise, false. * * @todo Create a better set of rules to define when 2 locations are equal. */ function equals ($expression) { //Are global location equals? //TODO: create a better set of rules to define when 2 locations are equal. if (is_a($expression, 'GeoLocation')) { if (!$this->equals($expression->data[0])) { return false; } if (count($expression->data) + count($this->data) > 2) { return $expression->data[1] == $this->data[1]; } } if ($expression == $this->data[0]) return true; $n1 = strlen($expression); $n2 = strlen($this->data[0]); if ($n1 > $n2) { return substr($expression, 0, $n2) == $this->data[0]; } return false; } /** * Represents the current location instance as a string * * @return string a string representing the current location */ function __toString () { if (!$this->data[0]) return ""; switch ($this->data[0][0]) { case 'S': $ship = new Ship($this->ship_code); $location[] = $ship->name; break; case 'B': $body = new GeoBody($this->body_code); $location[] = $body->name ? $body->name : lang_get('UnknownBody'); if (strlen($this->data[0]) == 9) { $place = GeoPlace::from_code($this->data[0]); $location[] = $place->name ? $place->name : lang_get('UnknownPlace'); } break; case 'x': - $pt = $this->point3D->to_spherical(); + $pt = $this->point3D->toSpherical(); return sprintf("(%d, %d°, %d°)", $pt[0], $pt[1], $pt[2]); default: message_die(GENERAL_ERROR, "Unknown location identifier: $type.
Expected: B or S."); } return implode(", ", array_reverse($location)); } /** * Magic method called when a unknown property is set. * * Handles $global, $local, $type, $body_code, $ship_code, $place_code */ function __set ($variable, $value) { switch ($variable) { /* main variables */ case 'global': $this->data[0] = $value; break; case 'local': $this->data[1] = $value; break; /* global location */ case 'type': if ($value == 'B' || $value == 'S') { if (!$this->data[0]) { $this->data[0] = $value; } else { $this->data[0][0] = $value; } } break; case 'body_code': if (preg_match("/[0-9]{1,5}/", $value)) { $value = sprintf("%05d", $value); if (!$this->data[0]) { $this->data[0] = "B" . $value; return; } elseif ($this->data[0][0] == 'B') { $this->data[0] = "B" . $value . substr($this->data[0], 6); return; } throw new Exception("Global location isn't a body."); } throw new Exception("$value isn't a valid body code"); case 'ship_code': if (preg_match("/[0-9]{1,5}/", $value)) { $value = sprintf("%05d", $value); if (!$this->data[0]) { $this->data[0] = "S" . $value; return; } elseif ($this->data[0][0] == 'S') { $this->data[0] = "S" . $value . substr($this->data[0], 6); return; } throw new Exception("Global location isn't a ship."); } throw new Exception("$value isn't a valid ship code"); case 'place_code': if (!preg_match("/[0-9]{1,3}/", $value)) { throw new Exception("$value isn't a valid place code"); } $value = sprintf("%03d", $value); if ($this->data[0][0] == 'B') { $this->data[0] = substr($this->data[0], 0, 6) . $value; } throw new Exception("Global location isn't a body."); default: throw new Exception("Unknown variable: $variable"); break; } } } diff --git a/includes/geo/point3D.php b/includes/geo/point3D.php index 1d4491b..577163b 100755 --- a/includes/geo/point3D.php +++ b/includes/geo/point3D.php @@ -1,239 +1,239 @@ * @copyright 2010 Sébastien Santoro aka Dereckson * @license http://www.opensource.org/licenses/bsd-license.php BSD * @version 0.1 * @link http://scherzo.dereckson.be/doc/zed * @link http://zed.dereckson.be/ * @filesource */ require_once("galaxy.php"); /** * Geo point 3D class. * * This class represents a x, y, z point. * * It implements IteratorAggregate to allow the foreach instruction * on a GeoPoint3D object: * * * $point = new GeoPoint3D(17, 24, -6); * foreach ($point as $axis => $coordinate) { * echo "\n\t$axis = $coordinate"; * } * //This will output: * // x = 17 * // y = 24 * // z = -6 * * * The point 3D representation is xyz: [x, y, z] ; you can print it as a string * and get this format: * * * $point = new GeoPoint3D(17, 24, -6); * echo (string)$point; //will output xyz: [17, 24, -6] * * */ class GeoPoint3D implements IteratorAggregate { // // x, y, z public properties // /** * the x coordinate * * @var integer */ public $x; /** * the y coordinate * * @var integer */ public $y; /** * the z coordinate * * @var integer */ public $z; // // constructor / toString // /** * Initializes a new instance of GeoPoint3D class * * @param int $x the x coordinate * @param int $y the y coordinate * @param int $z the z coordinate */ function __construct ($x, $y, $z) { $this->x = (int)$x; $this->y = (int)$y; $this->z = (int)$z; } /** * Parses a string expression ang gets a GeoPoint3D object * * Formats recognized are: * - xyz: [x, y, z] * - (x, y, z) * * @param string $expression the expression to parse * @return GeoPoint3D If the specified expression could be parsed, a GeoPoint3D instance ; otherwise, null. */ static function fromString ($expression) { if (string_starts_with($expression, 'xyz:', false)) { $pos1 = strpos($expression, '[', 4) + 1; $pos2 = strpos($expression, ']', $pos1); if ($pos1 > -1 && $pos2 > -1) { $expression = substr($expression, $pos1, $pos2 - $pos1); $xyz = explode(',', $expression, 3); return new GeoPoint3D($xyz[0], $xyz[1], $xyz[2]); } } elseif ($expression[0] = '(') { $expression = substr($expression, 1, -1); $xyz = explode(',', $expression, 3); return new GeoPoint3D($xyz[0], $xyz[1], $xyz[2]); } return null; } /** * Returns a string representation of the point coordinates. * * @param $format the format to use * @return string a string representation of the coordinates * * To print a "xyz: [10, 20, 40]" string: * $point = new GeoPoint3D(10, 20, 40); * echo $point->sprintf("xyz: [%d, %d, %d]"); * * //Of course, you could have (implicitely) use the __toString method: * echo $point; * * To print a (10, 20, 40) string: * $point = new GeoPoint3D(10, 20, 40); * echo $point->sprintf("(%d, %d, %d)"); */ function sprintf ($format) { return sprintf($format, $this->x, $this->y, $this->z); } /** * Returns a xyz: [x, y, z] string representation of the point coordinates. * * @return string a xyz: [x, y, z] string representation of the coordinates */ function __toString () { return $this->sprintf("xyz: [%d, %d, %d]"); } /** * Determines if this point is equal to the specified point. * * @param GeoPoint3D $point The point to compare * @return bool true if the two points are equal ; otherwise, false. */ function equals ($point) { return ($this->x == $point->x) && ($this->y == $point->y) && ($this->z == $point->z); } // // Math // /** * Gets the (ρ, φ, θ) spherical coordinates from the current x, y, z cartesian point * * The algo used is from http://fr.wikipedia.org/wiki/Coordonn%C3%A9es_sph%C3%A9riques#Relation_avec_les_autres_syst.C3.A8mes_de_coordonn.C3.A9es_usuels * * @return array an array of 3 floats number, representing the (ρ, φ, θ) spherical coordinates */ - function to_spherical () { - return GeoGalaxy::cartesian_to_spherical($this->x, $this->y, $this->z); + function toSpherical () { + return GeoGalaxy::cartesianToSpherical($this->x, $this->y, $this->z); } /** * Gets the (ρ, φ, θ) spherical coordinates from the current x, y, z cartesian point * * The algo used is from http://www.phy225.dept.shef.ac.uk/mediawiki/index.php/Cartesian_to_polar_conversion * * @return array an array of 3 floats number, representing the (ρ, φ, θ) spherical coordinates */ - function to_spherical2 () { - return GeoGalaxy::cartesian_to_spherical2($this->x, $this->y, $this->z); + function toSphericalAlternative () { + return GeoGalaxy::cartesianToSphericalAlternative($this->x, $this->y, $this->z); } /** * Translates the center and rescales. * * This method allow to help to represent coordinate in a new system * * This method is used to represent Zed objects in dojo with the following * parameters: * * $pointKaos = GeoPoint3D(800, 42, 220); * $pointKaos->translate(500, 300, 200, 2); * echo $pointKaos; * //This will output xyz: [150, -129, 10] * * * @param int $dx the difference between the old x and new x (ie the value of x = 0 in the new system) * @param int $dy the difference between the old y and new y (ie the value of y = 0 in the new system) * @param int $dz the difference between the old y and new z (ie the value of z = 0 in the new system) * @param float $scale if specified, divides each coordinate by this value (optional) */ function translate ($dx, $dy, $dz, $scale = 1) { if ($scale == 1) { $this->x += $dx; $this->y += $dy; $this->z += $dz; } elseif ($scale == 0) { $this->x = 0; $this->y = 0; $this->z = 0; } else { $this->x = $this->x * $scale + $dx; $this->y = $this->y * $scale + $dy; $this->z = $this->z * $scale + $dz; } } // // Implementing IteratorAggregate // /** * Retrieves class iterator. It traverses x, y and z. * * @return Traversable the iterator */ function getIterator () { return new ArrayIterator($this); } } diff --git a/includes/geo/pointPolarZ.php b/includes/geo/pointPolarZ.php index a7c482a..49e965f 100755 --- a/includes/geo/pointPolarZ.php +++ b/includes/geo/pointPolarZ.php @@ -1,374 +1,374 @@ * @copyright 2010 Sébastien Santoro aka Dereckson * @license http://www.opensource.org/licenses/bsd-license.php BSD * @version 0.1 * @link http://scherzo.dereckson.be/doc/zed * @link http://zed.dereckson.be/ * @filesource */ require_once("point3D.php"); /** * Geo point polar+z class. * * This class represents a r, ρ, z point. * * They are useful to express coordinates in a cylinder shape, like a tower * where it make senses to use polar coordinates instead x, y but where the * height is not relative to a center, like it would be in a sphere. * * It implements IteratorAggregate to allow the foreach instruction * on a GeoPointPolarZ object: * * * $point = new GeoPointPolarZ(17, '24°', -6); * foreach ($point as $axis => $coordinate) { * echo "\n\t$axis = $coordinate"; * } * //This will output: * // r = 17 * // t = 24° * // z = -6 * * * The point 3D representation is rtz: [ρ, θ, z] ; you can print it as a string * and get this format: * * * $point = new GeoPointPolarZ(17, '24°', -6); * echo (string)$point; //will output rρz: [17, 24°, -6] * * */ class GeoPointPolarZ implements IteratorAggregate { // // ρ, θ, z public properties // /** * the ρ coordinate * * @var float */ public $r; /** * the θ coordinate * * This coordinate could be expressed as: * - a string with a float, appended by "°" or " °" (in degree) * - as a float (in radian) * * @var mixed */ public $t; /** * the z coordinate * * @var float */ public $z; // // constructor / toString // /** * Initializes a new instance of GeoPointPolarZ class * * @param float $r the ρ coordinate * @param mixed $t the θ coordinate, in ° (string) or radian (float) * @param float $z the z coordinate */ function __construct ($r, $t, $z) { $this->r = (float)$r; $this->t = trim($t); $this->z = (float)$z; } /** * Parses a string expression ang gets a GeoPointPolarZ object * * Formats recognized are: * - rtz: [ρ, θ, z] * - (ρ, θ, z) * * @param string $expression the expression to parse * @return GeoPointPolarZ If the specified expression could be parsed, a GeoPointPolarZ instance ; otherwise, null. */ static function fromString ($expression) { if (string_starts_with($expression, 'rtz:', false)) { $pos1 = strpos($expression, '[', 4) + 1; $pos2 = strpos($expression, ']', $pos1); if ($pos1 > -1 && $pos2 > -1) { $expression = substr($expression, $pos1, $pos2 - $pos1); $rtz = explode(',', $expression, 3); return new GeoPointPolarZ($rtz[0], $rtz[1], $rtz[2]); } } elseif ($expression[0] = '(') { $expression = substr($expression, 1, -1); $rtz = explode(',', $expression, 3); return new GeoPointPolarZ($rtz[0], $rtz[1], $rtz[2]); } return null; } /** * Returns a string representation of the point coordinates. * * @param $format the format to use * @return string a string representation of the coordinates * * To print a "rtz: [10, 20°, 40]" string: * $point = new GeoPointPolarZ(10, '20°', 40); * echo $point->sprintf("rtz: [%d, %s, %d]"); * * //Of course, you could have (implicitely) use the __toString method: * echo $point; * * To print a (10, 20°, 40) string: * $point = new GeoPointPolarZ(10, 20°, 40); * echo $point->sprintf("(%d, %s, %d)"); */ function sprintf ($format) { return sprintf($format, $this->r, self::get_degrees($this->t), $this->z); } /** * Returns a rρz: [r, ρ, z] string representation of the point coordinates. * * @return string a rtz: [ρ, θ, z] string representation of the coordinates */ function __toString () { return $this->sprintf("rtz: [%d, %s, %d]"); } /** * Determines if this point is equal to the specified point. * * @param GeoPointPolarZ $point The point to compare * @return bool true if the two points are equal ; otherwise, false. */ function equals ($point) { return ($this->r == $point->r) && self::angle_equals($this->t, $point->t) && ($this->z == $point->z); } /** * Detemrines if two angles are equal * @param mixed $angle1 the first angle value, ie a float (angle in radian) or a string formed by an integed appended by ° (degrees) * @param mixed $angle2 the second angle value, a float (angle in radian) or a string formed by an integed appended by ° (degrees) * @return bool true if the angles are equal ; otherwise, false. */ static function angle_equals ($angle1, $angle2) { if ($angle1 === $angle2) return true; if (!is_numerical($angle1)) { $angle1 = deg2rad((float)$angle1); } if (!is_numerical($angle2)) { $angle2 = deg2rad((float)$angle2); } $angle1 = self::normalizeAngle($angle1); $angle2 = self::normalizeAngle($angle2); return ($angle1 == $angle2); } /** * Normalizes an angle (in radians) in the interval [0, π[ (or a custom interval) * * @param float $angle the angle (in radians) * @param float $min the radians value the angle must be greater or equal than [optional, default value: 0] * @param float $max the radains value the angle must be stricly lesser than [optional, default value: M_PI] * @param float $interval the increment interval [optional, default value: 360] */ static function normalizeAngle ($angle, $min = 0, $max = M_PI, $interval = M_PI) { while ($angle < $min) { $angle += $interval; } while ($angle >= $max) { $angle -= $interval; } return $angle; } /** * Normalizes an angle (in degrees) in the interval [0, 360[ (or a custom interval) * * @param float $angle the angle to normalize, in degrees * @param float $min the degrees value the angle must be greater or equal than [optional, default value: 0] * @param float $max the degrees value the angle must be stricly lesser than [optional, default value: 360] * @param float $interval the increment interval [optional, default value: 360] */ static function normalizeAngleInDegrees ($angle, $min = 0, $max = 360, $interval = 360) { while ($angle < $min) { $angle += $interval; } while ($angle >= $max) { $angle -= $interval; } return $angle; } /** * Gets the specified angle in radians * * @param mixed $angle the angle, a float in radians or a string (a float + "°" or " °" in degrees * @return float the angle in radians */ static function get_radians ($angle) { return is_numeric($angle) ? $angle : deg2rad((float)$angle); } /** * Gets the specified angle in degrees * * @param mixed $angle the angle, a float in radians or a string (a float + "°" or " °" in degrees * @return string the angle (float) in degrees followed by "°" */ static function get_degrees ($angle) { return is_numeric($angle) ? rad2deg((float)$angle) . '°' : $angle; } /** * Converts a polar coordinate angle to a 0-360° CW angle */ static function get_natural_degrees ($angle) { return self::normalizeAngleinDegrees(90 - self::get_degrees($angle)); } // // Math // /** * Gets the (x, y, z) cartesian coordinates from the current ρ, θ, z polar+z point * * @return array an array of 3 floats number, representing the (x, y, z) cartesian coordinates */ - function to_cartesian () { + function toCartesian () { $x = $this->r * cos(self::get_radians($this->t)); $y = $this->r * sin(self::get_radians($this->t)); return array($x, $y, $this->z); } /** * Converts the current GeoPointPolarZ instance to a GeoPoint3D instance * * @return GeoPoint3D an instance of the GeoPoint3D class representing the (x, y, z) cartesian coordinates */ function to_Point3D () { - $pt = $this->to_cartesian(); + $pt = $this->toCartesian(); return new GeoPoint3D($pt[0], $pt[1], $pt[2]); } /** * Gets the (ρ, φ, θ) spherical coordinates from the current (ρ, θ, z) polar+z point * * The algo used is from http://fr.wikipedia.org/wiki/Coordonn%C3%A9es_sph%C3%A9riques#Relation_avec_les_autres_syst.C3.A8mes_de_coordonn.C3.A9es_usuels * * @return array an array of 3 floats number, representing the (ρ, φ, θ) spherical coordinates */ - function to_spherical () { - $pt = $this->to_cartesian(); - return GeoGalaxy::cartesian_to_spherical($pt[0], $pt[1], $pt[2]); + function toSpherical () { + $pt = $this->toCartesian(); + return GeoGalaxy::cartesianToSpherical($pt[0], $pt[1], $pt[2]); } /** * Gets the (ρ, φ, θ) spherical coordinates from the current (ρ, θ, z) polar+z point * * The algo used is from http://www.phy225.dept.shef.ac.uk/mediawiki/index.php/Cartesian_to_polar_conversion * * @return array an array of 3 floats number, representing the (ρ, φ, θ) spherical coordinates */ - function to_spherical2 () { - $pt = $this->to_cartesian(); - return GeoGalaxy::cartesian_to_spherical2($pt[0], $pt[1], $pt[2]); + function toSphericalAlternative () { + $pt = $this->toCartesian(); + return GeoGalaxy::cartesianToSphericalAlternative($pt[0], $pt[1], $pt[2]); } /** * Translates the center and rescales. * * This method allow to help to represent coordinate in a new system * * This method is used to represent Zed objects in dojo with the following * parameters: * * $pointKaos = GeoPointPolarZ(800, 42, 220); * $pointKaos->translate(500, 300, 200, 2); * echo $pointKaos; * //This will output rρz: [150, -129, 10] * * * @param float $dr the difference between the old ρ and new ρ (ie the value of ρ = 0 in the new system) * @param float $dt the difference between the old θ and new θ (ie the value of θ = 0 in the new system) * @param float $dz the difference between the old y and new z (ie the value of z = 0 in the new system) * @param int $scale if specified, divides each coordinate by this value (optional) */ function translate ($dr, $dt, $dz, $scale = 1) { if ($scale == 1) { $this->r += $dr; $this->t += $dt; $this->z += $dz; } elseif ($scale == 0) { $this->r = 0; $this->t = 0; $this->z = 0; } else { $this->r = $this->r * $scale + $dr; $this->t = $this->t * $scale + $dt; $this->z = $this->z * $scale + $dz; } } /** * Calculates the section number the specified angle belongs * * @param $angle float The natural angle in degree (North 0°, East 90°, etc. clockwise) * @param int $count the number of sections (default value: 6) * @return $int the section number */ static function calculate_section ($angle, $count = 6) { if ($angle < 90) { $angle += 270; } else { $angle -= 90; } return 1 + (int)($angle / (360/$count)); } /** * Gets the section number the θ angle belongs to. * * @param int $count the number of sections * @return $int the section number */ function get_section ($count = 6) { return self::calculate_section(self::get_natural_degrees($this->t), $count); } // // Implementing IteratorAggregate // /** * Retrieves class iterator. It traverses ρ, θ and z. * * @return Traversable the iterator */ function getIterator () { return new ArrayIterator($this); } }