地图匹配算法-离散Fréchet距离(弗雷歇算法)Java实现

Posted Hepburn Yang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了地图匹配算法-离散Fréchet距离(弗雷歇算法)Java实现相关的知识,希望对你有一定的参考价值。

详细实现思路可以看论文:
弗雷歇算法文献

下面是java版本的实现

package momenta.hdmap.diffosm.Frechet;

import org.locationtech.jts.geom.Coordinate;

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

public class DiscreteFrechetDistance 

   /**
     * Dynamic programming memory array
     */
    private static double[][] mem;

    private static List<Coordinate> timeSeriesP;
    private static List<Coordinate> timeSeriesQ;

    /**-
     * 计算Frechet距离
     * @param cp
     * @param cq
     * @return
     */
    public static double getDiscreteFrechet(Coordinate[] cp, Coordinate[] cq) 

        timeSeriesP = Arrays.asList(cp);
        timeSeriesQ = Arrays.asList(cq);
        double distance = computeDiscreteFrechet(timeSeriesP, timeSeriesQ);
        // 四舍五入保留两位小数输出结果 (单位米)
        BigDecimal b = new BigDecimal(distance);
        return b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
    


    /**
     * Wrapper that makes a call to computeDFD. Initializes mem array with all
     * -1 values.
     *
     * @param P - the first time series
     * @param Q - the second time series
     * @return The length of the shortest distance that can traverse both time
     * series.
     */
    private static double computeDiscreteFrechet(List<Coordinate> P, List<Coordinate> Q) 

        mem = new double[P.size()][Q.size()];

        // initialize all values to -1
        for (int i = 0; i < mem.length; i++) 
            for (int j = 0; j < mem[i].length; j++) 
                mem[i][j] = -1.0;
            
        

        return computeDFD(P.size() - 1, Q.size() - 1);
    

    /**
     * @param i - the row
     * @param j - the column
     * @return The length of the shortest distance that can traverse both time
     * series.
     */
    private static double computeDFD(int i, int j) 
        // if the value has already been solved
        if (mem[i][j] > -1)
            return mem[i][j];
            // if top left column, just compute the distance
        else if (i == 0 && j == 0)
            mem[i][j] = euclideanDistance(timeSeriesP.get(i), timeSeriesQ.get(j));
            // can either be the actual distance or distance pulled from above
        else if (i > 0 && j == 0)
            mem[i][j] = max(computeDFD(i - 1, 0), euclideanDistance(timeSeriesP.get(i), timeSeriesQ.get(j)));
            // can either be the distance pulled from the left or the actual
            // distance
        else if (i == 0 && j > 0)
            mem[i][j] = max(computeDFD(0, j - 1), euclideanDistance(timeSeriesP.get(i), timeSeriesQ.get(j)));
            // can be the actual distance, or distance from above or from the left
        else if (i > 0 && j > 0) 
            mem[i][j] = max(min(computeDFD(i - 1, j), computeDFD(i - 1, j - 1), computeDFD(i, j - 1)), euclideanDistance(timeSeriesP.get(i), timeSeriesQ.get(j)));
        
        // infinite
        else
            mem[i][j] = Integer.MAX_VALUE;


        // printMemory();
        // return the DFD
        return mem[i][j];
    

    /**
     * Get the max value of all the values.
     *
     * @param values - the values being compared
     * @return The max value of all the values.
     */
    private static double max(double... values) 
        double max = Integer.MIN_VALUE;
        for (double i : values) 
            if (i >= max)
                max = i;
        
        return max;
    

    /**
     * Get the minimum value of all the values.
     *
     * @param values - the values being compared
     * @return The minimum value of all the values.
     */
    private static double min(double... values) 
        double min = Integer.MAX_VALUE;
        for (double i : values) 
            if (i <= min)
                min = i;
        
        return min;
    

    /**
     * Given two points, calculate the Euclidean distance between them, where
     * the Euclidean distance: sum from 1 to n dimensions of ((x - y)^2)^1/2
     *
     * @param i - the first point
     * @param j - the second point
     * @return The total Euclidean distance between two points.
     */
    private static double euclideanDistance(Coordinate i, Coordinate j) 

        double distance = 0;
        distance = i.distance(j) * 100000;
        // System.out.println(i.toString() + "_" + j.toString() + "_dis:" + distance);
        return distance;
    

    /**
     * Test method that prints the 2D dynamic programming array.
     */
    private static void printMemory() 
        System.out.println("\\n\\n memory");
        for (int row = 0; row < mem.length; row++) 
            for (int col = 0; col < mem[row].length; col++) 
                System.out.print(mem[row][col] + "\\t");
            
            System.out.println();
        
    


以上是关于地图匹配算法-离散Fréchet距离(弗雷歇算法)Java实现的主要内容,如果未能解决你的问题,请参考以下文章

GIS tips:基于弗雷歇(Frechet)距离的曲线/形状相似度计算方法(python)

Fréchet Inception Distance(FID)

矩阵匹配及相似度计算

理解 Baeza-Yates Régnier 算法(多字符串匹配,从 Boyer-Moore 扩展)

历年诺贝尔和平奖

删除重音和特殊字符[重复]