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.geometry.euclidean.threed.line; 018 019import java.util.ArrayList; 020import java.util.List; 021 022import org.apache.commons.geometry.core.Transform; 023import org.apache.commons.geometry.euclidean.oned.Interval; 024import org.apache.commons.geometry.euclidean.oned.RegionBSPTree1D; 025import org.apache.commons.geometry.euclidean.oned.Vector1D; 026import org.apache.commons.geometry.euclidean.threed.Bounds3D; 027import org.apache.commons.geometry.euclidean.threed.Vector3D; 028import org.apache.commons.geometry.euclidean.threed.line.Line3D.SubspaceTransform; 029 030/** Class representing an arbitrary subset of a line in 3D Euclidean space using a 031 * {@link RegionBSPTree1D}. This class can represent convex, non-convex, finite, 032 * infinite, and empty regions. 033 * 034 * <p>This class is mutable and <em>not</em> thread safe.</p> 035 */ 036public final class EmbeddedTreeLineSubset3D extends LineSubset3D { 037 /** The 1D region representing the area on the line. */ 038 private final RegionBSPTree1D region; 039 040 /** Construct a new, empty subset for the given line. 041 * @param line line defining the subset 042 */ 043 public EmbeddedTreeLineSubset3D(final Line3D line) { 044 this(line, false); 045 } 046 047 /** Construct a new subset for the given line. If {@code full} 048 * is true, then the subset will cover the entire line; otherwise, 049 * it will be empty. 050 * @param line line defining the subset 051 * @param full if true, the subset will cover the entire space; 052 * otherwise it will be empty 053 */ 054 public EmbeddedTreeLineSubset3D(final Line3D line, final boolean full) { 055 this(line, new RegionBSPTree1D(full)); 056 } 057 058 /** Construct a new instance from its defining line and subspace region. 059 * @param line line defining the subset 060 * @param region subspace region for the subset 061 */ 062 public EmbeddedTreeLineSubset3D(final Line3D line, final RegionBSPTree1D region) { 063 super(line); 064 065 this.region = region; 066 } 067 068 /** {@inheritDoc} */ 069 @Override 070 public double getSize() { 071 return region.getSize(); 072 } 073 074 /** {@inheritDoc} */ 075 @Override 076 public RegionBSPTree1D getSubspaceRegion() { 077 return region; 078 } 079 080 /** {@inheritDoc} */ 081 @Override 082 public Vector3D getCentroid() { 083 final Vector1D subcenter = region.getCentroid(); 084 return subcenter != null ? 085 getLine().toSpace(subcenter) : 086 null; 087 } 088 089 /** {@inheritDoc} */ 090 @Override 091 public Bounds3D getBounds() { 092 final double min = region.getMin(); 093 final double max = region.getMax(); 094 095 if (Double.isFinite(min) && Double.isFinite(max)) { 096 final Line3D line = getLine(); 097 098 return Bounds3D.builder() 099 .add(line.toSpace(min)) 100 .add(line.toSpace(max)) 101 .build(); 102 } 103 104 return null; 105 } 106 107 /** Transform this instance. 108 * @param transform the transform to apply 109 * @return a new, transformed instance 110 */ 111 public EmbeddedTreeLineSubset3D transform(final Transform<Vector3D> transform) { 112 final SubspaceTransform st = getLine().subspaceTransform(transform); 113 114 final RegionBSPTree1D tRegion = RegionBSPTree1D.empty(); 115 tRegion.copy(region); 116 tRegion.transform(st.getTransform()); 117 118 return new EmbeddedTreeLineSubset3D(st.getLine(), tRegion); 119 } 120 121 /** Return a list of {@link LineConvexSubset3D} instances representing the same region 122 * as this instance. 123 * @return a list of {@link LineConvexSubset3D} instances representing the same region 124 * as this instance. 125 */ 126 public List<LineConvexSubset3D> toConvex() { 127 final List<Interval> intervals = region.toIntervals(); 128 129 final Line3D line = getLine(); 130 final List<LineConvexSubset3D> convex = new ArrayList<>(intervals.size()); 131 132 for (final Interval interval : intervals) { 133 convex.add(Lines3D.subsetFromInterval(line, interval)); 134 } 135 136 return convex; 137 } 138 139 /** {@inheritDoc} */ 140 @Override 141 public String toString() { 142 final Line3D line = getLine(); 143 144 final StringBuilder sb = new StringBuilder(); 145 sb.append(this.getClass().getSimpleName()) 146 .append('[') 147 .append("lineOrigin= ") 148 .append(line.getOrigin()) 149 .append(", lineDirection= ") 150 .append(line.getDirection()) 151 .append(", region= ") 152 .append(region) 153 .append(']'); 154 155 return sb.toString(); 156 } 157}