org.kalypso.ogc.gml.map.widgets.builders.PolygonGeometryBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.kalypso.ogc.gml.map.widgets.builders.PolygonGeometryBuilder.java

Source

/*----------------    FILE HEADER KALYPSO ------------------------------------------
 *
 *  This file is part of kalypso.
 *  Copyright (C) 2004 by:
 *
 *  Technical University Hamburg-Harburg (TUHH)
 *  Institute of River and coastal engineering
 *  Denickestrae 22
 *  21073 Hamburg, Germany
 *  http://www.tuhh.de/wb
 *
 *  and
 *
 *  Bjoernsen Consulting Engineers (BCE)
 *  Maria Trost 3
 *  56070 Koblenz, Germany
 *  http://www.bjoernsen.de
 *
 *  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
 *
 *  Contact:
 *
 *  E-Mail:
 *  belger@bjoernsen.de
 *  schlienger@bjoernsen.de
 *  v.doemming@tuhh.de
 *
 *  ---------------------------------------------------------------------------*/
package org.kalypso.ogc.gml.map.widgets.builders;

import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.ArrayUtils;
import org.kalypso.transformation.transformer.GeoTransformerFactory;
import org.kalypso.transformation.transformer.IGeoTransformer;
import org.kalypsodeegree.graphics.transformation.GeoTransform;
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_Position;
import org.kalypsodeegree_impl.model.geometry.GeometryFactory;

/**
 * This class is a geometry builder for a polygon.
 * 
 * @author Holger Albert
 */
public class PolygonGeometryBuilder implements IGeometryBuilder {
    /**
     * Stores the count of points which this geometry must have. If it is 0, there is no rule.
     */
    private int m_cnt_points;

    private final List<GM_Point> m_points = new ArrayList<>();

    private final String m_crs;

    private GM_Object m_result;

    private final ToolTipRenderer m_renderer;

