SpaceNode.php:
SpaceNode.php:
-Added get_infra_list()
-Added coordinate type check (infra inherits ultra)
-Redid get_location(T_STRING) to be more generic.
Coords.php:
-Added string() to all classes
-Added magnitude() to all classes
-Added convert() to all classes TODO: Make this less duplicative?
-Fixed conversion of Cartesian to Spherical because I was stupid before.
-Added basic vector arithmetic to the abstract
UniSim.php:
-Added a loop to read children of $universe.
-Added some trivial vector arithmetic test cases.

file:a/Coords.php -> file:b/Coords.php
--- a/Coords.php
+++ b/Coords.php
@@ -2,6 +2,27 @@
 abstract class Coords {
 	// This is a stub that may contain functions or parameters that apply universally to all coordinate systems,
 	// but may never be instantiated itself.
+	
+	public function vector_add($vector2) {
+		$class = get_class($this);
+		$vector1 = $this->convert("CartesianCoords");
+		$vector2 = $vector2->convert("CartesianCoords");
+		list($x1, $y1, $z1) = $vector1->triplet();
+		list($x2, $y2, $z2) = $vector2->triplet();
+		$vector3 = new CartesianCoords($x1+$x2, $y1+$y2, $z1+$z2);
+		return $vector3->convert($class);
+	}
+	
+	public function vector_subtract($vector2) {
+		$class = get_class($this);
+		$vector1 = $this->convert("CartesianCoords");
+		$vector2 = $vector2->convert("CartesianCoords");
+		list($x1, $y1, $z1) = $vector1->triplet();
+		list($x2, $y2, $z2) = $vector2->triplet();
+		$vector3 = new CartesianCoords($x1-$x2, $y1-$y2, $z1-$z2);
+		return $vector3->convert($class);
+	}
+	
 }
 
 class SphericalCoords extends Coords {
@@ -21,12 +42,33 @@
 		);
 	}
 
-	public function to_Cartesian() {
-		return new CartesianCoords(
-			$this->radius * sin($this->theta) * cos($this->phi),
-			$this->radius * sin($this->theta) * sin($this->phi),
-			$this->radius * cos($this->theta)
-		);
+	public function convert($class) {
+		switch ($class) {
+			case "SphericalCoords":
+				return $this;
+				break;
+			case "CartesianCoords":
+				return new CartesianCoords(
+					$this->radius * sin($this->theta) * cos($this->phi),
+					$this->radius * sin($this->theta) * sin($this->phi),
+					$this->radius * cos($this->theta)
+				);
+				break;
+			case "LinearCoords":
+				return new LinearCoords($this->radius);
+				break;
+			default:
+				throw new Exception(sprintf("Cannot convert from type '%s' to type '%s'.", get_class($this), $class));
+				break;
+		}
+	}
+	
+	public function string() {
+		return sprintf("r = %.2f, ϑ = %.2f, ϕ = %.2f", $this->radius, $this->theta, $this->phi);
+	}
+	
+	public function magnitude() {
+		return $this->radius;
 	}
 
 	protected $radius = 0;
@@ -50,12 +92,33 @@
 		$this->z
 		);
 	}
+	
+	public function string() {
+		return sprintf("x = %.2f, y = %.2f, z = %.2f", $this->x, $this->y, $this->z);
+	}
+	
+	public function magnitude() {
+		return sqrt(pow($this->x,2) + pow($this->y,2) + pow($this->z,2));
+	}
 	 
-	public function to_Spherical() {
-		$r = pow($this->x,2) * pow($this->y,2) * pow($this->z,2);
-		$t = acos($this->z / $r);
-		$p = acos($this->y / $this->x);
-		return new SphericalCoords($r, $t, $p);
+	public function convert($class) {
+		switch ($class) {
+			case "SphericalCoords":
+				$r = sqrt(pow($this->x,2) + pow($this->y,2) + pow($this->z,2));
+				$t = acos($this->z / $r);
+				$p = atan2($this->y, $this->x);
+				return new SphericalCoords($r, $t, $p);
+				break;
+			case "CartesianCoords":
+				return $this;
+				break;
+			case "LinearCoords":
+				return new LinearCoords($this->magnitude());
+				break;
+			default:
+				throw new Exception(sprintf("Cannot convert from type '%s' to type '%s'.", get_class($this), $class));
+				break;
+		}
 	}
 	 
 	protected $x = 0;
@@ -65,7 +128,7 @@
 
 class LinearCoords extends CartesianCoords {
 	public function __construct($d) {
-		// make a car;tesian object, with just one axis
+		// make a cartesian object, with just one axis
 		$this->y = 0;
 		$this->z = 0;
 		$this->x = $d;
@@ -73,6 +136,10 @@
 		return $this;
 	}
 	
+	public function string() {
+		return "x = " . $this->x;
+	}
+	
 	public function magnitude() {
 		return $this->x;
 	}

--- a/SpaceNode.php
+++ b/SpaceNode.php
@@ -45,9 +45,16 @@
 	public function get_ultra() {

 		return $this->ultra;

 	}

+	

+	public function get_infra_list() {

+		return $this->child_list;

+	}

 

 	public function add_infra($infra) {

 		if (empty($this->child_list[$infra->id()])) {

+			if (!$infra->check_coords_type(get_class($this->relative_coords))) {

+				throw new Exception("Failed to get coordinates in the same reference!");

+			}

 			$infra_r = $infra->get_location(T_DNUMBER) + $infra->get_radius();

 			if ($infra_r > $this->mean_radius) {

 				$this->grow_radius($infra_r);

@@ -75,16 +82,27 @@
 	}

 	

 	public function get_location($type) {

-		list($a, $b, $c) = $this->relative_coords->triplet();

 		switch ($type) {

 			case T_STRING:

-				return "x = $a, y = $b, z = $c";

+				return $this->relative_coords->string();

 				break;

 			case T_DNUMBER:

 				return $this->relative_coords->magnitude();

 			default:

 				break;

 		}

+	}

+	

+	protected function check_coords_type($class) {

+		if (get_class($this->relative_coords) == $class) {

+			return true;

+		} else {

+			return ($this->relative_coords = $this->relative_coords->convert($class));

+		}

+	}

+	

+	public function describe() {

+		return sprintf("Node #%s '%s', with radius %.2f at relative location %s.\n", $this->id, $this->name, $this->mean_radius, $this->get_location(T_STRING));

 	}

 

 	protected $name = "";


file:a/UniSim.php -> file:b/UniSim.php
--- a/UniSim.php
+++ b/UniSim.php
@@ -3,12 +3,24 @@
 require_once("SpaceNode.php");
 require_once("Coords.php");
 
-$universe = new SpaceNode("universe node", 0, new LinearCoords(0), null);
-printf("Made new node '%s' with radius %.2g at coordinates %s.\n", $universe->name(), $universe->get_radius(), $universe->get_location(T_STRING));
+$universe = new SpaceNode("universe node", 0, new SphericalCoords(0,0,0), null);
 
 $node1 = new SpaceNode("node1", 40, new LinearCoords(40), $universe);
-printf("Made new node '%s' with parent '%s' with radius %.2g at coordinates %s.\n", $node1->name(), $node1->get_ultra()->name(), $node1->get_radius(), $node1->get_location(T_STRING));
 
-printf("'%s' has new radius %.2f\n", $universe->name(), $universe->get_radius());
+echo $universe->describe();
+
+$infra_list = $universe->get_infra_list();
+foreach ($infra_list as $infra) {
+	echo $infra->describe();
+}
+
+$vector1 = new SphericalCoords(5, M_PI/4, M_PI/8);
+printf("Vector1: %s\n", $vector1->string());
+$vector2 = new CartesianCoords(7, 6, 5);
+printf("Vector2: %s\n", $vector2->string());
+$vector3 = $vector1->vector_add($vector2);
+printf("Vector3 = Vector1 + Vector2: %s\n", $vector3->string());
+$vector4 = $vector1->vector_subtract($vector2);
+printf("Vector4 = Vector1 - Vector2: %s\n", $vector4->string());
 
 ?>