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

com.github.tsingjyujing.geo.basic.IGeoPointSet.scala Maven / Gradle / Ivy

package com.github.tsingjyujing.geo.basic

import com.github.tsingjyujing.geo.basic.operations.GeoJSONable
import com.github.tsingjyujing.geo.element.immutable.Vector2

import scala.util.parsing.json.JSONObject

/**
  * A point set to query points easily
  *
  * @tparam T Type to save geo points, any type extends IGeoPoint
  */
trait IGeoPointSet[T <: IGeoPoint] extends Iterable[T] with GeoJSONable {

    override def toGeoJSON: JSONObject = GeoJSONable.createMultiPoint(getPoints)

    /**
      * Add point to set
      *
      * @param point point value
      */
    def appendPoint(point: T): Unit

    def appendPoints(points: TraversableOnce[T]): Unit = points.foreach(appendPoint)

    /**
      * Query all points in set
      *
      * @return
      */
    def getPoints: Iterable[T]

    override def iterator: Iterator[T] = getPoints.iterator

    /**
      * Search the points nearest to point input in radius as max distance
      *
      * @param point       center point
      * @param maxDistance max radius to search
      * @return
      */
    def geoNear(point: IGeoPoint, maxDistance: Double = 1.0): Option[T]

    /**
      * Find points in ring
      *
      * @param point       center point
      * @param minDistance ring inside radius
      * @param maxDistance ring outside radius
      * @return
      */
    def geoWithinRing(point: IGeoPoint, minDistance: Double = 0.0, maxDistance: Double = 1.0): Iterable[T]

    /**
      * Search all points in radius of maxDistance
      *
      * @param point       center point
      * @param maxDistance max radius
      * @return
      */
    def geoWithin(point: IGeoPoint, maxDistance: Double = 1.0): Iterable[T] = geoWithinRing(point, -1, maxDistance)

    /**
      * Get geo distance of nearest point in set
      *
      * @param points
      * @param searchRadius
      * @return
      */
    def geoFrechet(points: TraversableOnce[IGeoPoint], searchRadius: Double = 0.5): TraversableOnce[Double] = {
        points.map(p => {
            val searchResult = geoNear(p, searchRadius)
            if (searchResult.isDefined) {
                searchResult.get.geoTo(p)
            } else {
                IGeoPoint.EARTH_RADIUS * math.Pi
            }
        })
    }

    /**
      * Get similarity of the route and set
      *
      * @param points
      * @param searchRadius
      * @return
      */
    def geoFrechetSimilarity(points: Iterable[IGeoPoint], searchRadius: Double = 0.5): Double = {
        val staticValue = points.map(point => {
            (point, geoNear(point, searchRadius).isDefined)
        }).sliding(2).map(pointSlide2 => {
            val ds = pointSlide2.head._1.geoTo(pointSlide2.last._1)
            Vector2(if (pointSlide2.forall(_._2)) {
                ds
            } else {
                0.0
            }, ds)
        }).reduce(_ + _)
        staticValue.getX / staticValue.getY
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy