/*
* 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.math.geometry.euclidean.twod;
import java.util.List;
import org.apache.commons.math.geometry.euclidean.oned.Euclidean1D;
import org.apache.commons.math.geometry.euclidean.oned.Interval;
import org.apache.commons.math.geometry.euclidean.oned.IntervalsSet;
import org.apache.commons.math.geometry.euclidean.oned.Vector1D;
import org.apache.commons.math.geometry.partitioning.AbstractSubHyperplane;
import org.apache.commons.math.geometry.partitioning.BSPTree;
import org.apache.commons.math.geometry.partitioning.BSPTreeVisitor;
import org.apache.commons.math.geometry.partitioning.BoundaryAttribute;
import org.apache.commons.math.geometry.partitioning.SubHyperplane;
import org.apache.commons.math.geometry.partitioning.utilities.AVLTree;
/** Visitor building segments.
* @version $Id: SegmentBuilder.java 1131229 2011-06-03 20:49:25Z luc $
* @since 3.0
*/
class SegmentsBuilder implements BSPTreeVisitor<Euclidean2D> {
/** Sorted segments. */
private AVLTree<Segment> sorted;
/** Simple constructor. */
public SegmentsBuilder() {
sorted = new AVLTree<Segment>();
}
/** {@inheritDoc} */
public Order visitOrder(final BSPTree<Euclidean2D> node) {
return Order.MINUS_SUB_PLUS;
}
/** {@inheritDoc} */
public void visitInternalNode(final BSPTree<Euclidean2D> node) {
@SuppressWarnings("unchecked")
final BoundaryAttribute<Euclidean2D> attribute = (BoundaryAttribute<Euclidean2D>) node.getAttribute();
if (attribute.getPlusOutside() != null) {
addContribution(attribute.getPlusOutside(), false);
}
if (attribute.getPlusInside() != null) {
addContribution(attribute.getPlusInside(), true);
}
}
/** {@inheritDoc} */
public void visitLeafNode(final BSPTree<Euclidean2D> node) {
}
/** Add he contribution of a boundary facet.
* @param sub boundary facet
* @param reversed if true, the facet has the inside on its plus side
*/
private void addContribution(final SubHyperplane<Euclidean2D> sub, final boolean reversed) {
@SuppressWarnings("unchecked")
final AbstractSubHyperplane<Euclidean2D, Euclidean1D> absSub =
(AbstractSubHyperplane<Euclidean2D, Euclidean1D>) sub;
final Line line = (Line) sub.getHyperplane();
final List<Interval> intervals = ((IntervalsSet) absSub.getRemainingRegion()).asList();
for (final Interval i : intervals) {
final Vector2D start = Double.isInfinite(i.getLower()) ?
null : (Vector2D) line.toSpace(new Vector1D(i.getLower()));
final Vector2D end = Double.isInfinite(i.getUpper()) ?
null : (Vector2D) line.toSpace(new Vector1D(i.getUpper()));
if (reversed) {
sorted.insert(new Segment(end, start, line.getReverse()));
} else {
sorted.insert(new Segment(start, end, line));
}
}
}
/** Get the sorted segments.
* @return sorted segments
*/
public AVLTree<Segment> getSorted() {
return sorted;
}
}