Conclusion and outlook
A.1 Python source code
A.1.7 APOLLO configuration process
4 """ The process is part of the explosive ordnance disposal workflow 5 and returns APOLLO configuration data for SIRIUS interface.
6 """
7 8 # libs
9 importlogging 10 importtempfile 11 importjson
12 frompywpsimportProcess, LiteralInput, ComplexInput, ComplexOutput, Format 13 frompywps.app.CommonimportMetadata
14 frompywps.validator.modeimportMODE 15 frompywps.validatorimportcomplexvalidator
16 frompywps.validator.allowed_valueimportRANGECLOSURETYPE, ALLOWEDVALUETYPE 17 frompywps.inout.literaltypesimportAllowedValue
18 fromeasydictimportEasyDict 19 fromosgeoimportogr 20 fromlibimportgeolib 21
22 # authorship information 23 __author__ ="Gunnar Ströer"
24 __copyright__ ="Copyright 2019, integration of wps in local sdi"
25 __version__ ="1.0"
26 __maintainer__ ="Gunnar Ströer"
27 __email__ ="gunnar.stroeer@yahoo.de"
34 # process returns APOLLO configuration data for SIRIUS interface 35 classApolloConf(Process):
36 # static class variables
37 epsg = 25832 # local spatial reference code 38 epsg2 = 4326 # spatial reference code for WGS84
39 srv_url ='https://www.cadfem.de/apollo/' # url provided by the SIRIUS project team 40
48 # validation mode unable to use due incompatibilities between mimetype library and QGIS wps client
49 mode=MODE.NONE
55 abstract='Precision used by APOLLO simulation. Supported values are: 0.5, 1.0, 2.5, 5.0, 10.0',
56 data_type='float',
57 allowed_values=(0.5, 1.0, 2.5, 5.0, 10.0)
58 )
69 'Exact TNT Blast Power [kg]',
70 data_type='integer',
71 # spacing unable to use due incompatibilities between QGIS wps client 72 # allowed_values=(range(50, 2000+1, 50)),
73 allowed_values=[AllowedValue(minval=1, maxval=5000, # spacing=50,
74 allowed_type=ALLOWEDVALUETYPE.RANGE,
75 range_closure=RANGECLOSURETYPE.OPEN)]
76 )
77
78 in_heading = LiteralInput(
79 'in_heading',
80 'Bomb Azimuth Angle [deg]',
81 data_type='float',
88 'Bomb Tilt Angle [deg]',
89 data_type='float',
97 abstract='Type of the bomb after classification. Supported values are: N/A, GP100, GP250',
98 data_type='string',
106 abstract='Position of detonator after classification. Supported values are: N/A, Front, Rear, Top, Bottom',
107 data_type='string',
108 allowed_values=('N/A','Front','Rear','Top','Bottom'),
109 min_occurs=0
115 abstract='Description of the bomb find location. Supported values are: Surface, Cavern',
116 data_type='string',
131 'Hidden Objects [gml:id1 gml:id2]',
132 abstract='List of 3D city model objects that will be ignored by the simulation. '
133 'Supported values are GML identificationstrings.',
134 data_type='string',
145
146 inputs = [in_geom, in_precision, in_height, in_tnt, in_heading, in_pitch, 147 in_type, in_detonator, in_site_desc, in_site_rad, in_hidden]
148
156 abstract='The process returns APOLLO configuration data for SIRIUS interface.', 157 metadata=[Metadata('The process is part of the explosive ordnance disposal workflow '
158 'and returns APOLLO configuration data for SIRIUS interface.',
159 'http://geodev:8080/geonetwork/srv/ger/catalog.search?service=CSW&version=2.0.2'
168 # handler method obtains request object and response object 169 # @staticmethod # only for static methods, no 'self' applicable 170 def_handler(self, request, response):
171 # obtain input with identifier as file name 172 in_file = request.inputs['in_geom'][0].file 173
174 # possible request attributes: 'abstract', 'as_reference', 'base64', 'clone', 'crs', 'crss', 'data', 175 # 'describe_xml', 'dimensions', 'execute_xml', 'file', 'get_base64', 'get_data', 'get_file',
176 # 'get_memory_object', 'get_stream', 'get_workdir', 'identifier', 'json', 'll', 'max_occurs', 'memory_object', 177 # 'metadata', 'min_occurs', 'set_base64', 'set_data', 'set_file', 'set_memory_object', 'set_stream', 178 # 'set_workdir', 'source', 'source_type', 'stream', 'title', 'ur', 'valid_mode', 'validator', 'workdir' 179
180 # default parameter values
181 bomb_type, detonator, site_desc, hidden ='','','',''
182 precision, height, tnt, heading, pitch, site_rad = 0., 0., 0, 0., 0., 2.
183
184 # check and obtain input with identifier as data directly 185 if'in_precision'inrequest.inputs:
186 precision = request.inputs['in_precision'][0].data 187 if'in_height'inrequest.inputs:
188 height = request.inputs['in_height'][0].data 189 if'in_tnt'inrequest.inputs:
190 tnt = request.inputs['in_tnt'][0].data 191 if'in_heading'inrequest.inputs:
192 heading = request.inputs['in_heading'][0].data 193 if'in_pitch'inrequest.inputs:
194 pitch = request.inputs['in_pitch'][0].data 195 if'in_type'inrequest.inputs:
196 bomb_type = request.inputs['in_type'][0].data 197 if'in_detonator'inrequest.inputs:
198 detonator = request.inputs['in_detonator'][0].data 199 if'in_site_desc'inrequest.inputs:
200 site_desc = request.inputs['in_site_desc'][0].data 201 if'in_site_rad'inrequest.inputs:
202 site_rad = request.inputs['in_site_rad'][0].data 203 if'in_hidden'inrequest.inputs:
204 hidden = (request.inputs['in_hidden'][0].data).split() 205
206 # open file and layer 207 in_src = ogr.Open(in_file) 208 in_lyr = in_src.GetLayer() 209
210 # only one single input feature and valid tnt blast power 211 ifin_lyr.GetFeatureCount() == 1andtnt > 0:
212 # conservative calculation for float glass
213 dist_threshold = geolib.damage_dist_threshold(tnt, 0) 214
215 LOGGER.debug('Threshold:'+str(dist_threshold)) 216
217 # get the feature geometry 218 in_feat = in_lyr.GetNextFeature() 219 in_geom = in_feat.GetGeometryRef() 220
221 # get SRID of geometry and make sure location is a point
222 epsg0 =int(in_geom.GetSpatialReference().GetAttrValue('AUTHORITY', 1)) 223 x0, y0 = in_geom.Centroid().GetX(), in_geom.Centroid().GetY() 224
225 # harmonization of spatial reference
226 ifepsg0 != self.epsg:
227 # transform position to local spatial reference 228 x2, y2 = geolib.geo_transform(x0, y0, epsg0, self.epsg)
229 else:
230 x2, y2 = x0, y0
231
232 # calculate bounding box
233 bbx1 = x2 - dist_threshold
234 bby1 = y2 - dist_threshold
235 bbx2 = x2 + dist_threshold
236 bby2 = y2 + dist_threshold
237
238 # transform position to WGS84
239 x_wgs, y_wgs = geolib.geo_transform(x2, y2, self.epsg, self.epsg2) 240
241 LOGGER.debug('Coordinates in '+str(self.epsg) +':'+str(x2) +'/'+str(y2)) 242 LOGGER.debug('Coordinates in '+str(self.epsg2) +':'+str(x_wgs) +'/'+str(y_wgs)) 243
244 # create location geometry
245 location = ogr.Geometry(ogr.wkbPoint)
246 location.AddPoint(x2, y2)
247
248 LOGGER.debug('Location as WKT:'+ location.ExportToWkt()) 249
250 # create output data
251 conf_data = EasyDict({'bomb': {'tnt': tnt,'type': bomb_type,'detonator': detonator},
252 'domain': {'name':'Ultimo','zroi': 100,'droi': dist_threshold},
253 'mode': {'name':'Ultimo','t': 50,'precision': precision},
254 'site': {'type': site_desc,'radius': site_rad},
255 'geometry': {'crs': self.epsg2,'position': [x_wgs, y_wgs],'depth': (-1) * height},
256 'crs': self.epsg,
257 'position': [x2, y2],
258 'height': height,
259 'heading': heading,
260 'pitch': pitch,
261 'extent': [bbx1, bby1, bbx2, bby2],
262 'hiddenObjects': hidden,
263 'service': {'url': self.srv_url,'resultFile':'effects_'+str(self.uuid) +'.zip'}
264 })
265
266 conf_json = json.dumps(conf_data) 267
268 # create file, w: write in text mode
269 conf_path = tempfile.mkstemp(prefix='conf_', suffix='.json')[1]
270 withopen(conf_path,'w') as fp:
271 fp.write(conf_json)
272 fp.close()
273
274 # set output format and file name
275 response.outputs['out_conf'].output_format = Format(mime_type='application/json', extension='.json',
276 validate=complexvalidator.validategeojson,
277 encoding='UTF-8', schema='json')
278 response.outputs['out_conf'].file= conf_path
279 else:
280 # remove output from response
281 delresponse.outputs['out_conf']
282
283 LOGGER.debug('Only one single input feature allowed. '+ 284 str(in_lyr.GetFeatureCount()) +' detected!') 285
286 # free and reassign
287 in_src = None
288 in_lyr = None
289
290 # possible response attributes: 'abstract', 'as_reference', 'base64', 'crs', 'crss', 'data', 'describe_xml', 291 # 'dimensions', 'execute_xml', 'file', 'get_base64', 'get_data', 'get_file', 'get_memory_object', 'get_stream', 292 # 'get_workdir', 'identifier', 'json', 'll', 'max_occurs', 'memory_object', 'metadata', 'min_occurs', 293 # 'set_base64', 'set_data', 'set_file', 'set_memory_object', 'set_stream', 'set_workdir', 'source', 294 # 'source_type', 'stream', 'title', 'ur', 'valid_mode', 'validator', 'workdir'
295
296 returnresponse
Listing A.7: APOLLO configuration process