    final java.awt.Cursor CROSSHAIR_CURSOR = java.awt.Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);

    final java.awt.Cursor DEFAULT_CURSOR = java.awt.Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);

    private final IGeometryBuilderExtensionProvider m_extender;

    private final boolean m_updateCursor;

    /**
     * The constructor.
     * 
     * @param cnt_points
     *          If > 2 the the geometry will be finished, if the count of points is reached. If <= 2 no rule regarding the
     *          count of the points will apply, except, that a polygon needs at least 3 points for beeing created.
     * @param targetCrs
     *          The target coordinate system.
     */
    public PolygonGeometryBuilder(final int cnt_points, final String targetCrs,
            final IGeometryBuilderExtensionProvider extender) {
        this(cnt_points, targetCrs, extender, true);
    }

    /**
     * The constructor.
     * 
     * @param cnt_points
     *          If > 2 the the geometry will be finished, if the count of points is reached. If <= 2 no rule regarding the
     *          count of the points will apply, except, that a polygon needs at least 3 points for beeing created.
     * @param targetCrs
     *          The target coordinate system.
     */
    public PolygonGeometryBuilder(final int cnt_points, final String targetCrs) {
        this(cnt_points, targetCrs, null);
    }

    public PolygonGeometryBuilder(final int cnt_points, final String targetCrs,
            final IGeometryBuilderExtensionProvider extender, final boolean updateCursor) {
        m_extender = extender;
        m_updateCursor = updateCursor;
        m_cnt_points = 0;

        if (cnt_points > 2)
            m_cnt_points = cnt_points;

        m_crs = targetCrs;

        m_renderer = new ToolTipRenderer(m_extender);

        if (m_extender != null && m_updateCursor)
            m_extender.setCursor(CROSSHAIR_CURSOR);
    }

    /**
     * @see org.kalypso.ogc.gml.map.widgets.builders.IGeometryBuilder#addPoint(org.kalypsodeegree.model.geometry.GM_Point)
     */
    @Override
    public GM_Object addPoint(final GM_Point p) throws Exception {
        m_points.add(p);

        if (m_points.size() > 2 && m_points.size() == m_cnt_points)
            return finish();

        return null;
    }

    /**
     * This function creates the geometry (GM_Surface).
     */
    private GM_Object createGeometry(final GM_Position[] poses) throws GM_Exception {
        final GM_Position[] pos = new GM_Position[poses.length + 1];

        for (int i = 0; i < poses.length; i++)
            pos[i] = (GM_Position) poses[i].clone();

        pos[poses.length] = (GM_Position) poses[0].clone();

        return GeometryFactory.createGM_Surface(pos, new GM_Position[0][0], m_crs);
    }

    private void drawHandles(final Graphics g, final int[] x, final int[] y) {
        for (int i = 0; i < y.length; i++)
            drawHandle(g, x[i], y[i]);
    }

    // TODO: move to central place. Should used by all widgets / all geometry builders
    public static void drawHandle(final Graphics g, final int x, final int y) {
        final int sizeOuter = 6;
        g.drawRect(x - sizeOuter / 2, y - sizeOuter / 2, sizeOuter, sizeOuter);
    }

    /**
     * @see org.kalypso.ogc.gml.map.widgets.builders.IGeometryBuilder#finish()
     */
    @Override
    public GM_Object finish() throws Exception {
        if (m_extender != null && m_updateCursor)
            m_extender.setCursor(DEFAULT_CURSOR);

        if (m_result != null)
            return m_result;

        if (m_points.size() > 2 && (m_cnt_points == m_points.size() || m_cnt_points <= 2)) {
            final IGeoTransformer transformer = GeoTransformerFactory.getGeoTransformer(m_crs);

            final GM_Position[] poses = new GM_Position[m_points.size()];
            for (int i = 0; i < poses.length; i++) {
                final GM_Point transformedPoint = (GM_Point) transformer.transform(m_points.get(i));
                poses[i] = transformedPoint.getPosition();
            }

            return createGeometry(poses);
        }

        return null;
    }

    private int[][] getPointArrays(final GeoTransform projection, final Point currentPoint) {
        final List<Integer> xArray = new ArrayList<>();
        final List<Integer> yArray = new ArrayList<>();

        for (int i = 0; i < m_points.size(); i++) {
            final GM_Point point = m_points.get(i);

            final int x = (int) projection.getDestX(point.getX());
            final int y = (int) projection.getDestY(point.getY());

            xArray.add(new Integer(x));
            yArray.add(new Integer(y));
        }

        if (currentPoint != null) {
            xArray.add(currentPoint.x);
            yArray.add(currentPoint.y);
        }

        final int[] xs = ArrayUtils.toPrimitive(xArray.toArray(new Integer[xArray.size()]));
        final int[] ys = ArrayUtils.toPrimitive(yArray.toArray(new Integer[yArray.size()]));

        return new int[][] { xs, ys };
    }

    @Override
    public void paint(final Graphics g, final GeoTransform projection, final Point currentPoint) {
        // IMPORTANT: we remember GM_Points (not Point's) and retransform them for painting
        // because the projection depends on the current map-extent, so this builder
        // is stable in regard to zoom in/out
        if (!m_points.isEmpty()) {
            final int[][] points = getPointArrays(projection, currentPoint);

            final int[] arrayX = points[0];
            final int[] arrayY = points[1];

            /* Paint a polygon. */
            g.drawPolygon(arrayX, arrayY, arrayX.length);
            drawHandles(g, arrayX, arrayY);
        }

        m_renderer.paint(g);
    }

    @Override
    public void removeLastPoint() {
        if (m_points.size() > 0)
            m_points.remove(m_points.size() - 1);
    }

    @Override
    public void reset() {
        m_points.clear();
        m_result = null;
        if (m_extender != null && m_updateCursor)
            m_extender.setCursor(CROSSHAIR_CURSOR);
    }

    public int size() {
        return m_points.size();
    }

    /**
     * This function returns the minimum number of points, as given in the constructor.
     * 
     * @return The number of points, at which the geometry should be finished. <= 2 if no rule will be used.
     */
    public int getCntPoints() {
        return m_cnt_points;
    }

    public int getPointCount() {
        return m_points.size();
    }
}