195 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			195 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/env seiscomp-python
 | 
						|
# -*- coding: utf-8 -*-
 | 
						|
 | 
						|
############################################################################
 | 
						|
# Copyright (C) gempa GmbH                                                 #
 | 
						|
# All rights reserved.                                                     #
 | 
						|
# Contact: gempa GmbH (seiscomp-dev@gempa.de)                              #
 | 
						|
#                                                                          #
 | 
						|
# GNU Affero General Public License Usage                                  #
 | 
						|
# This file may be used under the terms of the GNU Affero                  #
 | 
						|
# Public License version 3.0 as published by the Free Software Foundation  #
 | 
						|
# and appearing in the file LICENSE included in the packaging of this      #
 | 
						|
# file. Please review the following information to ensure the GNU Affero   #
 | 
						|
# Public License version 3.0 requirements will be met:                     #
 | 
						|
# https://www.gnu.org/licenses/agpl-3.0.html.                              #
 | 
						|
#                                                                          #
 | 
						|
# Other Usage                                                              #
 | 
						|
# Alternatively, this file may be used in accordance with the terms and    #
 | 
						|
# conditions contained in a signed written agreement between you and       #
 | 
						|
# gempa GmbH.                                                              #
 | 
						|
############################################################################
 | 
						|
 | 
						|
 | 
						|
import datetime
 | 
						|
import getopt
 | 
						|
import sys
 | 
						|
 | 
						|
from typing import TextIO
 | 
						|
 | 
						|
from seiscomp import geo
 | 
						|
 | 
						|
 | 
						|
# -----------------------------------------------------------------------------
 | 
						|
def printHelp():
 | 
						|
    msg = """
 | 
						|
gfs2fep - converts a SeisComP GeoFeatureSet file (GeoJSON or BNA) to FEP format
 | 
						|
 | 
						|
usage: {} [OPTIONS]
 | 
						|
 | 
						|
    -h, --help
 | 
						|
        print this help message
 | 
						|
 | 
						|
    -i, --input
 | 
						|
        input file (default: -)
 | 
						|
 | 
						|
    -o, --output
 | 
						|
        output fep file (default: -)
 | 
						|
 | 
						|
    -a, --append
 | 
						|
        append fep data to output file instead of overriding it
 | 
						|
 | 
						|
    -p, --precision (default: unrestricted)
 | 
						|
        number of decimal places of coordintes"""
 | 
						|
    print(msg.format(sys.argv[0]), file=sys.stderr)
 | 
						|
    sys.exit(0)
 | 
						|
 | 
						|
 | 
						|
# -----------------------------------------------------------------------------
 | 
						|
def error(code, msg):
 | 
						|
    print(f"error ({code}): {msg}", file=sys.stderr)
 | 
						|
    sys.exit(code)
 | 
						|
 | 
						|
 | 
						|
# -----------------------------------------------------------------------------
 | 
						|
def run():
 | 
						|
    if len(sys.argv) == 1:
 | 
						|
        printHelp()
 | 
						|
 | 
						|
    inFile = "-"
 | 
						|
    outFile = None
 | 
						|
    append = False
 | 
						|
    precision = None
 | 
						|
    opts, _ = getopt.getopt(
 | 
						|
        sys.argv[1:], "hi:o:ap:", ["help", "input=", "output=", "append", "precision"]
 | 
						|
    )
 | 
						|
    for o, a in opts:
 | 
						|
        if o in ("-h", "--help"):
 | 
						|
            printHelp()
 | 
						|
 | 
						|
        if o in ("-i", "--input"):
 | 
						|
            inFile = a
 | 
						|
 | 
						|
        if o in ("-o", "--output"):
 | 
						|
            outFile = a
 | 
						|
 | 
						|
        if o in ("-a", "--append"):
 | 
						|
            append = True
 | 
						|
 | 
						|
        if o in ("-p", "--precision"):
 | 
						|
            precision = max(int(a), 0)
 | 
						|
 | 
						|
    gfs = geo.GeoFeatureSet()
 | 
						|
    if not gfs.readFile(inFile, None):
 | 
						|
        error(1, f"Could not read from file '{inFile}'")
 | 
						|
 | 
						|
    # combine features sharing the same name
 | 
						|
    featureDict = {}
 | 
						|
    for f in gfs.features():
 | 
						|
        if not f.closedPolygon():
 | 
						|
            print(
 | 
						|
                f"warning: feature not a closed polygon: {f.name()}",
 | 
						|
                file=sys.stderr,
 | 
						|
            )
 | 
						|
        if f.name() in featureDict:
 | 
						|
            featureDict[f.name()].append(f)
 | 
						|
        else:
 | 
						|
            featureDict[f.name()] = [f]
 | 
						|
 | 
						|
    # output is set to stdout or a file name if specified
 | 
						|
    if outFile and outFile != "-":
 | 
						|
        try:
 | 
						|
            with open(outFile, "a" if append else "w", encoding="utf8") as fp:
 | 
						|
                writeFEPFile(featureDict, inFile, fp, precision)
 | 
						|
        except Exception as e:
 | 
						|
            error(2, e)
 | 
						|
 | 
						|
    else:
 | 
						|
        writeFEPFile(featureDict, inFile, sys.stdout, precision)
 | 
						|
        sys.stdout.flush()
 | 
						|
 | 
						|
 | 
						|
# -----------------------------------------------------------------------------
 | 
						|
def writeFEPFile(featureDict: dict, inFile: str, fp: TextIO, precision: int = None):
 | 
						|
    def _print(data: str):
 | 
						|
        print(data, file=fp)
 | 
						|
 | 
						|
    if precision:
 | 
						|
 | 
						|
        def _printVertex(v):
 | 
						|
            print(
 | 
						|
                f"{v.longitude():.{precision}f} {v.latitude():.{precision}f}", file=fp
 | 
						|
            )
 | 
						|
 | 
						|
    else:
 | 
						|
 | 
						|
        def _printVertex(v):
 | 
						|
            print(f"{v.longitude()} {v.latitude()}", file=fp)
 | 
						|
 | 
						|
    _print(f"# created from file: {inFile}")
 | 
						|
    _print(
 | 
						|
        f"# created on {str(datetime.datetime.now())} by gfs2fep.py - (C) gempa GmbH"
 | 
						|
    )
 | 
						|
    _print("# LON LAT")
 | 
						|
 | 
						|
    # write fep
 | 
						|
    for name, features in featureDict.items():
 | 
						|
        # print("{}: {}".format(len(features), name))
 | 
						|
        vCount = 0
 | 
						|
        fStart = features[0].vertices()[0]
 | 
						|
        v = fStart
 | 
						|
 | 
						|
        # iterate over features sharing name
 | 
						|
        for f in features:
 | 
						|
            # vertex array contains vertices of main land and sub features
 | 
						|
            vertices = f.vertices()
 | 
						|
 | 
						|
            # sub feature array holds indices of starting points
 | 
						|
            endIndices = list(f.subFeatures()) + [len(vertices)]
 | 
						|
 | 
						|
            # iterate of main land and sub features
 | 
						|
            i = 0
 | 
						|
            for iEnd in endIndices:
 | 
						|
                vStart = vertices[i]
 | 
						|
                while i < iEnd:
 | 
						|
                    v = vertices[i]
 | 
						|
                    _printVertex(v)
 | 
						|
                    vCount += 1
 | 
						|
                    i += 1
 | 
						|
 | 
						|
                # end sub feature on sub feature start
 | 
						|
                v = vStart
 | 
						|
                _printVertex(v)
 | 
						|
                vCount += 1
 | 
						|
 | 
						|
                # go back to start of main land
 | 
						|
                if v != vertices[0]:
 | 
						|
                    v = vertices[0]
 | 
						|
                    _printVertex(v)
 | 
						|
                    vCount += 1
 | 
						|
 | 
						|
            # go back to start of first feature
 | 
						|
            if v != fStart:
 | 
						|
                v = fStart
 | 
						|
                _printVertex(v)
 | 
						|
                vCount += 1
 | 
						|
 | 
						|
        # end fep region
 | 
						|
        _print(f"99.0 99.0 {vCount}")
 | 
						|
        _print(f"L  {name}")
 | 
						|
 | 
						|
 | 
						|
# -----------------------------------------------------------------------------
 | 
						|
if __name__ == "__main__":
 | 
						|
    run()
 |