blob: 51e0cf775a8cdc25094d5a6097e26b688c20f46a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.geometry.euclidean.threed;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.apache.commons.geometry.core.Transform;
import org.apache.commons.geometry.core.partitioning.ConvexSubHyperplane;
import org.apache.commons.geometry.core.partitioning.Hyperplane;
import org.apache.commons.geometry.core.partitioning.Split;
import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
import org.apache.commons.geometry.euclidean.threed.Plane.SubspaceTransform;
import org.apache.commons.geometry.euclidean.twod.AffineTransformMatrix2D;
import org.apache.commons.geometry.euclidean.twod.ConvexArea;
import org.apache.commons.geometry.euclidean.twod.Vector2D;
/** Class representing a convex subhyperplane in 3 dimensional Euclidean space, meaning
* a 2D convex area embedded in a plane.
*/
public final class ConvexSubPlane extends AbstractSubPlane<ConvexArea>
implements ConvexSubHyperplane<Vector3D> {
/** The embedded 2D area. */
private final ConvexArea area;
/** Create a new instance from its component parts.
* @param plane plane the the convex area is embedded in
* @param area the embedded convex area
*/
private ConvexSubPlane(final Plane plane, final ConvexArea area) {
super(plane);
this.area = area;
}
/** {@inheritDoc} */
@Override
public List<ConvexSubPlane> toConvex() {
return Arrays.asList(this);
}
/** {@inheritDoc} */
@Override
public ConvexSubPlane reverse() {
final Plane plane = getPlane();
final Plane rPlane = plane.reverse();
final Vector2D rU = rPlane.toSubspace(plane.toSpace(Vector2D.Unit.PLUS_X));
final Vector2D rV = rPlane.toSubspace(plane.toSpace(Vector2D.Unit.PLUS_Y));
final AffineTransformMatrix2D transform =
AffineTransformMatrix2D.fromColumnVectors(rU, rV);
return new ConvexSubPlane(rPlane, area.transform(transform));
}
/** {@inheritDoc} */
@Override
public ConvexSubPlane transform(final Transform<Vector3D> transform) {
final SubspaceTransform st = getPlane().subspaceTransform(transform);
final ConvexArea tArea = area.transform(st.getTransform());
return fromConvexArea(st.getPlane(), tArea);
}
/** {@inheritDoc} */
@Override
public ConvexArea getSubspaceRegion() {
return area;
}
/** {@inheritDoc} */
@Override
public Split<ConvexSubPlane> split(Hyperplane<Vector3D> splitter) {
return splitInternal(splitter, this, (p, r) -> new ConvexSubPlane(p, (ConvexArea) r));
}
/** Get the vertices for the subplane. The vertices lie at the intersections of the
* 2D area bounding lines.
* @return the vertices for the subplane
*/
public List<Vector3D> getVertices() {
return getPlane().toSpace(area.getVertices());
}
/** Create a new instance from a plane and an embedded convex subspace area.
* @param plane embedding plane for the area
* @param area area embedded in the plane
* @return a new convex sub plane instance
*/
public static ConvexSubPlane fromConvexArea(final Plane plane, final ConvexArea area) {
return new ConvexSubPlane(plane, area);
}
/** Create a new instance from the given sequence of points. The points must define a unique plane, meaning that
* at least 3 unique vertices must be given. In contrast with the
* {@link #fromVertices(Collection, DoublePrecisionContext)} method, the first point in the sequence is included
* at the end if needed, in order to form a closed loop.
* @param pts collection of points defining the convex subplane
* @param precision precision context used to compare floating point values
* @return a new instance defined by the given sequence of vertices
* @throws IllegalArgumentException if fewer than 3 vertices are given
* @throws org.apache.commons.geometry.core.exception.GeometryException if the vertices do not define a
* unique plane
* @see #fromVertices(Collection, DoublePrecisionContext)
* @see #fromVertices(Collection, boolean, DoublePrecisionContext)
* @see Plane#fromPoints(Collection, DoublePrecisionContext)
*/
public static ConvexSubPlane fromVertexLoop(final Collection<Vector3D> pts,
final DoublePrecisionContext precision) {
return fromVertices(pts, true, precision);
}
/** Create a new instance from the given sequence of points. The points must define a unique plane, meaning that
* at least 3 unique vertices must be given.
* @param pts collection of points defining the convex subplane
* @param precision precision context used to compare floating point values
* @return a new instance defined by the given sequence of vertices
* @throws IllegalArgumentException if fewer than 3 vertices are given
* @throws org.apache.commons.geometry.core.exception.GeometryException if the vertices do not define a
* unique plane
* @see #fromVertexLoop(Collection, DoublePrecisionContext)
* @see #fromVertices(Collection, boolean, DoublePrecisionContext)
* @see Plane#fromPoints(Collection, DoublePrecisionContext)
*/
public static ConvexSubPlane fromVertices(final Collection<Vector3D> pts,
final DoublePrecisionContext precision) {
return fromVertices(pts, false, precision);
}
/** Create a new instance from the given sequence of points. The points must define a unique plane, meaning that
* at least 3 unique vertices must be given. If {@code close} is true, the vertices are made into a closed loop
* by including the start point at the end if needed.
* @param pts collection of points
* @param close if true, the point sequence will implicitly include the start point again at the end; otherwise
* the vertex sequence is taken as-is
* @param precision precision context used to compare floating point values
* @return a new convex subplane instance
* @see #fromVertexLoop(Collection, DoublePrecisionContext)
* @see #fromVertices(Collection, DoublePrecisionContext)
* @see Plane#fromPoints(Collection, DoublePrecisionContext)
*/
public static ConvexSubPlane fromVertices(final Collection<Vector3D> pts, final boolean close,
final DoublePrecisionContext precision) {
final Plane plane = Plane.fromPoints(pts, precision);
final List<Vector2D> subspacePts = plane.toSubspace(pts);
final ConvexArea area = ConvexArea.fromVertices(subspacePts, close, precision);
return new ConvexSubPlane(plane, area);
}
}