Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
lgl
SmartVillages2 Converter
Commits
50016c9e
Commit
50016c9e
authored
Nov 26, 2025
by
Matthias Betz
Browse files
add geolocation extraction service
parent
598378fc
Changes
10
Hide whitespace changes
Inline
Side-by-side
README.md
View file @
50016c9e
...
...
@@ -12,10 +12,14 @@ It can be used behind a reverse-proxy like apache or nginx.
To configure the conversion binary use the start parameter
`-Dconverter.executable=./IfcConvert`
. The converter binaries for linux and
windows are included in this repository. The service requires executable rights for the converter program.
In addition to extract geolocation information from the IFC files a python script is used. The python script requires the package
`ifcopenshell`
to be installed via
`pip install ifcopenshell`
. Python has to be available on the path, the service searches for python as well as python3 executable.
## Packaging
To create a runnable package. This does not package the converter program into the jar. It has to be deployed seperatly.
Alternatively a Dockerfile has been provided
```
mvn package
...
...
dockerfile
View file @
50016c9e
...
...
@@ -13,6 +13,14 @@ COPY IfcConvert /app/IfcConvert
# Ensure it's executable
RUN
chmod
+x /app/IfcConvert
# Install Python and pip
RUN
apt-get update
&&
\
apt-get
install
-y
python3 python3-pip
&&
\
rm
-rf
/var/lib/apt/lists/
*
# Install ifcopenshell Python package
RUN
pip3
install
ifcopenshell
# Expose the port your Spring Boot app runs on
EXPOSE
80
...
...
extract_geolocation.py
0 → 100644
View file @
50016c9e
import
ifcopenshell
import
sys
import
json
import
math
def
extract_geolocation
(
ifc_file
):
model
=
ifcopenshell
.
open
(
ifc_file
)
# data structure for geolocation
data
=
[]
# --- IfcSite ---
sites
=
model
.
by_type
(
"IfcSite"
)
for
site
in
sites
:
georef
=
{
"type"
:
"LoGeoRef20"
}
if
site
.
RefLatitude
and
site
.
RefLongitude
:
lat
=
compound_angle_to_float
(
site
.
RefLatitude
)
lon
=
compound_angle_to_float
(
site
.
RefLongitude
)
georef
[
"lat"
]
=
lat
georef
[
"lon"
]
=
lon
data
.
append
(
georef
)
if
site
.
RefElevation
is
not
None
:
georef
[
"ele"
]
=
site
.
RefElevation
# --- IfcSite.ObjectPlacement ---
if
site
.
ObjectPlacement
is
not
None
:
if
site
.
ObjectPlacement
.
is_a
(
'IfcGridPlacement'
):
pass
elif
site
.
ObjectPlacement
.
is_a
(
'IfcLinearPlacement'
):
pass
elif
site
.
ObjectPlacement
.
is_a
(
'IfcLocalPlacement'
):
relativePlacement
=
site
.
ObjectPlacement
.
RelativePlacement
if
relativePlacement
.
is_a
(
'IfcAxis2Placement3D'
):
if
(
relativePlacement
.
Location
is
not
None
):
georef
=
{
"type"
:
"LoGeoRef30"
}
coords
=
list
(
relativePlacement
.
Location
.
Coordinates
)
if
all
(
v
==
0
for
v
in
coords
):
continue
georef
[
"lon"
]
=
coords
[
0
]
georef
[
"lat"
]
=
coords
[
1
]
georef
[
"ele"
]
=
coords
[
2
]
if
len
(
coords
)
>
2
else
0
data
.
append
(
georef
)
elif
relativePlacement
.
is_a
(
'IfcAxis2Placement2D'
):
georef
=
{
"type"
:
"LoGeoRef30"
}
coords
=
list
(
relativePlacement
.
Location
.
Coordinates
)
if
all
(
v
==
0
for
v
in
coords
):
continue
georef
[
"lon"
]
=
coords
[
0
]
georef
[
"lat"
]
=
coords
[
1
]
georef
[
"ele"
]
=
coords
[
2
]
if
len
(
coords
)
>
2
else
0
data
.
append
(
georef
)
# --- IfcBuilding ---
sites
=
model
.
by_type
(
"IfcBuilding"
)
for
site
in
sites
:
# --- IfcBuilding.ObjectPlacement ---
if
site
.
ObjectPlacement
is
not
None
:
if
site
.
ObjectPlacement
.
is_a
(
'IfcGridPlacement'
):
pass
elif
site
.
ObjectPlacement
.
is_a
(
'IfcLinearPlacement'
):
pass
elif
site
.
ObjectPlacement
.
is_a
(
'IfcLocalPlacement'
):
relativePlacement
=
site
.
ObjectPlacement
.
RelativePlacement
if
relativePlacement
.
is_a
(
'IfcAxis2Placement3D'
):
if
(
relativePlacement
.
Location
is
not
None
):
georef
=
{
"type"
:
"LoGeoRef30"
}
coords
=
list
(
relativePlacement
.
Location
.
Coordinates
)
if
all
(
v
==
0
for
v
in
coords
):
continue
georef
[
"lon"
]
=
coords
[
0
]
georef
[
"lat"
]
=
coords
[
1
]
georef
[
"ele"
]
=
coords
[
2
]
if
len
(
coords
)
>
2
else
0
data
.
append
(
georef
)
elif
relativePlacement
.
is_a
(
'IfcAxis2Placement2D'
):
georef
=
{
"type"
:
"LoGeoRef30"
}
coords
=
list
(
relativePlacement
.
Location
.
Coordinates
)
if
all
(
v
==
0
for
v
in
coords
):
continue
georef
[
"lon"
]
=
coords
[
0
]
georef
[
"lat"
]
=
coords
[
1
]
georef
[
"ele"
]
=
coords
[
2
]
if
len
(
coords
)
>
2
else
0
data
.
append
(
georef
)
# --- IFCPROJECT ---
project
=
model
.
by_type
(
"IfcProject"
)
for
p
in
project
:
repContext
=
p
.
RepresentationContexts
for
rep
in
repContext
:
if
rep
.
is_a
(
"IfcGeometricRepresentationContext"
):
crs
=
rep
.
WorldCoordinateSystem
if
crs
is
None
:
continue
georef
=
{
"type"
:
"LoGeoRef40"
}
if
crs
.
is_a
(
'IfcAxis2Placement3D'
):
if
(
crs
.
Location
is
not
None
):
coords
=
list
(
crs
.
Location
.
Coordinates
)
if
all
(
v
==
0
for
v
in
coords
):
continue
georef
[
"lon"
]
=
coords
[
0
]
georef
[
"lat"
]
=
coords
[
1
]
georef
[
"ele"
]
=
coords
[
2
]
if
len
(
coords
)
>
2
else
0
data
.
append
(
georef
)
elif
crs
.
is_a
(
'IfcAxis2Placement2D'
):
coords
=
list
(
crs
.
Location
.
Coordinates
)
if
all
(
v
==
0
for
v
in
coords
):
continue
georef
[
"lon"
]
=
coords
[
0
]
georef
[
"lat"
]
=
coords
[
1
]
georef
[
"ele"
]
=
coords
[
2
]
if
len
(
coords
)
>
2
else
0
data
.
append
(
georef
)
north
=
rep
.
TrueNorth
if
north
is
not
None
:
vec
=
normalize
(
list
(
north
.
DirectionRatios
))
georef
[
"axisX"
]
=
vec
[
0
]
georef
[
"axisY"
]
=
vec
[
1
]
# --- IfcMapConversion ---
try
:
conversions
=
model
.
by_type
(
"IfcMapConversion"
)
for
conv
in
conversions
:
georef
=
{
"type"
:
"LoGeoRef50"
}
if
conv
.
SourceCRS
.
is_a
(
'IfcGeometricRepresentationContext'
):
# local coordinate system
pass
else
:
pass
georef
[
"targetCRS"
]
=
conv
.
TargetCRS
.
Name
georef
[
"northings"
]
=
conv
.
Northings
georef
[
"eastings"
]
=
conv
.
Eastings
georef
[
"ele"
]
=
conv
.
OrthogonalHeight
if
conv
.
XAxisAbscissa
is
not
None
:
georef
[
"XAxisAbscissa"
]
=
conv
.
XAxisAbscissa
if
conv
.
XAxisOrdinate
is
not
None
:
georef
[
"XAxisOrdinate"
]
=
conv
.
XAxisOrdinate
data
.
append
(
georef
)
except
RuntimeError
:
pass
return
data
def
normalize
(
vec
):
length
=
math
.
sqrt
(
sum
(
c
**
2
for
c
in
vec
))
return
[
c
/
length
for
c
in
vec
]
if
length
!=
0
else
vec
def
compound_angle_to_float
(
angle_list
):
if
not
angle_list
or
len
(
angle_list
)
not
in
(
3
,
4
):
raise
ValueError
(
"Input must be a list of 3 or 4 integers: [d, m, s, (ms)]"
)
d
,
m
,
s
=
angle_list
[:
3
]
ms
=
angle_list
[
3
]
if
len
(
angle_list
)
==
4
else
0
return
d
+
m
/
60.0
+
s
/
3600.0
+
ms
/
3_600_000_000.0
if
__name__
==
"__main__"
:
if
len
(
sys
.
argv
)
<
2
:
print
(
"Usage: python myscript.py <ifcFile>"
)
sys
.
exit
(
1
)
print
(
json
.
dumps
(
extract_geolocation
(
sys
.
argv
[
1
])))
pom.xml
View file @
50016c9e
...
...
@@ -4,7 +4,7 @@
<modelVersion>
4.0.0
</modelVersion>
<groupId>
de.hft.stuttgart
</groupId>
<artifactId>
ifc-converter-server
</artifactId>
<version>
1.1.
0
</version>
<version>
1.1.
1
</version>
<properties>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
</properties>
...
...
@@ -28,6 +28,35 @@
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-actuator
</artifactId>
</dependency>
<dependency>
<groupId>
com.fasterxml.jackson.core
</groupId>
<artifactId>
jackson-databind
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-test
</artifactId>
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
org.junit.jupiter
</groupId>
<artifactId>
junit-jupiter
</artifactId>
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
org.assertj
</groupId>
<artifactId>
assertj-core
</artifactId>
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
org.locationtech.proj4j
</groupId>
<artifactId>
proj4j
</artifactId>
<version>
1.3.0
</version>
</dependency>
<dependency>
<groupId>
org.locationtech.proj4j
</groupId>
<artifactId>
proj4j-epsg
</artifactId>
<version>
1.3.0
</version>
</dependency>
</dependencies>
<build>
...
...
src/main/java/de/hft/stuttgart/lgl/ifc/controller/ConverterEndpoints.java
View file @
50016c9e
...
...
@@ -10,9 +10,10 @@ import java.nio.file.Paths;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.UUID
;
import
java.util.concurrent.CompletableFuture
;
import
java.util.concurrent.ExecutionException
;
import
java.util.concurrent.TimeUnit
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
...
...
@@ -32,19 +33,21 @@ import jakarta.servlet.http.HttpServletRequest;
@CrossOrigin
@RestController
public
class
ConverterEndpoints
{
@Value
(
"${converter.executable}"
)
private
String
converterExecutable
;
private
GeolocationExtractionService
geolocationService
;
@Autowired
public
ConverterEndpoints
()
{
// constructor for injection
public
ConverterEndpoints
(
GeolocationExtractionService
geolocationService
)
{
this
.
geolocationService
=
geolocationService
;
}
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ConverterEndpoints
.
class
);
@PostMapping
(
path
=
"/convert"
,
produces
=
MediaType
.
APPLICATION_OCTET_STREAM_VALUE
)
public
ResponseEntity
<
StreamingResponseBody
>
c
heckAddress
(
@RequestParam
(
"file"
)
MultipartFile
file
,
@PostMapping
(
path
=
"/convert"
,
produces
=
MediaType
.
APPLICATION_OCTET_STREAM_VALUE
)
public
ResponseEntity
<
StreamingResponseBody
>
c
onvertIfc
(
@RequestParam
(
"file"
)
MultipartFile
file
,
HttpServletRequest
request
)
{
logger
.
info
(
"Convert request: {}"
,
file
.
getOriginalFilename
());
...
...
@@ -55,6 +58,9 @@ public class ConverterEndpoints {
try
{
Files
.
createDirectories
(
workFolder
);
Files
.
copy
(
file
.
getInputStream
(),
ifcFile
);
CompletableFuture
<
String
>
geolocation
=
checkGeolocation
(
ifcFile
);
List
<
String
>
commands
=
new
ArrayList
<>();
commands
.
add
(
converterExecutable
);
commands
.
add
(
ifcFile
.
toAbsolutePath
().
toString
());
...
...
@@ -75,33 +81,67 @@ public class ConverterEndpoints {
process
.
waitFor
(
10
,
TimeUnit
.
MINUTES
);
int
exitValue
=
process
.
exitValue
();
logger
.
info
(
"Converter exit code for file {} is {}"
,
file
.
getOriginalFilename
(),
exitValue
);
Files
.
delete
(
ifcFile
);
String
originalFileName
=
file
.
getOriginalFilename
();
if
(
originalFileName
==
null
)
{
originalFileName
=
"converted.ifc"
;
}
String
outputFileName
=
originalFileName
.
substring
(
0
,
originalFileName
.
lastIndexOf
(
'.'
))
+
".glb"
;
return
ResponseEntity
.
ok
().
contentType
(
MediaType
.
parseMediaType
(
"application/octet-stream"
))
.
header
(
HttpHeaders
.
CONTENT_DISPOSITION
,
"attachment; filename=\""
+
outputFileName
+
"\""
)
.
body
(
new
StreamingResponseBody
()
{
@Override
public
void
writeTo
(
OutputStream
outputStream
)
throws
IOException
{
try
{
Files
.
copy
(
output
,
outputStream
);
}
finally
{
Files
.
delete
(
output
);
String
outputFileName
=
output
.
getFileName
().
toString
();
String
geolocationString
=
extractGeolocationString
(
geolocation
);
if
(
geolocationString
==
null
)
{
return
ResponseEntity
.
ok
().
contentType
(
MediaType
.
parseMediaType
(
"application/octet-stream"
))
.
header
(
HttpHeaders
.
CONTENT_DISPOSITION
,
"attachment; filename=\""
+
outputFileName
+
"\""
)
.
body
(
new
StreamingResponseBody
()
{
@Override
public
void
writeTo
(
OutputStream
outputStream
)
throws
IOException
{
try
{
Files
.
copy
(
output
,
outputStream
);
}
finally
{
Files
.
delete
(
output
);
}
}
}
});
}
catch
(
IOException
|
InterruptedException
e
)
{
});
}
else
{
return
ResponseEntity
.
ok
().
contentType
(
MediaType
.
parseMediaType
(
"application/octet-stream"
))
.
header
(
HttpHeaders
.
CONTENT_DISPOSITION
,
"attachment; filename=\""
+
outputFileName
+
"\""
)
.
header
(
"X-geolocation"
,
geolocationString
)
.
header
(
"Access-Control-Expose-Headers"
,
"X-geolocation, Content-Disposition"
)
.
body
(
new
StreamingResponseBody
()
{
@Override
public
void
writeTo
(
OutputStream
outputStream
)
throws
IOException
{
try
{
Files
.
copy
(
output
,
outputStream
);
}
finally
{
Files
.
delete
(
output
);
}
}
});
}
}
catch
(
IOException
|
InterruptedException
|
ExecutionException
e
)
{
logger
.
error
(
"Failed to convert file: {}"
,
file
.
getOriginalFilename
(),
e
);
return
ResponseEntity
.
internalServerError
().
build
();
}
finally
{
try
{
Files
.
delete
(
output
);
Files
.
delete
(
ifcFile
);
}
catch
(
IOException
ex
)
{
}
return
ResponseEntity
.
internalServerError
().
build
();
}
}
private
String
extractGeolocationString
(
CompletableFuture
<
String
>
geolocation
)
throws
InterruptedException
,
ExecutionException
{
try
{
return
geolocation
.
get
();
}
catch
(
Exception
e
)
{
logger
.
info
(
"Failed to extract geolocation"
,
e
);
return
null
;
}
}
private
CompletableFuture
<
String
>
checkGeolocation
(
Path
ifcFile
)
{
return
geolocationService
.
extractGeolocation
(
ifcFile
);
}
}
src/main/java/de/hft/stuttgart/lgl/ifc/controller/GeolocationExtractionService.java
0 → 100644
View file @
50016c9e
package
de.hft.stuttgart.lgl.ifc.controller
;
import
java.io.BufferedReader
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
java.lang.ProcessBuilder.Redirect
;
import
java.nio.file.Path
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Locale
;
import
java.util.concurrent.CompletableFuture
;
import
java.util.concurrent.CompletionException
;
import
org.locationtech.proj4j.BasicCoordinateTransform
;
import
org.locationtech.proj4j.CRSFactory
;
import
org.locationtech.proj4j.CoordinateReferenceSystem
;
import
org.locationtech.proj4j.CoordinateTransform
;
import
org.locationtech.proj4j.ProjCoordinate
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.scheduling.annotation.Async
;
import
org.springframework.stereotype.Service
;
import
com.fasterxml.jackson.core.type.TypeReference
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
de.hft.stuttgart.lgl.ifc.model.Geolocation
;
@Service
public
class
GeolocationExtractionService
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
GeolocationExtractionService
.
class
);
private
static
final
ObjectMapper
mapper
=
new
ObjectMapper
();
private
CRSFactory
crsFactory
=
new
CRSFactory
();
private
CoordinateReferenceSystem
gsk3
=
crsFactory
.
createFromName
(
"EPSG:31467"
);
private
CoordinateReferenceSystem
utm32
=
crsFactory
.
createFromName
(
"EPSG:25832"
);
private
CoordinateReferenceSystem
wgs84
=
crsFactory
.
createFromName
(
"EPSG:4326"
);
private
CoordinateTransform
utm32ToWgs84Transform
=
new
BasicCoordinateTransform
(
utm32
,
wgs84
);
private
CoordinateTransform
gsk3ToWgs84Transform
=
new
BasicCoordinateTransform
(
gsk3
,
wgs84
);
private
String
pythonExecutable
=
null
;
@Async
public
CompletableFuture
<
String
>
extractGeolocation
(
Path
ifcFile
)
{
return
CompletableFuture
.
supplyAsync
(()
->
{
if
(
pythonExecutable
==
null
)
{
pythonExecutable
=
getAvailablePython
();
}
List
<
String
>
commands
=
new
ArrayList
<>();
commands
.
add
(
pythonExecutable
);
commands
.
add
(
"extract_geolocation.py"
);
commands
.
add
(
ifcFile
.
toString
());
ProcessBuilder
processBuilder
=
new
ProcessBuilder
(
commands
);
processBuilder
.
redirectError
(
Redirect
.
INHERIT
);
try
{
Process
process
=
processBuilder
.
start
();
process
.
onExit
().
thenApply
(
p
->
{
logger
.
info
(
"Geolocation extraction process exited with: {}"
,
process
.
exitValue
());
return
0
;
});
byte
[]
allBytes
=
process
.
getInputStream
().
readAllBytes
();
if
(
allBytes
.
length
==
0
)
{
return
null
;
}
List
<
Geolocation
>
data
=
mapper
.
readValue
(
allBytes
,
new
TypeReference
<>()
{
});
for
(
Geolocation
loc
:
data
)
{
logger
.
info
(
"Found geolocation: {}"
,
loc
);
}
return
findMostViableLocation
(
data
);
}
catch
(
Exception
e
)
{
throw
new
CompletionException
(
e
);
}
});
}
public
static
String
getAvailablePython
()
{
if
(
isCommandAvailable
(
"python"
))
{
return
"python"
;
}
else
if
(
isCommandAvailable
(
"python3"
))
{
return
"python3"
;
}
else
{
throw
new
IllegalArgumentException
(
"Could not find either python or python3 executable for python installation"
);
}
}
private
static
boolean
isCommandAvailable
(
String
command
)
{
try
{
ProcessBuilder
pb
=
new
ProcessBuilder
(
command
,
"--version"
);
Process
process
=
pb
.
start
();
try
(
BufferedReader
reader
=
new
BufferedReader
(
new
InputStreamReader
(
process
.
getInputStream
())))
{
String
line
=
reader
.
readLine
();
if
(
line
!=
null
&&
line
.
toLowerCase
().
contains
(
"python"
))
{
return
true
;
}
}
int
exitCode
=
process
.
waitFor
();
return
exitCode
==
0
;
}
catch
(
IOException
|
InterruptedException
e
)
{
return
false
;
}
}
private
String
findMostViableLocation
(
List
<
Geolocation
>
data
)
{
if
(
data
.
isEmpty
())
{
return
null
;
}
String
geoRef50
=
extractViableGeoRef50Data
(
data
);
if
(
geoRef50
!=
null
)
{
logger
.
info
(
"Using LoGeoRef50: {}"
,
geoRef50
);
return
geoRef50
;
}
String
geoRef40
=
extractViableGeoRef40Data
(
data
);
if
(
geoRef40
!=
null
)
{
logger
.
info
(
"Using LoGeoRef40: {}"
,
geoRef40
);
return
geoRef40
;
}
String
geoRef30
=
extractViableGeoRef30Data
(
data
);
if
(
geoRef30
!=
null
)
{
logger
.
info
(
"Using LoGeoRef30: {}"
,
geoRef30
);
return
geoRef30
;
}
String
geoRef20
=
extractViableGeoRef20Data
(
data
);
if
(
geoRef20
!=
null
)
{
logger
.
info
(
"Using LoGeoRef20: {}"
,
geoRef20
);
}
return
geoRef20
;
}
private
String
extractViableGeoRef50Data
(
List
<
Geolocation
>
data
)
{
try
{
Geolocation
loc
=
findByType
(
data
,
"LoGeoRef50"
);
if
(
loc
==
null
)
{
return
null
;
}
String
epsg
=
(
String
)
loc
.
getReferenceData
().
get
(
"targetCRS"
);
double
x
=
(
double
)
loc
.
getReferenceData
().
get
(
"eastings"
);
double
y
=
(
double
)
loc
.
getReferenceData
().
get
(
"northings"
);
Double
elevation
=
(
Double
)
loc
.
getReferenceData
().
get
(
"ele"
);
double
[]
lonLat
=
convertToWgs84
(
x
,
y
,
epsg
);
if
(
lonLat
==
null
)
{
return
null
;
}
Double
abscissa
=
(
Double
)
loc
.
getReferenceData
().
get
(
"XAxisAbscissa"
);
Double
ordinate
=
(
Double
)
loc
.
getReferenceData
().
get
(
"XAxisOrdinate"
);
if
(
abscissa
!=
null
&&
ordinate
!=
null
)
{
// found north axis as well
double
heading
=
Math
.
atan2
(
ordinate
,
abscissa
);
return
createLongLatElevationWithHeadingString
(
lonLat
,
elevation
,
heading
);
}
return
createLongLatElevationString
(
lonLat
,
elevation
);
}
catch
(
Exception
e
)
{
logger
.
info
(
"Failed to read LoGeoRef50: {}, {}"
,
e
.
getClass
().
getSimpleName
(),
e
.
getMessage
());
return
null
;
}
}
private
double
[]
convertToWgs84
(
double
x
,
double
y
,
String
epsg
)
{
CoordinateReferenceSystem
crs
=
crsFactory
.
createFromName
(
epsg
);
BasicCoordinateTransform
bct
=
new
BasicCoordinateTransform
(
crs
,
wgs84
);
logger
.
info
(
"Found {}"
,
epsg
);
ProjCoordinate
c1
=
new
ProjCoordinate
(
x
,
y
);
ProjCoordinate
c2
=
new
ProjCoordinate
();
bct
.
transform
(
c1
,
c2
);
return
new
double
[]
{
c2
.
x
,
c2
.
y
};
}
private
String
extractViableGeoRef40Data
(
List
<
Geolocation
>
data
)
{
try
{
Geolocation
loc
=
findByType
(
data
,
"LoGeoRef40"
);
if
(
loc
==
null
)
{
return
null
;
}
double
lon
=
(
double
)
loc
.
getReferenceData
().
get
(
"lon"
);
double
lat
=
(
double
)
loc
.
getReferenceData
().
get
(
"lat"
);
Double
elevation
=
(
Double
)
loc
.
getReferenceData
().
get
(
"ele"
);
double
[]
lonLat
=
convertToWgs84
(
lon
,
lat
);
if
(
lonLat
==
null
)
{
return
null
;
}
Double
axisX
=
(
Double
)
loc
.
getReferenceData
().
get
(
"axisX"
);
Double
axisY
=
(
Double
)
loc
.
getReferenceData
().
get
(
"axisY"
);
if
(
axisX
!=
null
&&
axisY
!=
null
)
{
// found north axis as well
double
heading
=
Math
.
atan2
(
axisY
,
axisX
);
return
createLongLatElevationWithHeadingString
(
lonLat
,
elevation
,
heading
);
}
return
createLongLatElevationString
(
lonLat
,
elevation
);
}
catch
(
Exception
e
)
{
return
null
;
}
}
private
String
createLongLatElevationWithHeadingString
(
double
[]
lonLat
,
Double
elevation
,
double
heading
)
{
if
(
elevation
==
null
||
(
elevation
<
0.001
&&
elevation
>
-
0.001
))
{
return
String
.
format
(
Locale
.
US
,
"{\"lon\":%.15f,\"lat\":%.15f, \"heading\": %.15f}"
,
lonLat
[
0
],
lonLat
[
1
],
heading
);
}
else
{
return
String
.
format
(
Locale
.
US
,
"{\"lon\": %.15f, \"lat\": %.15f, \"heading\": %.15f, \"ele\": %.15f}"
,
lonLat
[
0
],
lonLat
[
1
],
heading
,
elevation
);
}
}
private
String
extractViableGeoRef30Data
(
List
<
Geolocation
>
data
)
{
try
{
Geolocation
loc
=
findByType
(
data
,
"LoGeoRef30"
);
if
(
loc
==
null
)
{
return
null
;
}
double
lon
=
(
double
)
loc
.
getReferenceData
().
get
(
"lon"
);
double
lat
=
(
double
)
loc
.
getReferenceData
().
get
(
"lat"
);
Double
elevation
=
(
Double
)
loc
.
getReferenceData
().
get
(
"ele"
);
double
[]
lonLat
=
convertToWgs84
(
lon
,
lat
);
if
(
lonLat
==
null
)
{
return
null
;
}
return
createLongLatElevationString
(
lonLat
,
elevation
);
}
catch
(
Exception
e
)
{
return
null
;
}
}
private
String
createLongLatElevationString
(
double
[]
lonLat
,
Double
elevation
)
{
if
(
elevation
==
null
||
(
elevation
<
0.001
&&
elevation
>
-
0.001
))
{
return
String
.
format
(
Locale
.
US
,
"{\"lon\":%.15f,\"lat\":%.15f}"
,
lonLat
[
0
],
lonLat
[
1
]);
}
else
{
return
String
.
format
(
Locale
.
US
,
"{\"lon\": %.15f, \"lat\": %.15f, \"ele\": %.15f}"
,
lonLat
[
0
],
lonLat
[
1
],
elevation
);
}
}
private
String
extractViableGeoRef20Data
(
List
<
Geolocation
>
data
)
{
try
{
Geolocation
loc
=
findByType
(
data
,
"LoGeoRef20"
);
if
(
loc
==
null
)
{
return
null
;
}
double
lon
=
(
double
)
loc
.
getReferenceData
().
get
(
"lon"
);
double
lat
=
(
double
)
loc
.
getReferenceData
().
get
(
"lat"
);
Double
elevation
=
(
Double
)
loc
.
getReferenceData
().
get
(
"ele"
);
double
[]
lonLat
=
convertToWgs84
(
lon
,
lat
);
if
(
lonLat
==
null
)
{
return
null
;
}
return
createLongLatElevationString
(
lonLat
,
elevation
);
}
catch
(
Exception
e
)
{
return
null
;
}
}
/**
*
* @param lon
* @param lat
* @return array for longitude and latitude in that order
*/
private
double
[]
convertToWgs84
(
double
lon
,
double
lat
)
{
if
(
isWgs84
(
lon
,
lat
))
{
// valid WGS84 values
logger
.
info
(
"Found WGS84"
);
return
new
double
[]
{
lon
,
lat
};
}
else
if
(
isGsk3
(
lon
,
lat
))
{
// convert from Gsk3 to WGS84
logger
.
info
(
"Found GSK3"
);
ProjCoordinate
c1
=
new
ProjCoordinate
(
lon
,
lat
);
ProjCoordinate
c2
=
new
ProjCoordinate
();
gsk3ToWgs84Transform
.
transform
(
c1
,
c2
);
return
new
double
[]
{
c2
.
x
,
c2
.
y
};
}
else
if
(
isETRS89Utm32N
(
lon
,
lat
))
{
// convert from UTM32 to WGS84
logger
.
info
(
"Found UTM32"
);
ProjCoordinate
c1
=
new
ProjCoordinate
(
lon
,
lat
);
ProjCoordinate
c2
=
new
ProjCoordinate
();
utm32ToWgs84Transform
.
transform
(
c1
,
c2
);
return
new
double
[]
{
c2
.
x
,
c2
.
y
};
}
return
null
;
}
private
boolean
isWgs84
(
double
lon
,
double
lat
)
{
return
(
lat
>=
-
90
&&
lat
<=
90
)
&&
(
lon
>=
-
180
&&
lon
<=
180
);
}
private
boolean
isGsk3
(
double
lon
,
double
lat
)
{
// lon=3545359.5355, lat=5462569.635889
return
(
lon
>=
3262472.55
&&
lon
<=
3957072.2
)
&&
(
lat
>=
5236843.08
&&
lat
<=
6123498.88
);
}
private
boolean
isETRS89Utm32N
(
double
lon
,
double
lat
)
{
// 463996.23 5475743.2
// lon = x = easting
// lat = y = northing
return
(
lat
>=
0
&&
lat
<=
9329005.18
)
&&
(
lon
>=
166021.44
&&
lon
<=
833978.56
);
}
private
Geolocation
findByType
(
List
<
Geolocation
>
data
,
String
type
)
{
for
(
Geolocation
loc
:
data
)
{
if
(
type
.
equals
(
loc
.
getType
()))
{
return
loc
;
}
}
return
null
;
}
}
src/main/java/de/hft/stuttgart/lgl/ifc/model/Geolocation.java
0 → 100644
View file @
50016c9e
package
de.hft.stuttgart.lgl.ifc.model
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Objects
;
import
com.fasterxml.jackson.annotation.JsonAnyGetter
;
import
com.fasterxml.jackson.annotation.JsonAnySetter
;
import
com.fasterxml.jackson.annotation.JsonAutoDetect
;
@JsonAutoDetect
(
fieldVisibility
=
JsonAutoDetect
.
Visibility
.
ANY
)
public
class
Geolocation
{
private
String
type
;
@JsonAnySetter
private
Map
<
String
,
Object
>
referenceData
=
new
HashMap
<>();
public
String
getType
()
{
return
type
;
}
@JsonAnyGetter
public
Map
<
String
,
Object
>
getReferenceData
()
{
return
referenceData
;
}
@Override
public
int
hashCode
()
{
return
Objects
.
hash
(
referenceData
,
type
);
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
return
true
;
if
(
obj
==
null
)
return
false
;
if
(
getClass
()
!=
obj
.
getClass
())
return
false
;
Geolocation
other
=
(
Geolocation
)
obj
;
return
Objects
.
equals
(
referenceData
,
other
.
referenceData
)
&&
Objects
.
equals
(
type
,
other
.
type
);
}
@Override
public
String
toString
()
{
return
"Geolocation [type="
+
type
+
", referenceData="
+
referenceData
+
"]"
;
}
}
src/main/resources/application-dev.properties
View file @
50016c9e
converter.executable
=
ifcConvert.exe
python.executable
=
python.exe
management.endpoints.web.exposure.include
=
info,health
management.endpoint.health.enabled
=
true
server.port
=
50000
...
...
src/main/resources/application-docker.properties
View file @
50016c9e
converter.executable
=
./IfcConvert
python.executable
=
python
management.endpoints.web.exposure.include
=
info,health
management.endpoint.health.enabled
=
true
server.port
=
80
...
...
src/main/resources/application-prod.properties
View file @
50016c9e
converter.executable
=
./IfcConvert
python.executable
=
python
management.endpoints.web.exposure.include
=
info,health
management.endpoint.health.enabled
=
true
server.port
=
50000
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment