All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.graphhopper.util.gpx.GpxFromInstructions Maven / Gradle / Ivy

There is a newer version: 9.1
Show newest version
/*
 *  Licensed to GraphHopper GmbH under one or more contributor
 *  license agreements. See the NOTICE file distributed with this work for
 *  additional information regarding copyright ownership.
 *
 *  GraphHopper GmbH 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 com.graphhopper.util.gpx;

import com.graphhopper.util.*;
import com.graphhopper.util.shapes.GHPoint3D;

import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class GpxFromInstructions {

    static String simpleXMLEscape(String str) {
        // We could even use the 'more flexible' CDATA section but for now do the following. The 'and' could be important sometimes:
        return str.replaceAll("&", "&").
                // but do not care for:
                        replaceAll("[\\<\\>]", "_");
    }

    public static List createGPXList(InstructionList instructions) {
        List gpxList = new ArrayList<>();
        long timeOffset = 0;
        for (Instruction instruction : instructions) {
            int i = 0;
            for (GHPoint3D point : instruction.getPoints()) {
                GPXEntry gpxEntry;
                if (i == 0) {
                    gpxEntry = new GPXEntry(point, timeOffset);
                } else {
                    // We don't have timestamps for pillar nodes
                    gpxEntry = new GPXEntry(point);
                }
                gpxList.add(gpxEntry);
                i++;
            }
            timeOffset = timeOffset + instruction.getTime();
        }
        return gpxList;
    }

    private static void createWayPointBlock(StringBuilder output, Instruction instruction, DecimalFormat decimalFormat, Translation tr) {
        output.append("\n");
        String name;
        if (instruction.getName().isEmpty())
            name = instruction.getTurnDescription(tr);
        else
            name = instruction.getName();

        output.append(" ").append(simpleXMLEscape(name)).append("");
        output.append("");
    }

    public static String createGPX(InstructionList instructions, String trackName, long startTimeMillis, boolean includeElevation, boolean withRoute, boolean withTrack, boolean withWayPoints, String version, Translation tr) {
        DateFormat formatter = Helper.createFormatter();

        DecimalFormat decimalFormat = new DecimalFormat("#", DecimalFormatSymbols.getInstance(Locale.ROOT));
        decimalFormat.setMinimumFractionDigits(1);
        decimalFormat.setMaximumFractionDigits(6);
        decimalFormat.setMinimumIntegerDigits(1);

        String header = ""
                + ""
                + "\n"
                + ""
                + ""
                + "GraphHopper GPX"
                + ""
                + ""
                + "";
        StringBuilder gpxOutput = new StringBuilder(header);
        if (!instructions.isEmpty()) {
            if (withWayPoints) {
                createWayPointBlock(gpxOutput, instructions.get(0), decimalFormat, tr);   // Start
                for (Instruction currInstr : instructions) {
                    if ((currInstr.getSign() == Instruction.REACHED_VIA) // Via
                            || (currInstr.getSign() == Instruction.FINISH)) // End
                    {
                        createWayPointBlock(gpxOutput, currInstr, decimalFormat, tr);
                    }
                }
            }
            if (withRoute) {
                gpxOutput.append("\n");
                Instruction nextInstr = null;
                for (Instruction currInstr : instructions) {
                    if (null != nextInstr)
                        createRteptBlock(gpxOutput, nextInstr, currInstr, decimalFormat, tr);

                    nextInstr = currInstr;
                }
                createRteptBlock(gpxOutput, nextInstr, null, decimalFormat, tr);
                gpxOutput.append("\n");
            }
        }
        if (withTrack) {
            gpxOutput.append("\n").append(trackName).append("");

            gpxOutput.append("");
            for (GPXEntry entry : createGPXList(instructions)) {
                gpxOutput.append("\n");
                if (includeElevation)
                    gpxOutput.append("").append(Helper.round2(((GHPoint3D) entry.getPoint()).getEle())).append("");
                if (entry.getTime() != null)
                    gpxOutput.append("");
                gpxOutput.append("");
            }
            gpxOutput.append("\n");
            gpxOutput.append("\n");
        }

        // we could now use 'wpt' for via points
        gpxOutput.append("\n");
        return gpxOutput.toString();
    }

    private static void createRteptBlock(StringBuilder output, Instruction instruction, Instruction nextI, DecimalFormat decimalFormat, Translation tr) {
        output.append("\n");

        if (!instruction.getName().isEmpty())
            output.append("").append(simpleXMLEscape(instruction.getTurnDescription(tr))).append("");

        output.append("");
        output.append("").append(Helper.round(instruction.getDistance(), 1)).append("");
        output.append("").append(instruction.getTime()).append("");

        String direction = instruction.calcDirection(nextI);
        if (!direction.isEmpty())
            output.append("").append(direction).append("");

        double azimuth = instruction.calcAzimuth(nextI);
        if (!Double.isNaN(azimuth))
            output.append("").append(Helper.round2(azimuth)).append("");

        if (instruction instanceof RoundaboutInstruction) {
            RoundaboutInstruction ri = (RoundaboutInstruction) instruction;

            output.append("").append(ri.getExitNumber()).append("");
        }

        output.append("").append(instruction.getSign()).append("");
        output.append("");
        output.append("");
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy