/** return a vector orthogonal to this one */ public function ortho() { $k = $this->largestAbsComponent(); if ($k == 1) { $temp = new S2Point(1, 0, 0); } else { if ($k == 2) { $temp = new S2Point(0, 1, 0); } else { $temp = new S2Point(0, 0, 1); } } return S2Point::normalize($this->crossProd($this, $temp)); }
public static function toPoint() { return S2Point::normalize(self::toPointRaw()); }
/** * Return the average area for cells at the given level. *#/ * public static double averageArea(int level) { * return S2Projections.AVG_AREA.getValue(level); * } * * /** * Return the average area of cells at this level. This is accurate to within * a factor of 1.7 (for S2_QUADRATIC_PROJECTION) and is extremely cheap to * compute. *#/ * public double averageArea() { * return averageArea(level); * } * * /** * Return the approximate area of this cell. This method is accurate to within * 3% percent for all cell sizes and accurate to within 0.1% for cells at * level 5 or higher (i.e. 300km square or smaller). It is moderately cheap to * compute. *#/ * public double approxArea() { * * // All cells at the first two levels have the same area. * if (level < 2) { * return averageArea(level); * } * * // First, compute the approximate area of the cell when projected * // perpendicular to its normal. The cross product of its diagonals gives * // the normal, and the length of the normal is twice the projected area. * double flatArea = 0.5 * S2Point.crossProd( * S2Point.sub(getVertex(2), getVertex(0)), S2Point.sub(getVertex(3), getVertex(1))).norm(); * * // Now, compensate for the curvature of the cell surface by pretending * // that the cell is shaped like a spherical cap. The ratio of the * // area of a spherical cap to the area of its projected disc turns out * // to be 2 / (1 + sqrt(1 - r*r)) where "r" is the radius of the disc. * // For example, when r=0 the ratio is 1, and when r=1 the ratio is 2. * // Here we set Pi*r*r == flat_area to find the equivalent disc. * return flatArea * 2 / (1 + Math.sqrt(1 - Math.min(S2.M_1_PI * flatArea, 1.0))); * } * * /** * Return the area of this cell as accurately as possible. This method is more * expensive but it is accurate to 6 digits of precision even for leaf cells * (whose area is approximately 1e-18). *#/ * public double exactArea() { * S2Point v0 = getVertex(0); * S2Point v1 = getVertex(1); * S2Point v2 = getVertex(2); * S2Point v3 = getVertex(3); * return S2.area(v0, v1, v2) + S2.area(v0, v2, v3); * } * * // ////////////////////////////////////////////////////////////////////// * // S2Region interface (see {@code S2Region} for details): * * @Override * public S2Region clone() { * S2Cell clone = new S2Cell(); * clone.face = this.face; * clone.level = this.level; * clone.orientation = this.orientation; * clone.uv = this.uv.clone(); * * return clone; * } */ public function getCapBound() { // Use the cell center in (u,v)-space as the cap axis. This vector is // very close to GetCenter() and faster to compute. Neither one of these // vectors yields the bounding cap with minimal surface area, but they // are both pretty close. // // It's possible to show that the two vertices that are furthest from // the (u,v)-origin never determine the maximum cap size (this is a // possible future optimization). $u = 0.5 * ($this->uv[0][0] + $this->uv[0][1]); $v = 0.5 * ($this->uv[1][0] + $this->uv[1][1]); $cap = S2Cap::fromAxisHeight(S2Point::normalize(S2Projections::faceUvToXyz($this->face, $u, $v)), 0); for ($k = 0; $k < 4; ++$k) { $cap = $cap->addPoint($this->getVertex($k)); } return $cap; }