1 /*
2  * Copyright (c) 2016 Martin Davis.
3  *
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
7  * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
8  * and the Eclipse Distribution License is available at
9  *
10  * http://www.eclipse.org/org/documents/edl-v10.php.
11  */
12 
13 package org.locationtech.jts.math;
14 
15 import org.locationtech.jts.geom.Coordinate;
16 
17 /**
18  * Models a plane in 3-dimensional Cartesian space.
19  *
20  * @author mdavis
21  *
22  */
23 public class Plane3D {
24 
25 	/**
26 	 * Enums for the 3 coordinate planes
27 	 */
28 	public static final int XY_PLANE = 1;
29 	public static final int YZ_PLANE = 2;
30 	public static final int XZ_PLANE = 3;
31 
32 	private Vector3D normal;
33 	private Coordinate basePt;
34 
Plane3D(Vector3D normal, Coordinate basePt)35 	public Plane3D(Vector3D normal, Coordinate basePt)
36 	{
37 		this.normal = normal;
38 		this.basePt = basePt;
39 	}
40 
41 	/**
42 	 * Computes the oriented distance from a point to the plane.
43 	 * The distance is:
44 	 * <ul>
45 	 * <li><b>positive</b> if the point lies above the plane (relative to the plane normal)
46 	 * <li><b>zero</b> if the point is on the plane
47 	 * <li><b>negative</b> if the point lies below the plane (relative to the plane normal)
48 	 * </ul>
49 	 *
50 	 * @param p the point to compute the distance for
51 	 * @return the oriented distance to the plane
52 	 */
orientedDistance(Coordinate p)53 	public double orientedDistance(Coordinate p) {
54 		Vector3D pb = new Vector3D(p, basePt);
55 		double pbdDotNormal = pb.dot(normal);
56 		if (Double.isNaN(pbdDotNormal))
57 			throw new IllegalArgumentException("3D Coordinate has NaN ordinate");
58 		double d = pbdDotNormal / normal.length();
59 		return d;
60 	}
61 
62 	/**
63 	 * Computes the axis plane that this plane lies closest to.
64 	 * <p>
65 	 * Geometries lying in this plane undergo least distortion
66 	 * (and have maximum area)
67 	 * when projected to the closest axis plane.
68 	 * This provides optimal conditioning for
69 	 * computing a Point-in-Polygon test.
70 	 *
71 	 * @return the index of the closest axis plane.
72 	 */
closestAxisPlane()73 	public int closestAxisPlane() {
74 		double xmag = Math.abs(normal.getX());
75 		double ymag = Math.abs(normal.getY());
76 		double zmag = Math.abs(normal.getZ());
77 		if (xmag > ymag) {
78 			if (xmag > zmag)
79 				return YZ_PLANE;
80 			else
81 				return XY_PLANE;
82 		}
83 		// y >= x
84 		else if (zmag > ymag) {
85 			return XY_PLANE;
86 		}
87 		// y >= z
88 		return XZ_PLANE;
89 	}
90 
91 }
92