org.kalypsodeegree_impl.model.geometry.GM_TriangulatedSurface_Impl.java Source code

Java tutorial

Introduction

Here is the source code for org.kalypsodeegree_impl.model.geometry.GM_TriangulatedSurface_Impl.java

Source

/** This file is part of kalypso/deegree.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * history:
 *
 * Files in this package are originally taken from deegree and modified here
 * to fit in kalypso. As goals of kalypso differ from that one in deegree
 * interface-compatibility to deegree is wanted but not retained always.
 *
 * If you intend to use this software in other ways than in kalypso
 * (e.g. OGC-web services), you should consider the latest version of deegree,
 * see http://www.deegree.org .
 *
 * all modifications are licensed as deegree,
 * original copyright:
 *
 * Copyright (C) 2001 by:
 * EXSE, Department of Geography, University of Bonn
 * http://www.giub.uni-bonn.de/exse/
 * lat/lon GmbH
 * http://www.lat-lon.de
 */
package org.kalypsodeegree_impl.model.geometry;

import gnu.trove.TIntProcedure;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.Range;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.kalypso.jts.JTSUtilities;
import org.kalypso.transformation.transformer.GeoTransformerException;
import org.kalypsodeegree.model.elevation.ElevationException;
import org.kalypsodeegree.model.geometry.GM_Envelope;
import org.kalypsodeegree.model.geometry.GM_Exception;
import org.kalypsodeegree.model.geometry.GM_Object;
import org.kalypsodeegree.model.geometry.GM_Point;
import org.kalypsodeegree.model.geometry.GM_PolyhedralSurface;
import org.kalypsodeegree.model.geometry.GM_Position;
import org.kalypsodeegree.model.geometry.GM_Triangle;
import org.kalypsodeegree.model.geometry.GM_TriangulatedSurface;
import org.kalypsodeegree.model.geometry.MinMaxSurfacePatchVisitor;

import com.infomatiq.jsi.Rectangle;

/**
 * @author Gernot Belger
 */
final class GM_TriangulatedSurface_Impl extends GM_PolyhedralSurface_Impl<GM_Triangle>
        implements GM_TriangulatedSurface {
    private GM_Triangle m_lastHit = null;

    private final boolean m_hasStatistics = false;

    private Range<BigDecimal> m_minMax;

    public GM_TriangulatedSurface_Impl(final String crs) throws GM_Exception {
        this(new ArrayList<GM_Triangle>(), crs);
    }

    public GM_TriangulatedSurface_Impl(final List<GM_Triangle> items, final String crs) throws GM_Exception {
        super(items, crs);
    }

    @Override
    public void dispose() {
        // nothing to do...
    }

    @Override
    protected GM_PolyhedralSurface<GM_Triangle> createCloneInstance() throws GM_Exception {
        return new GM_TriangulatedSurface_Impl(getCoordinateSystem());
    }

    @Override
    public Object getAdapter(final Class adapter) {
        if (adapter == GM_Triangle[].class) {
            return toArray(new GM_Triangle[size()]);
        }
        return super.getAdapter(adapter);
    }

    @Override
    public double getValue(final GM_Point location) {
        try {
            final GM_Point transformedLocation = (GM_Point) location.transform(getCoordinateSystem());
            final GM_Position position = transformedLocation.getPosition();
            return getValue(position);
        } catch (final Exception e) {
            e.printStackTrace();
            return Double.NaN;
        }
    }

    @Override
    public double getValue(final GM_Position position) {
        final GM_Triangle triangle = getTriangle(position);
        if (triangle == null)
            return Double.NaN;

        return triangle.getValue(position);
    }

    @Override
    public GM_Triangle getTriangle(final GM_Position position) {
        // Protect against concurrent access
        final GM_Triangle lastHit = m_lastHit;
        if (lastHit != null) {
            if (lastHit.contains(position))
                return lastHit;
        }

        final Rectangle searchEnv = JTSUtilities.toRectangle(position.getX(), position.getY());

        final GM_Triangle[] result = new GM_Triangle[] { null };

        final TIntProcedure ip = new TIntProcedure() {
            @Override
            public boolean execute(final int value) {
                final GM_Triangle triangle = get(value);
                if (triangle.contains(position)) {
                    result[0] = triangle;
                    return false;
                }

                return true;
            }
        };

        getIndex().intersects(searchEnv, ip);

        m_lastHit = result[0];
        return result[0];
    }

    /**
     * Must override, else the wrong type is created.
     */
    @Override
    public GM_Object transform(final String targetCRS) throws GeoTransformerException {
        try {
            /* If the target is the same coordinate system, do not transform. */
            final String sourceCRS = getCoordinateSystem();
            if (sourceCRS == null || sourceCRS.equalsIgnoreCase(targetCRS))
                return this;

            final int cnt = size();
            final GM_Triangle[] triangles = new GM_Triangle[cnt];
            for (int i = 0; i < cnt; i++)
                triangles[i] = (GM_Triangle) get(i).transform(targetCRS);

            return GeometryFactory.createGM_TriangulatedSurface(triangles, targetCRS);
        } catch (final GM_Exception e) {
            throw new GeoTransformerException(e);
        }
    }

    @Override
    public double getElevation(final GM_Point location) {
        return getValue(location);
    }

    @Override
    public GM_Envelope getBoundingBox() {
        return getEnvelope();
    }

    @Override
    public double getMinElevation() throws ElevationException {
        buildStatistics();
        return m_minMax.getMinimum().doubleValue();
    }

    @Override
    public double getMaxElevation() throws ElevationException {
        buildStatistics();
        return m_minMax.getMaximum().doubleValue();
    }

    private void buildStatistics() throws ElevationException {
        if (m_hasStatistics)
            return;
        final MinMaxSurfacePatchVisitor<GM_Triangle> minMaxVisitor = new MinMaxSurfacePatchVisitor<>();
        final GM_Envelope maxBox = getEnvelope();
        try {
            acceptSurfacePatches(maxBox, minMaxVisitor, new NullProgressMonitor());
        } catch (final CoreException e) {
            throw new ElevationException(e.getStatus().getMessage(), e);
        }

        final BigDecimal min = minMaxVisitor.getMin();
        final BigDecimal max = minMaxVisitor.getMax();

        m_minMax = Range.between(min, max);
    }
}