Package org.catais.veriso.utils

Source Code of org.catais.veriso.utils.Iox2wkt

package org.catais.veriso.utils;

import org.apache.log4j.Logger;

import ch.interlis.iom.IomConstants;
import ch.interlis.iom.IomObject;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.CoordinateList;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineSegment;
import com.vividsolutions.jts.geom.PrecisionModel;
import com.vividsolutions.jts.precision.SimpleGeometryPrecisionReducer;

/**
* Methoden zur Umwandlung von Iom-Objekten nach JTS-Geometrien.
*
* @author Stefan Ziegler
* @version 0.1
*/

public class Iox2wkt {
    private static Logger logger = Logger.getLogger(Iox2wkt.class);

    private static final CoordinateList coords = new CoordinateList();

    private static PrecisionModel pm = new PrecisionModel(1000);
    private static SimpleGeometryPrecisionReducer pr = new SimpleGeometryPrecisionReducer(
            pm);

    public Iox2wkt() {

    }

    /**
     * Wandelt ein IOM Polylineobjekt in eine JTS-Geometrie um. Kreisbögen
     * werden segmentiert. Durch die Angabe des korrekten maxOverlap wird
     * vermieden, dass Zentroidpunkte ausserhalb des Polygons zu liegen kommt.
     * Dabei wird aus dem maxOverlap resp. der maximalen Pfeilhöhe der
     * Segmentierungswinkel berechnet.
     *
     * @param polylineObj
     *            IOM Polylineobjekt
     * @param maxOverlaps
     *            maximal erlaubter Overlap
     * @return JTS Linestring
     */

    public static Geometry polyline2jts(IomObject polylineObj,
            double maxOverlaps) {

        coords.clear();

        boolean clipped = polylineObj.getobjectconsistency() == IomConstants.IOM_INCOMPLETE;
        for (int sequencei = 0; sequencei < polylineObj
                .getattrvaluecount("sequence"); sequencei++) {
            if (!clipped && sequencei > 0) {
                throw new IllegalArgumentException();
            }

            IomObject sequence = polylineObj.getattrobj("sequence", sequencei);
            for (int segmenti = 0; segmenti < sequence
                    .getattrvaluecount("segment"); segmenti++) {
                IomObject segment = sequence.getattrobj("segment", segmenti);
                if (segment.getobjecttag().equals("COORD")) {

                    String c1 = segment.getattrvalue("C1");
                    String c2 = segment.getattrvalue("C2");
                    // String c3=segment.getattrvalue("C3");

                    Coordinate coord = new Coordinate(Double.valueOf(c1),
                            Double.valueOf(c2));
                    coords.add(coord, false);

                } else if (segment.getobjecttag().equals("ARC")) {
                    String a1 = segment.getattrvalue("A1");
                    String a2 = segment.getattrvalue("A2");
                    String c1 = segment.getattrvalue("C1");
                    String c2 = segment.getattrvalue("C2");
                    // String c3=segment.getattrvalue("C3");

                    Coordinate ptStart = coords
                            .getCoordinate(coords.size() - 1);
                    Coordinate ptArc = new Coordinate(Double.valueOf(a1),
                            Double.valueOf(a2));
                    Coordinate ptEnd = new Coordinate(Double.valueOf(c1),
                            Double.valueOf(c2));

                    // logger.debug(ptStart.toString() + " " + ptArc.toString()
                    // + " " + ptEnd.toString());
                    interpolateArc(ptStart, ptArc, ptEnd, maxOverlaps);

                } else {
                    // custom line form is not supported
                }
            }
        }

        Geometry line = null;
        // Bei 3D-Koordinaten ergäbe das eben schon noch Sinn....
        try {
            line = new GeometryFactory().createLineString(coords
                    .toCoordinateArray());
        } catch (IllegalArgumentException e) {
            // e.printStackTrace();
            System.err.println("not valid linestring");
        }

        return line;
    }

