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

com.github.tsingjyujing.geo.basic.operations.GeoJSONable.scala Maven / Gradle / Ivy

There is a newer version: 2.8.9-2.11
Show newest version
package com.github.tsingjyujing.geo.basic.operations

import com.github.tsingjyujing.geo.basic.IGeoPoint
import com.github.tsingjyujing.geo.element.GeoPolygon
import com.github.tsingjyujing.geo.element.immutable.GeoPoint
import com.github.tsingjyujing.geo.model.{GeoJsonPoint, GeoJsonPolygon}
import com.google.gson.Gson

import scala.util.parsing.json._

/**
  * Object which can convert to GeoJSON, for more details, see:
  * http://geojson.org/
  */
trait GeoJSONable {

    /**
      * Get scala original JSON object,
      * JSON object deprecated in Scala 2.12 but still using in 2.10
      *
      * @return
      */
    def toGeoJSON: JSONObject

    def toGeoJSONString: String = toGeoJSON.toString()

}

/**
  * Common utils of generating GeoJSON object
  */
object GeoJSONable {

    private val gson: Gson = new Gson()

    private def JSONSeq[T](elems: T*): JSONArray = JSONArray(List(elems: _*))

    private def JSONList[T](elems: TraversableOnce[T]): JSONArray = JSONArray(elems.toList)

    private def JSONMap[V](elems: (String, V)*): JSONObject = JSONObject(elems.toMap)

    /**
      * Create Point GeoJSON object
      * Point
      *
      * @param point which can get longitude and latitude
      * @return
      */
    def createPoint(point: IGeoPoint): JSONObject = {
        JSONMap(
            "type" -> "Point",
            "coordinates" -> JSONSeq(point.getLongitude, point.getLatitude)
        )
    }

    /**
      * Create MultiPoint GeoJSON object
      * MultiPoint
      *
      * @param points points
      * @return
      */
    def createMultiPoint(points: TraversableOnce[IGeoPoint]): JSONObject = {
        JSONMap(
            "type" -> "MultiPoint",
            "coordinates" -> JSONList(points.map(point => JSONSeq(point.getLongitude, point.getLatitude)))
        )
    }

    /**
      * Create LineString GeoJSON object
      * LineString
      *
      * @param points
      * @return
      */
    def createLineString(points: TraversableOnce[IGeoPoint]): JSONObject = {
        JSONMap(
            "type" -> "LineString",
            "coordinates" -> JSONList(points.map(point => JSONSeq(point.getLongitude, point.getLatitude)))
        )
    }

    /**
      * MultiLineString
      * MultiLineString
      *
      * @param pointsList
      * @return
      */
    def createMultiLineString(pointsList: TraversableOnce[TraversableOnce[IGeoPoint]]): JSONObject = {
        JSONMap(
            "type" -> "MultiLineString",
            "coordinates" -> JSONList(pointsList.map(points => JSONList(points.map(point => JSONSeq(point.getLongitude, point.getLatitude)))))
        )
    }

    /**
      * Standard support of polygon GeoJSON
      * Polygon
      *
      * @param pointsList ring and hole
      * @param autoClose  is auto close the polygon
      * @return
      */
    def createPolygon(pointsList: TraversableOnce[Traversable[IGeoPoint]], autoClose: Boolean = true): JSONObject = {
        JSONMap(
            "type" -> "Polygon",
            "coordinates" -> JSONList(
                pointsList.map(points => {
                    val first = points.head
                    val last = points.last
                    JSONList(
                        {
                            val pointsClosed = if (autoClose && first.geoTo(last) >= 1e-10) {
                                List(points.toSeq: _*) ::: List(first)
                            } else {
                                points
                            }
                            pointsClosed.map(p => {
                                JSONList(Array(p.getLongitude, p.getLatitude))
                            })
                        }
                    )
                })
            )
        )
    }

    /**
      * Simple polygon without hole
      * Polygon
      *
      * @param points    ring
      * @param autoClose is auto close the polygon
      * @return
      */
    def createRingPolygon(points: Traversable[IGeoPoint], autoClose: Boolean = true): JSONObject = createPolygon(List(points), autoClose)

    /**
      * Create GeometryCollection GsonObject
      * GeometryCollection
      *
      * @param objects
      * @return
      */
    def createGeometryCollection(objects: TraversableOnce[JSONObject]): JSONObject = {
        JSONMap(
            "type" -> "GeometryCollection",
            "geometries" -> JSONList(objects)
        )
    }


    /**
      * Generate object from json string "{\"type\":\"Point\","coordinates":[100,20]}"
      *
      * @param json
      * @return
      */
    def parseGeoJSON(json: String): GeoJSONable = {
        val mapDecode = gson.fromJson(json, classOf[java.util.HashMap[String, Object]])
        if (!mapDecode.containsKey("type")) {
            throw new RuntimeException("Not GeoJSON object.")
        }
        mapDecode.get("type") match {
            case "Point" =>
                parseGeoPoint(json)
            case "Polygon" =>
                parseGeoPolygon(json)
            case _ =>
                throw new RuntimeException("Unimplemented/unsupport type.")
        }
    }

    def parseGeoPoint(json: String): GeoPoint = gson.fromJson(json, classOf[GeoJsonPoint]).getPoint

    def parseGeoPolygon(json: String): GeoPolygon = gson.fromJson(json, classOf[GeoJsonPolygon]).getPolygon
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy