Ddongyu1009init
cdf6f0e0创建于 2024年9月6日历史提交
/**
  This file is created by Yu Dong (2023).
  License  : Apache 2.0
  FileName : SpatialReference.cj
  Author   : Yu Dong
  Version  : 0.0.1
  Date     : 20230424
  Note     : First Commit
 */

/**
 * @file
 * SpatialReference
 */
package gistools

/**
 * toWKID Interface 
 * @author Yu Dong
 * @since 0.38.2
 */
public interface ToWKID {

    prop wkid : Int64

    func toWKID() : ?Int64
}

/**
 * SpatialReference for common methods 
 * @author Yu Dong
 * @since 0.38.2
 */
public interface SpatialReference <: ToString & ToWKID{

    /**
     * The Property for wkid implementation of toWKID interface
     *
     * @return Type of Int64
     * @since 0.38.2
     */
    prop wkid : Int64 {
        get() {
            match(toWKID()) {
                case Some(v) => v
                case None => 0 
            }
        }
    }

    /**
     * The Operator Function is to determine if the spatialreference is same or not
     *
     * @param right of SpatialReference
     *
     * @return Type of Bool
     * @since 0.38.2
     */
    operator func ==(right: SpatialReference): Bool {
        this.toWKID() == right.toWKID()
    }

    /**
     * The Operator Function is to determine if the spatialreference is not same
     *
     * @param right of SpatialReference
     *
     * @return Type of Bool
     * @since 0.38.2
     */
    operator func !=(right: SpatialReference): Bool {
        this.toWKID() != right.toWKID()
    }

    /**
     * The Function is to determine if the spatial reference is WGS 1984.
     *
     * @return Type of Bool
     * @since 0.38.2
     */
    func isWGS1984() : Bool {
        this.toWKID() == 4326
    }


    /**
     * The Function is to determine if the spatial reference is BD-09.
     *
     * @return Type of Bool
     * @since 0.38.2
     */
    func isBD09() : Bool {
        this.toString() == "BD-09"
    }

    /**
     * The Function is to determine if the spatial reference is GCJ-02.
     *
     * @return Type of Bool
     * @since 0.38.2
     */
    func isGCJ02() : Bool {
        this.toString() == "GCJ-02"
    }

    /**
     * The Function is to determine if the spatial reference is unknown.
     *
     * @return Type of Bool
     * @since 0.38.2
     */
    func isUnknown() : Bool {
        this == GeographicSpatialReference.Unknown || this == ProjectedSpatialReference.Unknown
    }

    /**
     * The Function is to determine if the spatial reference is geographic.
     *
     * @return Type of Bool
     * @since 0.38.2
     */
    func isGeographic() : Bool {
        this is GeographicSpatialReference
    }

    
    /**
     * The Function is to determine if the spatial reference is projected.
     *
     * @return Type of Bool
     * @since 0.38.2
     */
    func isProjected() : Bool {
        this is ProjectedSpatialReference
    }

    /**
     * The Function is create WGS 1984 Spatial Reference
     *
     * @return Type of GeographicSpatialReference
     * @since 0.38.2
     */
    static func wgs84() : GeographicSpatialReference{
        return GeographicSpatialReference.WGS1984
    }


    /**
     * The Function is create GCJ-02 Spatial Reference
     *
     * @return Type of GeographicSpatialReference
     * @since 0.38.2
     */
    static func gcj02() : GeographicSpatialReference{
        GeographicSpatialReference.GCJ02
    }

    /**
     * The Function is create BD-09 Spatial Reference
     *
     * @return Type of GeographicSpatialReference
     * @since 0.38.2
     */
    static func bd09() : GeographicSpatialReference {
        GeographicSpatialReference.BD09
    }

    /**
     * The Function is create Web Mercator Spatial Reference with WGS 1984 Geographic Spatial Reference
     *
     * @return Type of GeographicSpatialReference
     * @since 0.38.2
     */
    static func webMercator() : ProjectedSpatialReference{
        ProjectedSpatialReference.WebMercator(wgs84())
    }

    /**
     * The Function is create Web Mercator Spatial Reference with any Geographic Spatial Reference
     *
     * @param gcj of GeographicSpatialReference
     *
     * @return Type of GeographicSpatialReference
     * @since 0.38.2
     */
    static func webMercator(gcj : GeographicSpatialReference) : ProjectedSpatialReference{
        ProjectedSpatialReference.WebMercator(gcj)
    }

    /**
     * The Function is create Gauss-Kruger Spatial Reference
     *
     * @param zone of Int64
     *
     * @return Type of ProjectedSpatialReference
     * @since 0.38.2
     */
    static func gaussKruger3degreeZoneWithCGCS2000(zone : Int64) : ProjectedSpatialReference{
        if (zone > 45 || zone < 25) {
            return ProjectedSpatialReference.Unknown
        }
        ProjectedSpatialReference.Gauss_Kruger_3_degree_Zone_With_CGCS2000(zone)
    }

    /**
     * The Function is create unknown Spatial Reference
     *
     * @return Type of SpatialReference
     * @since 0.38.2
     */
    static func unknown() : SpatialReference{
        GeographicSpatialReference.Unknown
    }

    /**
     * The Function is create Spatial Reference by WKID
     *
     * @return Type of ?SpatialReference
     * @since 0.38.2
     */
    static func fromWKID(wkid : Int64) : ?SpatialReference {

        if (wkid >= 4513 && wkid <= 4533) {
            return ProjectedSpatialReference.Gauss_Kruger_3_degree_Zone_With_CGCS2000(wkid - 4513 + 25)
        }
        match(wkid) {
            case 4326 => GeographicSpatialReference.WGS1984
            case 4490 => GeographicSpatialReference.CGCS2000
            case 3857 => ProjectedSpatialReference.WebMercator(wgs84())
            case _ => None
        }
    }
}

/**
 * GeographicSpatialReference
 * @author Yu Dong
 * @since 0.38.2
 */
public enum GeographicSpatialReference <: SpatialReference {
    | WGS1984   // WGS-1984
    | GCJ02     // GVJ-02
    | BD09      // BD-09
    | CGCS2000  // CGCS-2000
    | Unknown   // Unknown


    /**
     * The Function is to String
     *
     * @return Type of String
     * @since 0.38.2
     */
    public func toString() : String {
        
        match(this) {
            case WGS1984 => "WGS 1984"
            case GCJ02 => "GCJ-02"
            case BD09 => "BD-09"
            case CGCS2000 => "CGCS 2000"
            case _ => "Unknown"
        }
    }

    /**
     * The Function is to WKID
     *
     * @return Type of ?Int64 
     * @since 0.38.2
     */
    public func toWKID() : ?Int64 {
        
        match(this) {
            case WGS1984 => 4326
            case GCJ02 => None
            case BD09 => None
            case CGCS2000 => 4490
            case _ => None
        }
    }
}

/**
 * ProjectedSpatialReference
 * @author Yu Dong
 * @since 0.38.2
 */
public enum ProjectedSpatialReference <: SpatialReference {
    // WebMercator
    | WebMercator(GeographicSpatialReference)
    // Gauss_ ruger 3 degree Zone With CGCS2000
    | Gauss_Kruger_3_degree_Zone_With_CGCS2000(Int64)
    // Unknown
    | Unknown


    /**
     * The Function is to String
     *
     * @return Type of String
     * @since 0.38.2
     */
    public func toString() : String {
        match(this) {
            case WebMercator(gsr) => "Web Mercator whih ${gsr}"
            case Gauss_Kruger_3_degree_Zone_With_CGCS2000(zone) => "CGCS2000 / 3-degree Gauss-Kruger zone ${zone}"
            case _ => "Unknown"
        }
    }

    /**
     * The Function is to WKID
     *
     * @return Type of ?Int64 
     * @since 0.38.2
     */
    public func toWKID() : ?Int64 {
        match(this) {
            case WebMercator(gsr) => if (gsr.toWKID() == 4326) { 3857 } else { None }
            case Gauss_Kruger_3_degree_Zone_With_CGCS2000(zone) => if (zone >= 25 && zone <= 45) { zone - 25 + 4513 } else { None }
            case _ => None
        }
    }

}