    /**
     * Segmentiert ein Kreisbogenelement. Durch die Angabe des korrekten
     * maxOverlap wird vermieden, dass Zentroidpunkte ausserhalb des Polygons zu
     * liegen kommt. Dabei wird aus dem maxOverlap resp. der maximalen Pfeilhöhe
     * der Segmentierungswinkel berechnet.
     *
     * @param ptStart
     *            Bogenanfang
     * @param ptArc
     *            Bogenpunkt
     * @param ptEnd
     *            Bogenende
     * @param maxOverlaps
     *            maximal erlaubter Overlap
     */
    private static void interpolateArc(Coordinate ptStart, Coordinate ptArc,
            Coordinate ptEnd, double maxOverlaps) {

        double arcIncr = 1;
        if (maxOverlaps < 0.00001) {
            maxOverlaps = 0.002;
        }

        // TEMPORARY:
        maxOverlaps = 0.002;
        // maxOverlaps = 0.0001;

        LineSegment segment = new LineSegment(ptStart, ptEnd);
        double dist = segment.distancePerpendicular(ptArc);
        // logger.debug( "perpendicular distance: " + dist);

        // Abbruchkriterium Handgelenkt mal Pi...
        // (für ganz flache Kreisbogen).
        if (dist < maxOverlaps) {
            coords.add(ptEnd, false);
            return;
        }

        Coordinate center = getArcCenter(ptStart, ptArc, ptEnd);
        // logger.debug("arc center: " + center.toString());

        double cx = center.x;
        double cy = center.y;
        double px = ptArc.x;
        double py = ptArc.y;
        double r = Math.sqrt((cx - px) * (cx - px) + (cy - py) * (cy - py));

        double myAlpha = 2.0 * Math.acos(1.0 - maxOverlaps / r);

        if (myAlpha < arcIncr) {
            arcIncr = myAlpha;
        }

        double a1 = Math.atan2(ptStart.y - center.y, ptStart.x - center.x);
        double a2 = Math.atan2(ptArc.y - center.y, ptArc.x - center.x);
        double a3 = Math.atan2(ptEnd.y - center.y, ptEnd.x - center.x);

        double sweep;

        // Clockwise
        if (a1 > a2 && a2 > a3) {
            sweep = a3 - a1;
        }
        // Counter-clockwise
        else if (a1 < a2 && a2 < a3) {
            sweep = a3 - a1;
        }
        // Clockwise, wrap
        else if ((a1 < a2 && a1 > a3) || (a2 < a3 && a1 > a3)) {
            sweep = a3 - a1 + 2 * Math.PI;
        }
        // Counter-clockwise, wrap
        else if ((a1 > a2 && a1 < a3) || (a2 > a3 && a1 < a3)) {
            sweep = a3 - a1 - 2 * Math.PI;
        } else {
            sweep = 0.0;
        }

        double ptcount = Math.ceil(Math.abs(sweep / arcIncr));

        if (sweep < 0)
            arcIncr *= -1.0;

        double angle = a1;

        for (int i = 0; i < ptcount - 1; i++) {
            angle += arcIncr;

            if (arcIncr > 0.0 && angle > Math.PI)
                angle -= 2 * Math.PI;
            if (arcIncr < 0.0 && angle < -1 * Math.PI)
                angle -= 2 * Math.PI;

            double x = cx + r * Math.cos(angle);
            double y = cy + r * Math.sin(angle);

            Coordinate coord = new Coordinate(x, y);
            coords.add(coord, false);

            if ((angle < a2) && ((angle + arcIncr) > a2)) {
                coords.add(ptArc, false);
            }
            if ((angle > a2) && ((angle + arcIncr) < a2)) {
                coords.add(ptArc, false);
            }
        }
        coords.add(ptEnd, false);
    }

    /**
     * Berechnet Kreisbogenzentrum.
     *
     * @param ptStart
     *            Bogenanfang
     * @param ptArc
     *            Bogenpunkt
     * @param ptEnd
     *            Bogenende
     * @return Kreisbogenzentrum
     */
    private static Coordinate getArcCenter(Coordinate ptStart,
            Coordinate ptArc, Coordinate ptEnd) {
        double bx = ptStart.x;
        double by = ptStart.y;
        double cx = ptArc.x;
        double cy = ptArc.y;
        double dx = ptEnd.x;
        double dy = ptEnd.y;
        double temp, bc, cd, det, x, y;

        temp = cx * cx + cy * cy;
        bc = (bx * bx + by * by - temp) / 2.0;
        cd = (temp - dx * dx - dy * dy) / 2.0;
        det = (bx - cx) * (cy - dy) - (cx - dx) * (by - cy);

        det = 1 / det;

        x = (bc * (cy - dy) - cd * (by - cy)) * det;
        y = ((bx - cx) * cd - (cx - dx) * bc) * det;

        return new Coordinate(x, y);
    }

    /**
     * Wandelt ein IOM-Punktelement in ein WKT-String um.
     *
     * @param pointObj
     *            IOM-Punktelement
     * @return WKT-Punktgeometrie
     */
    public static String point2wkt(IomObject pointObj) {
        String point_wkt = null;

        String c1 = pointObj.getattrvalue("C1");
        String c2 = pointObj.getattrvalue("C2");

        point_wkt = "POINT(" + c1 + " " + c2 + ")";

        return point_wkt;
    }

    /**
     * Wandelt ein IOM-Polylineobjekt in ein WKT-String um. Kreisbogen werden
     * unterstützt.
     *
     * @param polylineObj
     *            IOM-Polylineobjekt
     * @return WKT-Linestring oder WKT-Compoundcurve
     */
    public static String polyline2wkt(IomObject polylineObj) {

        String polyline_wkt = null;

        boolean clipped = polylineObj.getobjectconsistency() == IomConstants.IOM_INCOMPLETE;
        for (int sequencei = 0; sequencei < polylineObj
                .getattrvaluecount("sequence"); sequencei++) {
            if (!clipped && sequencei > 0) {
                throw new IllegalArgumentException();
            }
            Boolean curved = false;
            Boolean curves = false;
            StringBuffer line = new StringBuffer("(");
            String c1_tmp = null;
            String c2_tmp = null;

            IomObject sequence = polylineObj.getattrobj("sequence", sequencei);
            for (int segmenti = 0; segmenti < sequence
                    .getattrvaluecount("segment"); segmenti++) {
                IomObject segment = sequence.getattrobj("segment", segmenti);
                if (segment.getobjecttag().equals("COORD")) {

                    if (curved) {
                        line.append(",(");
                        line.append(c1_tmp + " " + c2_tmp);
                        line.append(",");
                        curved = false;
                    }

                    String c1 = segment.getattrvalue("C1");
                    String c2 = segment.getattrvalue("C2");
                    String c3 = segment.getattrvalue("C3");

                    line.append(c1 + " " + c2);
                    line.append(",");

                    c1_tmp = c1;
                    c2_tmp = c2;

                } else if (segment.getobjecttag().equals("ARC")) {

                    // Falls ein Circuarstring vorangegangen ist,
                    // muss noch ein Komma gesetzt werden.
                    if (curved) {
                        line.append(",");
                    }

                    // Liniensegment abschliessen, aber nur
                    // falls kein Circularstring vorangegangen
                    // ist.
                    if (segmenti != 0 && curved == false) {
                        line.deleteCharAt(line.length() - 1);
                        line.append("),");
                    }

                    // Flags für Kreisbogen setzen
                    curved = true;
                    curves = true;

                    String c1 = segment.getattrvalue("C1");
                    String c2 = segment.getattrvalue("C2");
                    String c3 = segment.getattrvalue("C3");
                    String a1 = segment.getattrvalue("A1");
                    String a2 = segment.getattrvalue("A2");

                    String curve = "CIRCULARSTRING(" + c1_tmp + " " + c2_tmp
                            + "," + a1 + " " + a2 + "," + c1 + " " + c2 + ")";

                    line.append(curve);

                    c1_tmp = c1;
                    c2_tmp = c2;

                } else {
                    // custom line form
                }

                // Falls keine Kreisbögen muss das
                // Liniensegment hier geschlossen werden.
                if (segmenti == (sequence.getattrvaluecount("segment") - 1)
                        && segmenti != 0) {
                    line.deleteCharAt(line.length() - 1);
                    line.append(")");
                }
            }
            // Falls keine Kreisbögen vorhanden sind,
            // gehts als Linestring durch, sonst
            // als Compoundcurve.
            if (curves) {
                line.insert(0, "COMPOUNDCURVE(");
                line.append(")");
            } else {
                line.insert(0, "LINESTRING");
                line.append("");
            }

            polyline_wkt = line.toString();

        }
        return polyline_wkt;
    }

}
TOP

Related Classes of org.catais.veriso.utils.Iox2wkt

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.