001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.math3.geometry.euclidean.threed; 018 019import org.apache.commons.math3.geometry.Point; 020import org.apache.commons.math3.geometry.euclidean.oned.Euclidean1D; 021import org.apache.commons.math3.geometry.euclidean.oned.Vector1D; 022import org.apache.commons.math3.geometry.euclidean.twod.Euclidean2D; 023import org.apache.commons.math3.geometry.euclidean.twod.PolygonsSet; 024import org.apache.commons.math3.geometry.euclidean.twod.Vector2D; 025import org.apache.commons.math3.geometry.partitioning.AbstractSubHyperplane; 026import org.apache.commons.math3.geometry.partitioning.BSPTree; 027import org.apache.commons.math3.geometry.partitioning.Hyperplane; 028import org.apache.commons.math3.geometry.partitioning.Region; 029import org.apache.commons.math3.geometry.partitioning.SubHyperplane; 030 031/** This class represents a sub-hyperplane for {@link Plane}. 032 * @since 3.0 033 */ 034public class SubPlane extends AbstractSubHyperplane<Euclidean3D, Euclidean2D> { 035 036 /** Simple constructor. 037 * @param hyperplane underlying hyperplane 038 * @param remainingRegion remaining region of the hyperplane 039 */ 040 public SubPlane(final Hyperplane<Euclidean3D> hyperplane, 041 final Region<Euclidean2D> remainingRegion) { 042 super(hyperplane, remainingRegion); 043 } 044 045 /** {@inheritDoc} */ 046 @Override 047 protected AbstractSubHyperplane<Euclidean3D, Euclidean2D> buildNew(final Hyperplane<Euclidean3D> hyperplane, 048 final Region<Euclidean2D> remainingRegion) { 049 return new SubPlane(hyperplane, remainingRegion); 050 } 051 052 /** Split the instance in two parts by an hyperplane. 053 * @param hyperplane splitting hyperplane 054 * @return an object containing both the part of the instance 055 * on the plus side of the instance and the part of the 056 * instance on the minus side of the instance 057 */ 058 @Override 059 public SplitSubHyperplane<Euclidean3D> split(Hyperplane<Euclidean3D> hyperplane) { 060 061 final Plane otherPlane = (Plane) hyperplane; 062 final Plane thisPlane = (Plane) getHyperplane(); 063 final Line inter = otherPlane.intersection(thisPlane); 064 final double tolerance = thisPlane.getTolerance(); 065 066 if (inter == null) { 067 // the hyperplanes are parallel 068 final double global = otherPlane.getOffset(thisPlane); 069 if (global < -tolerance) { 070 return new SplitSubHyperplane<Euclidean3D>(null, this); 071 } else if (global > tolerance) { 072 return new SplitSubHyperplane<Euclidean3D>(this, null); 073 } else { 074 return new SplitSubHyperplane<Euclidean3D>(null, null); 075 } 076 } 077 078 // the hyperplanes do intersect 079 Vector2D p = thisPlane.toSubSpace((Point<Euclidean3D>) inter.toSpace((Point<Euclidean1D>) Vector1D.ZERO)); 080 Vector2D q = thisPlane.toSubSpace((Point<Euclidean3D>) inter.toSpace((Point<Euclidean1D>) Vector1D.ONE)); 081 Vector3D crossP = Vector3D.crossProduct(inter.getDirection(), thisPlane.getNormal()); 082 if (crossP.dotProduct(otherPlane.getNormal()) < 0) { 083 final Vector2D tmp = p; 084 p = q; 085 q = tmp; 086 } 087 final SubHyperplane<Euclidean2D> l2DMinus = 088 new org.apache.commons.math3.geometry.euclidean.twod.Line(p, q, tolerance).wholeHyperplane(); 089 final SubHyperplane<Euclidean2D> l2DPlus = 090 new org.apache.commons.math3.geometry.euclidean.twod.Line(q, p, tolerance).wholeHyperplane(); 091 092 final BSPTree<Euclidean2D> splitTree = getRemainingRegion().getTree(false).split(l2DMinus); 093 final BSPTree<Euclidean2D> plusTree = getRemainingRegion().isEmpty(splitTree.getPlus()) ? 094 new BSPTree<Euclidean2D>(Boolean.FALSE) : 095 new BSPTree<Euclidean2D>(l2DPlus, new BSPTree<Euclidean2D>(Boolean.FALSE), 096 splitTree.getPlus(), null); 097 098 final BSPTree<Euclidean2D> minusTree = getRemainingRegion().isEmpty(splitTree.getMinus()) ? 099 new BSPTree<Euclidean2D>(Boolean.FALSE) : 100 new BSPTree<Euclidean2D>(l2DMinus, new BSPTree<Euclidean2D>(Boolean.FALSE), 101 splitTree.getMinus(), null); 102 103 return new SplitSubHyperplane<Euclidean3D>(new SubPlane(thisPlane.copySelf(), new PolygonsSet(plusTree, tolerance)), 104 new SubPlane(thisPlane.copySelf(), new PolygonsSet(minusTree, tolerance))); 105 106 } 107 108}