Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
CityGML
CityGMLViewer
Commits
0f66af82
Commit
0f66af82
authored
Aug 30, 2021
by
Matthias Betz
Browse files
initial viewer release
parent
364470b6
Changes
36
Show whitespace changes
Inline
Side-by-side
src/main/java/de/hft/stuttgart/citygml/viewer/datastructure/Primitive.java
0 → 100644
View file @
0f66af82
/*-
* Copyright 2021 Hochschule für Technik Stuttgart
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
de.hft.stuttgart.citygml.viewer.datastructure
;
import
java.util.ArrayList
;
import
java.util.List
;
import
com.jogamp.opengl.GL
;
import
de.hft.stuttgart.citygml.viewer.math.Vector3d
;
/**
* Result of the tesselation process. Primitives can be converted to triangles.
*
* @author Matthias Betz
*
*/
public
class
Primitive
{
private
static
final
double
AREA_EPSILON
=
0.00001
;
private
final
int
type
;
private
final
List
<
Integer
>
pIndices
=
new
ArrayList
<>();
private
final
List
<
Vector3d
>
vertices
;
public
Primitive
(
int
type
,
List
<
Vector3d
>
vertices
)
{
this
.
vertices
=
vertices
;
this
.
type
=
type
;
}
public
void
fillListWithIndices
(
List
<
Integer
>
indices
)
{
switch
(
type
)
{
case
GL
.
GL_TRIANGLES
:
for
(
int
i
=
0
;
i
<
pIndices
.
size
();
i
+=
3
)
{
addToListIfAreaNonNull
(
pIndices
.
get
(
i
),
pIndices
.
get
(
i
+
1
),
pIndices
.
get
(
i
+
2
),
indices
);
}
break
;
case
GL
.
GL_TRIANGLE_STRIP
:
for
(
int
i
=
0
;
i
<
pIndices
.
size
()
-
2
;
i
++)
{
if
(
i
%
2
==
0
)
{
addToListIfAreaNonNull
(
pIndices
.
get
(
i
),
pIndices
.
get
(
i
+
1
),
pIndices
.
get
(
i
+
2
),
indices
);
}
else
{
addToListIfAreaNonNull
(
pIndices
.
get
(
i
),
pIndices
.
get
(
i
+
2
),
pIndices
.
get
(
i
+
1
),
indices
);
}
}
break
;
case
GL
.
GL_TRIANGLE_FAN
:
Integer
first
=
pIndices
.
get
(
0
);
for
(
int
i
=
0
;
i
<
pIndices
.
size
()
-
2
;
i
++)
{
addToListIfAreaNonNull
(
first
,
pIndices
.
get
(
i
+
1
),
pIndices
.
get
(
i
+
2
),
indices
);
}
break
;
default
:
throw
new
IllegalStateException
(
"unknown type found: "
+
type
);
}
}
public
void
addIndex
(
Integer
i
)
{
pIndices
.
add
(
i
);
}
private
void
addToListIfAreaNonNull
(
Integer
i1
,
Integer
i2
,
Integer
i3
,
List
<
Integer
>
indices
)
{
Vector3d
v1
=
vertices
.
get
(
i1
);
Vector3d
v2
=
vertices
.
get
(
i2
);
Vector3d
v3
=
vertices
.
get
(
i3
);
double
area
=
Math
.
abs
(
calculateAreaOfTriangle
(
v1
,
v2
,
v3
));
if
(
area
>
AREA_EPSILON
)
{
indices
.
add
(
i1
);
indices
.
add
(
i2
);
indices
.
add
(
i3
);
}
}
/**
* Calculates the area of a triangle given by the 3 points
*
* @param v1 the first point of the triangle
* @param v2 the second point of the triangle
* @param v3 the last point of the triangle
* @return the area of the triangle
*/
private
static
double
calculateAreaOfTriangle
(
Vector3d
v1
,
Vector3d
v2
,
Vector3d
v3
)
{
double
a
=
v1
.
getDistance
(
v2
);
double
b
=
v2
.
getDistance
(
v3
);
double
c
=
v1
.
getDistance
(
v3
);
double
s
=
0.5d
*
(
a
+
b
+
c
);
return
Math
.
sqrt
(
s
*
(
s
-
a
)
*
(
s
-
b
)
*
(
s
-
c
));
}
}
src/main/java/de/hft/stuttgart/citygml/viewer/datastructure/Ring.java
0 → 100644
View file @
0f66af82
/*-
* Copyright 2021 Hochschule für Technik Stuttgart
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
de.hft.stuttgart.citygml.viewer.datastructure
;
import
java.util.ArrayList
;
import
java.util.List
;
import
de.hft.stuttgart.citygml.viewer.math.Vector3d
;
public
class
Ring
{
private
List
<
Vector3d
>
vertices
=
new
ArrayList
<>();
public
List
<
Vector3d
>
getVertices
()
{
return
vertices
;
}
public
void
addPoint
(
Vector3d
v
)
{
vertices
.
add
(
v
);
}
public
Vector3d
calculateNormal
()
{
double
[]
coords
=
new
double
[
3
];
for
(
int
i
=
0
;
i
<
vertices
.
size
()
-
1
;
i
++)
{
Vector3d
current
=
vertices
.
get
(
i
+
0
);
Vector3d
next
=
vertices
.
get
(
i
+
1
);
coords
[
0
]
+=
(
current
.
getZ
()
+
next
.
getZ
())
*
(
current
.
getY
()
-
next
.
getY
());
coords
[
1
]
+=
(
current
.
getX
()
+
next
.
getX
())
*
(
current
.
getZ
()
-
next
.
getZ
());
coords
[
2
]
+=
(
current
.
getY
()
+
next
.
getY
())
*
(
current
.
getX
()
-
next
.
getX
());
}
if
(
coords
[
0
]
==
0
&&
coords
[
1
]
==
0
&&
coords
[
2
]
==
0
)
{
// no valid normal vector found
if
(
vertices
.
size
()
<
3
)
{
// no three points, return x-axis
return
new
Vector3d
(
1
,
0
,
0
);
}
Vector3d
v1
=
vertices
.
get
(
0
);
Vector3d
v2
=
vertices
.
get
(
1
);
Vector3d
v3
=
vertices
.
get
(
2
);
return
calculateNormalWithCross
(
v1
,
v2
,
v3
);
}
Vector3d
v
=
new
Vector3d
(
coords
);
v
.
normalize
();
return
v
;
}
private
Vector3d
calculateNormalWithCross
(
Vector3d
v1
,
Vector3d
v2
,
Vector3d
v3
)
{
Vector3d
dir1
=
v2
.
minus
(
v1
);
Vector3d
dir2
=
v3
.
minus
(
v1
);
Vector3d
cross
=
dir1
.
cross
(
dir2
);
return
cross
.
normalize
();
}
}
src/main/java/de/hft/stuttgart/citygml/viewer/datastructure/TesselatedPolygon.java
0 → 100644
View file @
0f66af82
/*-
* Copyright 2021 Hochschule für Technik Stuttgart
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
de.hft.stuttgart.citygml.viewer.datastructure
;
import
java.awt.Color
;
import
java.util.ArrayList
;
import
java.util.List
;
import
de.hft.stuttgart.citygml.viewer.math.Vector3d
;
public
class
TesselatedPolygon
{
private
List
<
Triangle3d
>
triangles
;
private
Vector3d
normal
;
private
Color
color
;
public
static
TesselatedPolygon
of
(
Polygon
p
)
{
TesselatedPolygon
tessP
=
JoglTesselator
.
tesselatePolygon
(
p
);
tessP
.
normal
=
p
.
calculateNormal
();
tessP
.
color
=
p
.
getColor
();
return
tessP
;
}
public
TesselatedPolygon
(
List
<
Triangle3d
>
triangles
)
{
this
.
triangles
=
triangles
;
}
public
TesselatedPolygon
(
List
<
Vector3d
>
vertices
,
List
<
Integer
>
indices
)
{
if
(
indices
.
size
()
%
3
!=
0
)
{
throw
new
IllegalArgumentException
(
"Number of indices is not a multiple of 3"
);
}
triangles
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
indices
.
size
();
i
=
i
+
3
)
{
Vector3d
v1
=
vertices
.
get
(
indices
.
get
(
i
+
0
));
Vector3d
v2
=
vertices
.
get
(
indices
.
get
(
i
+
1
));
Vector3d
v3
=
vertices
.
get
(
indices
.
get
(
i
+
2
));
triangles
.
add
(
new
Triangle3d
(
v1
,
v2
,
v3
));
}
}
public
List
<
Triangle3d
>
getTriangles
()
{
return
triangles
;
}
public
Vector3d
getNormal
()
{
return
normal
;
}
public
Color
getColor
()
{
return
color
;
}
}
src/main/java/de/hft/stuttgart/citygml/viewer/datastructure/TesselationException.java
0 → 100644
View file @
0f66af82
/*-
* Copyright 2021 Hochschule für Technik Stuttgart
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
de.hft.stuttgart.citygml.viewer.datastructure
;
/**
* Thrown when something went wrong with the tesselation process.
*
* @author Matthias Betz
*
*/
public
class
TesselationException
extends
RuntimeException
{
public
TesselationException
()
{
super
();
}
public
TesselationException
(
String
message
,
Throwable
cause
,
boolean
enableSuppression
,
boolean
writableStackTrace
)
{
super
(
message
,
cause
,
enableSuppression
,
writableStackTrace
);
}
public
TesselationException
(
String
message
,
Throwable
cause
)
{
super
(
message
,
cause
);
}
public
TesselationException
(
Throwable
cause
)
{
super
(
cause
);
}
private
static
final
long
serialVersionUID
=
-
2010522579830781136L
;
public
TesselationException
(
String
message
)
{
super
(
message
);
}
}
src/main/java/de/hft/stuttgart/citygml/viewer/datastructure/Triangle3d.java
0 → 100644
View file @
0f66af82
/*-
* Copyright 2021 Hochschule für Technik Stuttgart
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
de.hft.stuttgart.citygml.viewer.datastructure
;
import
de.hft.stuttgart.citygml.viewer.math.Vector3d
;
/**
* A three dimensional triangle described by three points
*
* @author Matthias Betz
*
*/
public
class
Triangle3d
{
private
Vector3d
p1
;
private
Vector3d
p2
;
private
Vector3d
p3
;
public
Triangle3d
(
Vector3d
p1
,
Vector3d
p2
,
Vector3d
p3
)
{
this
.
p1
=
p1
;
this
.
p2
=
p2
;
this
.
p3
=
p3
;
}
public
Vector3d
getP1
()
{
return
p1
;
}
public
Vector3d
getP2
()
{
return
p2
;
}
public
Vector3d
getP3
()
{
return
p3
;
}
@Override
public
int
hashCode
()
{
final
int
prime
=
31
;
int
result
=
1
;
result
=
prime
*
result
+
((
p1
==
null
)
?
0
:
p1
.
hashCode
());
result
=
prime
*
result
+
((
p2
==
null
)
?
0
:
p2
.
hashCode
());
result
=
prime
*
result
+
((
p3
==
null
)
?
0
:
p3
.
hashCode
());
return
result
;
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(
obj
==
null
)
{
return
false
;
}
if
(
getClass
()
!=
obj
.
getClass
())
{
return
false
;
}
Triangle3d
other
=
(
Triangle3d
)
obj
;
if
(
p1
==
null
)
{
if
(
other
.
p1
!=
null
)
{
return
false
;
}
}
else
if
(!
p1
.
equals
(
other
.
p1
))
{
return
false
;
}
if
(
p2
==
null
)
{
if
(
other
.
p2
!=
null
)
{
return
false
;
}
}
else
if
(!
p2
.
equals
(
other
.
p2
))
{
return
false
;
}
if
(
p3
==
null
)
{
if
(
other
.
p3
!=
null
)
{
return
false
;
}
}
else
if
(!
p3
.
equals
(
other
.
p3
))
{
return
false
;
}
return
true
;
}
@Override
public
String
toString
()
{
return
"Triangle3d [p1="
+
p1
+
", p2="
+
p2
+
", p3="
+
p3
+
"]"
;
}
}
src/main/java/de/hft/stuttgart/citygml/viewer/math/BoundingBoxCalculator.java
0 → 100644
View file @
0f66af82
/*-
* Copyright 2021 Hochschule für Technik Stuttgart
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
de.hft.stuttgart.citygml.viewer.math
;
import
java.util.ArrayList
;
import
java.util.List
;
import
de.hft.stuttgart.citygml.viewer.datastructure.BoundingBox
;
import
de.hft.stuttgart.citygml.viewer.datastructure.Polygon
;
import
de.hft.stuttgart.citygml.viewer.parser.FeatureMapper
;
/**
* Utility class for calculating axis aligned bounding boxes for different
* inputs.
*
* @author Matthias Betz
*
*/
public
class
BoundingBoxCalculator
{
private
BoundingBoxCalculator
()
{
// only static use
}
/**
* This will calculate two points where every other point in the geometry is
* between those two. If the geometry does not contain points or is null, an
* empty array is returned. This is considered an axis aligned bounding box.
* Only the exterior rings of the polygons is used as inner rings should be
* within the exterior or they are faulty.
*
* @param a list of polygons containing the vertices
* @return an BoundingBox containing the two end points of the bounding box.
*/
public
static
BoundingBox
calculateBoundingBox
(
List
<
Polygon
>
polygons
)
{
double
lowX
=
Double
.
MAX_VALUE
;
double
highX
=
Double
.
NEGATIVE_INFINITY
;
double
lowY
=
Double
.
MAX_VALUE
;
double
highY
=
Double
.
NEGATIVE_INFINITY
;
double
lowZ
=
Double
.
MAX_VALUE
;
double
highZ
=
Double
.
NEGATIVE_INFINITY
;
for
(
Polygon
p
:
polygons
)
{
// only need to check exterior rings
for
(
Vector3d
v
:
p
.
getExteriorRing
().
getVertices
())
{
if
(
v
.
getX
()
<
lowX
)
{
lowX
=
v
.
getX
();
}
if
(
v
.
getX
()
>
highX
)
{
highX
=
v
.
getX
();
}
if
(
v
.
getY
()
<
lowY
)
{
lowY
=
v
.
getY
();
}
if
(
v
.
getY
()
>
highY
)
{
highY
=
v
.
getY
();
}
if
(
v
.
getZ
()
<
lowZ
)
{
lowZ
=
v
.
getZ
();
}
if
(
v
.
getZ
()
>
highZ
)
{
highZ
=
v
.
getZ
();
}
}
}
Vector3d
[]
result
=
new
Vector3d
[
2
];
result
[
0
]
=
new
Vector3d
(
lowX
,
lowY
,
lowZ
);
result
[
1
]
=
new
Vector3d
(
highX
,
highY
,
highZ
);
return
BoundingBox
.
of
(
result
);
}
public
static
BoundingBox
calculateBoundingBoxFromPoints
(
List
<?
extends
Vector3d
>
points
)
{
double
lowX
=
Double
.
MAX_VALUE
;
double
highX
=
Double
.
NEGATIVE_INFINITY
;
double
lowY
=
Double
.
MAX_VALUE
;
double
highY
=
Double
.
NEGATIVE_INFINITY
;
double
lowZ
=
Double
.
MAX_VALUE
;
double
highZ
=
Double
.
NEGATIVE_INFINITY
;
// only need to check exterior rings
for
(
Vector3d
v
:
points
)
{
if
(
v
.
getX
()
<
lowX
)
{
lowX
=
v
.
getX
();
}
if
(
v
.
getX
()
>
highX
)
{
highX
=
v
.
getX
();
}
if
(
v
.
getY
()
<
lowY
)
{
lowY
=
v
.
getY
();
}
if
(
v
.
getY
()
>
highY
)
{
highY
=
v
.
getY
();
}
if
(
v
.
getZ
()
<
lowZ
)
{
lowZ
=
v
.
getZ
();
}
if
(
v
.
getZ
()
>
highZ
)
{
highZ
=
v
.
getZ
();
}
}
Vector3d
[]
result
=
new
Vector3d
[
2
];
result
[
0
]
=
new
Vector3d
(
lowX
,
lowY
,
lowZ
);
result
[
1
]
=
new
Vector3d
(
highX
,
highY
,
highZ
);
return
BoundingBox
.
of
(
result
);
}
public
static
BoundingBox
calculateBoundingBox
(
FeatureMapper
mapper
)
{
List
<
List
<
Polygon
>>
polygonList
=
new
ArrayList
<>();
polygonList
.
add
(
mapper
.
getLod1Polygons
());
polygonList
.
add
(
mapper
.
getLod2Polygons
());
polygonList
.
add
(
mapper
.
getLod3Polygons
());
polygonList
.
add
(
mapper
.
getLod4Polygons
());
double
lowX
=
Double
.
MAX_VALUE
;
double
highX
=
Double
.
NEGATIVE_INFINITY
;
double
lowY
=
Double
.
MAX_VALUE
;
double
highY
=
Double
.
NEGATIVE_INFINITY
;
double
lowZ
=
Double
.
MAX_VALUE
;
double
highZ
=
Double
.
NEGATIVE_INFINITY
;
for
(
List
<
Polygon
>
polygons
:
polygonList
)
{
for
(
Polygon
p
:
polygons
)
{
// only need to check exterior rings
for
(
Vector3d
v
:
p
.
getExteriorRing
().
getVertices
())
{
if
(
v
.
getX
()
<
lowX
)
{
lowX
=
v
.
getX
();
}
if
(
v
.
getX
()
>
highX
)
{
highX
=
v
.
getX
();
}
if
(
v
.
getY
()
<
lowY
)
{
lowY
=
v
.
getY
();
}
if
(
v
.
getY
()
>
highY
)
{
highY
=
v
.
getY
();
}
if
(
v
.
getZ
()
<
lowZ
)
{
lowZ
=
v
.
getZ
();
}
if
(
v
.
getZ
()
>
highZ
)
{
highZ
=
v
.
getZ
();
}
}
}
}
Vector3d
[]
result
=
new
Vector3d
[
2
];
result
[
0
]
=
new
Vector3d
(
lowX
,
lowY
,
lowZ
);
result
[
1
]
=
new
Vector3d
(
highX
,
highY
,
highZ
);
return
BoundingBox
.
of
(
result
);
}
}
src/main/java/de/hft/stuttgart/citygml/viewer/math/Vector3d.java
0 → 100644
View file @
0f66af82
/*-
* Copyright 2021 Hochschule für Technik Stuttgart
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
de.hft.stuttgart.citygml.viewer.math
;
import
java.io.Serializable
;
import
java.util.Arrays
;
public
class
Vector3d
implements
Serializable
{
private
static
final
long
serialVersionUID
=
3495650092142761365L
;
private
static
final
Vector3d
ORIGIN
=
new
Vector3d
();
public
static
final
int
X
=
0
;
public
static
final
int
Y
=
1
;
public
static
final
int
Z
=
2
;
private
double
[]
coords
;
public
Vector3d
()
{
this
(
0
d
,
0
d
,
0
d
);
}
public
Vector3d
(
double
x
,
double
y
,
double
z
)
{
coords
=
new
double
[
3
];
coords
[
0
]
=
x
;
coords
[
1
]
=
y
;
coords
[
2
]
=
z
;
}
public
Vector3d
(
double
[]
coords
)
{
if
(
coords
==
null
)
{
throw
new
IllegalArgumentException
(
"Coordinates can not be null"
);
}
this
.
coords
=
coords
;
}
public
Vector3d
(
Vector3d
vec
)
{
coords
=
new
double
[
3
];
coords
[
0
]
=
vec
.
getX
();
coords
[
1
]
=
vec
.
getY
();
coords
[
2
]
=
vec
.
getZ
();
}
public
double
getX
()
{
return
coords
[
0
];
}
public
double
getY
()
{
return
coords
[
1
];
}
public
double
getZ
()
{
return
coords
[
2
];
}
public
void
setX
(
double
x
)
{
coords
[
0
]
=
x
;
}
public
void
setY
(
double
y
)
{
coords
[
1
]
=
y
;
}
public
void
setZ
(
double
z
)
{
coords
[
2
]
=
z
;
}
/**
* Getter for all coordinates. The changes made to this array are reflected in
* this vector.
*
* @return the coordiantes array
*/
public
double
[]
getCoordinates
()
{
return
coords
;
}
public
void
setCoordinates
(
double
[]
coordiantes
)
{
if
(
coordiantes
==
null
||
coordiantes
.
length
!=
3
)
{
throw
new
IllegalArgumentException
(
"Vector must have exactly 3 coordinates"
);
}
this
.
coords
=
coordiantes
;
}
public
double
getLength
()
{
return
getDistance
(
ORIGIN
);
}
public
double
getSquaredLength
()
{
double
x
=
coords
[
0
];
double
y
=
coords
[
1
];
double
z
=
coords
[
2
];
return
x
*
x
+
y
*
y
+
z
*
z
;
}
public
double
getDistance
(
Vector3d
other
)
{
return
Math
.
sqrt
(
getDistanceSquare
(
other
));
}
public
double
getDistanceSquare
(
Vector3d
other
)
{
double
x
=
coords
[
0
]
-
other
.
getX
();
double
y
=
coords
[
1
]
-
other
.
getY
();
double
z
=
coords
[
2
]
-
other
.
getZ
();
return
x
*
x
+
y
*
y
+
z
*
z
;
}
/**
* adds another vector to this one. The result is
* <code><br>(a1 + b1)<br>(a2 + b2)<br>(a3 + b3)</code>
*
* @param b the other vector
* @return the sum of both vectors as a new vector. Values in this instance
* remain unchanged.
*/
public
Vector3d
plus
(
Vector3d
b
)
{
double
x
=
coords
[
0
]
+
b
.
getX
();
double
y
=
coords
[
1
]
+
b
.
getY
();
double
z
=
coords
[
2
]
+
b
.
getZ
();
return
new
Vector3d
(
x
,
y
,
z
);
}
/**
* add a value to a coordinate. This will change the coordinates of this vector.
*
* @param coordinateIndex one of <code>Vector3d.X, Vector3d.Y, Vector3d.Z</code>
* @param value the added value
* @return the current instance for chaining commands
*/
public
Vector3d
plus
(
int
coordinateIndex
,
double
value
)
{
if
(
coordinateIndex
<
0
||
coordinateIndex
>
2
)
{
throw
new
IllegalArgumentException
(
"coordinateIndex has to be between 0 and 2"
);
}
coords
[
coordinateIndex
]
+=
value
;
return
this
;
}
/**
* subtract a value to a coordinate. This will change the coordinates of this
* vector.
*
* @param coordinateIndex one of <code>Vector3d.X, Vector3d.Y, Vector3d.Z</code>
* @param value the subtracted value
* @return the current instance for chaining commands
*/
public
Vector3d
minus
(
int
coordinateIndex
,
double
value
)
{
if
(
coordinateIndex
<
0
||
coordinateIndex
>
2
)
{
throw
new
IllegalArgumentException
(
"coordinateIndex has to be between 0 and 2"
);
}
coords
[
coordinateIndex
]
-=
value
;
return
this
;
}
/**
* subtract another vector from this one. The result is
* <code><br>(a1 - b1)<br>(a2 - b2)<br>(a3 - b3)</code>
*
* @param b the other vector
* @return the result as a new vector. Values in this instance remain unchanged.
*/
public
Vector3d
minus
(
Vector3d
b
)
{
double
x
=
coords
[
0
]
-
b
.
getX
();
double
y
=
coords
[
1
]
-
b
.
getY
();
double
z
=
coords
[
2
]
-
b
.
getZ
();
return
new
Vector3d
(
x
,
y
,
z
);
}
/**
* multiply this vector with a scalar.
*
* @param scalar the scalar
* @return the result as a new vector. Values in this instance remain unchanged.
*/
public
Vector3d
mult
(
double
scalar
)
{
double
x
=
coords
[
0
]
*
scalar
;
double
y
=
coords
[
1
]
*
scalar
;
double
z
=
coords
[
2
]
*
scalar
;
return
new
Vector3d
(
x
,
y
,
z
);
}
/**
* normalizes this vector. This method changes the coordinates of this instance.
*/
public
Vector3d
normalize
()
{
double
length
=
getLength
();
// if the length is already 1, do nothing
final
double
epsilon
=
0.0000001
;
if
(
Math
.
abs
(
1
-
length
)
<
epsilon
)
{
return
this
;
}
coords
[
0
]
/=
length
;
coords
[
1
]
/=
length
;
coords
[
2
]
/=
length
;
return
this
;
}
/**
* calculates the cross product. The result is
* <code><br>(a2 * b3 - a3 * b2)<br>(a3 * b1 - a1 * b3)<br>(a1 * b2 - a2 * b1)</code>
*
* @param b the other vector
* @return the result as a new vector. Values in this instance remain unchanged.
*/
public
Vector3d
cross
(
Vector3d
b
)
{
double
x
=
coords
[
1
]
*
b
.
getZ
()
-
coords
[
2
]
*
b
.
getY
();
double
y
=
coords
[
2
]
*
b
.
getX
()
-
coords
[
0
]
*
b
.
getZ
();
double
z
=
coords
[
0
]
*
b
.
getY
()
-
coords
[
1
]
*
b
.
getX
();
return
new
Vector3d
(
x
,
y
,
z
);
}
/**
* Calculates the dot product. The result is
* <code><br>(a1 * b1) + (a2 * b2) + (a3 * b3)<br></code>
*
* @param b the other vector
* @return the dot product
*/
public
double
dot
(
Vector3d
b
)
{
return
coords
[
0
]
*
b
.
getX
()
+
coords
[
1
]
*
b
.
getY
()
+
coords
[
2
]
*
b
.
getZ
();
}
/**
* creates a new copy of this vector.
*
* @return a copy of this vector
*/
public
Vector3d
copy
()
{
return
new
Vector3d
(
coords
[
0
],
coords
[
1
],
coords
[
2
]);
}
@Override
public
String
toString
()
{
final
int
maxLen
=
5
;
StringBuilder
builder
=
new
StringBuilder
();
builder
.
append
(
"Vector3d [coords="
);
builder
.
append
(
coords
!=
null
?
Arrays
.
toString
(
Arrays
.
copyOf
(
coords
,
Math
.
min
(
coords
.
length
,
maxLen
)))
:
null
);
builder
.
append
(
"]"
);
return
builder
.
toString
();
}
@Override
public
int
hashCode
()
{
final
int
prime
=
31
;
int
result
=
1
;
result
=
prime
*
result
+
Arrays
.
hashCode
(
coords
);
return
result
;
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
return
true
;
if
(
obj
==
null
)
return
false
;
if
(
getClass
()
!=
obj
.
getClass
())
return
false
;
Vector3d
other
=
(
Vector3d
)
obj
;
return
Arrays
.
equals
(
coords
,
other
.
coords
);
}
/**
* Two vectors are equals, when the distance between both is less than epsilon
*
* @param other the other vector
* @param epsilon the distance where the vectors are considered the same
* @return true if they are within epsilon distance, false otherwise.
*/
public
boolean
equalsWithEpsilon
(
Vector3d
other
,
double
epsilon
)
{
if
(
other
==
this
)
{
return
true
;
}
Vector3d
dif
=
this
.
minus
(
other
);
double
sqLength
=
dif
.
getSquaredLength
();
return
sqLength
<
(
epsilon
*
epsilon
);
}
public
double
getCoordinate
(
int
axis
)
{
return
coords
[
axis
];
}
public
void
plus
(
double
radius
)
{
coords
[
0
]
+=
radius
;
coords
[
1
]
+=
radius
;
coords
[
2
]
+=
radius
;
}
}
src/main/java/de/hft/stuttgart/citygml/viewer/parser/CityGMLParser.java
0 → 100644
View file @
0f66af82
/*-
* Copyright 2021 Hochschule für Technik Stuttgart
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
de.hft.stuttgart.citygml.viewer.parser
;
import
java.io.BufferedInputStream
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.util.logging.Level
;
import
java.util.logging.Logger
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
javax.xml.XMLConstants
;
import
javax.xml.parsers.ParserConfigurationException
;
import
javax.xml.parsers.SAXParser
;
import
javax.xml.parsers.SAXParserFactory
;
import
org.locationtech.proj4j.BasicCoordinateTransform
;
import
org.locationtech.proj4j.CRSFactory
;
import
org.locationtech.proj4j.CoordinateReferenceSystem
;
import
org.locationtech.proj4j.ProjCoordinate
;
import
org.locationtech.proj4j.units.Units
;
import
org.xml.sax.InputSource
;
import
org.xml.sax.SAXException
;
import
org.xml.sax.SAXNotRecognizedException
;
import
org.xml.sax.SAXNotSupportedException
;
import
de.hft.stuttgart.citygml.viewer.CityGmlHandler
;
import
de.hft.stuttgart.citygml.viewer.math.Vector3d
;
public
class
CityGMLParser
{
private
static
final
Logger
log
=
Logger
.
getLogger
(
CityGMLParser
.
class
.
getName
());
private
static
final
SAXParserFactory
FACTORY
;
private
static
final
CRSFactory
CRS_FACTORY
=
new
CRSFactory
();
// EPSG:31467
private
static
final
Pattern
P_EPSG
=
Pattern
.
compile
(
"^(EPSG:\\d+)$"
);
// urn:ogc:def:crs,crs:EPSG:6.12:31467,crs:EPSG:6.12:5783
// or
// urn:ogc:def:crs,crs:EPSG::28992
private
static
final
Pattern
P_OGC
=
Pattern
.
compile
(
"urn:ogc:def:crs,crs:EPSG:[\\d\\.]*:([\\d]+)\\D*"
);
private
static
final
Pattern
P_OGC2
=
Pattern
.
compile
(
"urn:ogc:def:crs:EPSG:[\\d\\.]*:([\\d]+)\\D*"
);
// urn:adv:crs:DE_DHDN_3GK3*DE_DHHN92_NH
// urn:adv:crs:ETRS89_UTM32*DE_DHHN92_NH
private
static
final
Pattern
P_URN
=
Pattern
.
compile
(
"urn:adv:crs:([^\\*]+)"
);
private
static
final
String
WGS_84
=
"EPSG:4326"
;
static
{
FACTORY
=
SAXParserFactory
.
newInstance
();
try
{
FACTORY
.
setFeature
(
XMLConstants
.
FEATURE_SECURE_PROCESSING
,
true
);
}
catch
(
SAXNotRecognizedException
|
SAXNotSupportedException
|
ParserConfigurationException
e
)
{
e
.
printStackTrace
();
}
}
public
static
void
parseEpsgCodeFromFile
(
File
file
,
ParserConfiguration
config
)
throws
IOException
,
ParserConfigurationException
,
SAXException
{
try
(
BufferedInputStream
bis
=
new
BufferedInputStream
(
new
FileInputStream
(
file
)))
{
parseEpsgCodeFromStream
(
bis
,
config
);
}
}
private
static
void
parseEpsgCodeFromStream
(
InputStream
is
,
ParserConfiguration
config
)
throws
ParserConfigurationException
,
SAXException
{
SAXParser
parser
=
FACTORY
.
newSAXParser
();
CityGmlHandler
handler
=
new
CityGmlHandler
();
try
{
parser
.
parse
(
new
InputSource
(
is
),
handler
);
}
catch
(
EnvelopeFoundException
e
)
{
try
{
parseCoordinateSystem
(
config
,
handler
);
}
catch
(
Exception
e2
)
{
log
.
log
(
Level
.
WARNING
,
"Caught unknown error while parsing EPSG, assuming metric coordinate system"
,
e2
);
}
}
catch
(
Exception
e
)
{
log
.
log
(
Level
.
WARNING
,
"Caught unknown error while parsing EPSG, assuming metric coordinate system"
,
e
);
}
}
private
static
void
parseCoordinateSystem
(
ParserConfiguration
config
,
CityGmlHandler
handler
)
{
if
(
handler
.
getEpsg
()
==
null
)
{
return
;
}
CoordinateReferenceSystem
crs
=
crsFromSrsName
(
handler
.
getEpsg
());
if
(
crs
==
null
)
{
// could not find a coordinate system for srsName
// assuming metric system
return
;
}
if
(
crs
.
getProjection
().
getUnits
()
==
Units
.
METRES
)
{
// coordinate system is in meters, do not convert
return
;
}
Vector3d
low
=
handler
.
getLowerCorner
();
Vector3d
up
=
handler
.
getUpperCorner
();
double
centerLong
=
low
.
getX
()
+
((
up
.
getX
()
-
low
.
getX
())
/
2
);
double
centerLat
=
low
.
getY
()
+
((
up
.
getY
()
-
low
.
getY
())
/
2
);
if
(!
crs
.
getName
().
equals
(
WGS_84
))
{
// need to convert coordinates first to WGS84, then find UTM Zone
CoordinateReferenceSystem
wgs84
=
crsFromSrsName
(
WGS_84
);
ProjCoordinate
p1
=
new
ProjCoordinate
();
p1
.
setValue
(
centerLong
,
centerLat
);
ProjCoordinate
p2
=
new
ProjCoordinate
();
BasicCoordinateTransform
bct
=
new
BasicCoordinateTransform
(
crs
,
wgs84
);
bct
.
transform
(
p1
,
p2
);
centerLong
=
p2
.
x
;
centerLat
=
p2
.
y
;
}
int
zone
=
(
int
)
(
31
+
Math
.
round
(
centerLong
/
6
));
CoordinateReferenceSystem
utm
;
if
(
centerLat
<
0
)
{
// south
utm
=
CRS_FACTORY
.
createFromParameters
(
"UTM"
,
"+proj=utm +ellps=WGS84 +units=m +zone="
+
zone
+
" +south"
);
}
else
{
// north
utm
=
CRS_FACTORY
.
createFromParameters
(
"UTM"
,
"+proj=utm +ellps=WGS84 +units=m +zone="
+
zone
);
}
config
.
setCoordinateSystem
(
crs
,
utm
);
}
/**
* The srsName (The name by which this reference system is identified) inside
* the CityGML file can have multiple formats. This method tries to parse the
* string and detect the corresponding reference system. If it is found, it
* returns a proj4j.CoordinateReferenceSystem. It throws an
* IllegalArgumentException otherwise.
*
* This method should be able to parse any EPSG id : e.g. "EPSG:1234". German
* Citygmls might also have "DE_DHDN_3GK3" or "ETRS89_UTM32" as srsName, so
* those are also included. It isn't guaranteed that those formats are correctly
* parsed, though.
*
* The EPSG ids and parameters are defined in resources ('nad/epsg') inside
* proj4j-0.1.0.jar. Some EPSG ids are missing though, e.g. 7415
*
* @param srsName
* @return CoordinateReferenceSystem
*/
private
static
CoordinateReferenceSystem
crsFromSrsName
(
String
srsName
)
{
srsName
=
srsName
.
trim
();
Matcher
mEPSG
=
P_EPSG
.
matcher
(
srsName
);
if
(
mEPSG
.
find
())
{
if
(
"EPSG:4979"
.
contentEquals
(
srsName
))
{
srsName
=
"EPSG:4236"
;
}
else
if
(
"EPSG:7415"
.
contentEquals
(
srsName
))
{
return
CRS_FACTORY
.
createFromParameters
(
"EPSG:7415"
,
"+proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +towgs84=565.417,50.3319,465.552,-0.398957,0.343988,-1.8774,4.0725 +units=m +no_defs"
);
}
return
CRS_FACTORY
.
createFromName
(
srsName
);
}
Matcher
mOGC
=
P_OGC
.
matcher
(
srsName
);
if
(
mOGC
.
find
())
{
return
CRS_FACTORY
.
createFromName
(
"EPSG:"
+
mOGC
.
group
(
1
));
}
Matcher
mOGC2
=
P_OGC2
.
matcher
(
srsName
);
if
(
mOGC2
.
find
())
{
return
CRS_FACTORY
.
createFromName
(
"EPSG:"
+
mOGC2
.
group
(
1
));
}
Matcher
mURN
=
P_URN
.
matcher
(
srsName
);
// NOTE: Could use a HashMap if the switch/case becomes too long.
if
(
mURN
.
find
())
{
switch
(
mURN
.
group
(
1
))
{
case
"DE_DHDN_3GK2"
:
return
CRS_FACTORY
.
createFromName
(
"EPSG:31466"
);
case
"DE_DHDN_3GK3"
:
return
CRS_FACTORY
.
createFromName
(
"EPSG:31467"
);
case
"DE_DHDN_3GK4"
:
return
CRS_FACTORY
.
createFromName
(
"EPSG:31468"
);
case
"DE_DHDN_3GK5"
:
return
CRS_FACTORY
.
createFromName
(
"EPSG:31469"
);
case
"ETRS89_UTM32"
:
return
CRS_FACTORY
.
createFromName
(
"EPSG:25832"
);
default
:
return
null
;
}
}
if
(
srsName
.
equals
(
"http://www.opengis.net/def/crs/EPSG/0/6697"
))
{
return
CRS_FACTORY
.
createFromParameters
(
"EPSG:6697"
,
"+proj=longlat +ellps=GRS80 +no_defs +axis=neu"
);
}
return
null
;
}
}
src/main/java/de/hft/stuttgart/citygml/viewer/parser/EnvelopeFoundException.java
0 → 100644
View file @
0f66af82
/*-
* Copyright 2021 Hochschule für Technik Stuttgart
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
de.hft.stuttgart.citygml.viewer.parser
;
import
org.xml.sax.SAXException
;
/**
* To stop the SAXParser from further parsing when the relevant section has
* already been found.
*
* @author Matthias Betz
*
*/
public
class
EnvelopeFoundException
extends
SAXException
{
private
static
final
long
serialVersionUID
=
-
9188617211115043815L
;
public
EnvelopeFoundException
()
{
super
();
}
public
EnvelopeFoundException
(
Exception
e
)
{
super
(
e
);
}
public
EnvelopeFoundException
(
String
message
,
Exception
e
)
{
super
(
message
,
e
);
}
public
EnvelopeFoundException
(
String
message
)
{
super
(
message
);
}
}
src/main/java/de/hft/stuttgart/citygml/viewer/parser/FeatureMapper.java
0 → 100644
View file @
0f66af82
/*-
* Copyright 2021 Hochschule für Technik Stuttgart
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
de.hft.stuttgart.citygml.viewer.parser
;
import
java.awt.Color
;
import
java.io.FileReader
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Properties
;
import
org.citygml4j.model.bridge.AbstractBridge
;
import
org.citygml4j.model.building.AbstractBuilding
;
import
org.citygml4j.model.building.BuildingInstallation
;
import
org.citygml4j.model.construction.AbstractFillingElement
;
import
org.citygml4j.model.construction.Door
;
import
org.citygml4j.model.construction.GroundSurface
;
import
org.citygml4j.model.construction.RoofSurface
;
import
org.citygml4j.model.construction.Window
;
import
org.citygml4j.model.core.AbstractThematicSurface
;
import
org.citygml4j.model.core.ImplicitGeometry
;
import
org.citygml4j.model.core.ImplicitGeometryProperty
;
import
org.citygml4j.model.deprecated.bridge.DeprecatedPropertiesOfAbstractBridge
;
import
org.citygml4j.model.deprecated.building.DeprecatedPropertiesOfAbstractBuilding
;
import
org.citygml4j.model.deprecated.building.DeprecatedPropertiesOfBuildingInstallation
;
import
org.citygml4j.model.deprecated.core.DeprecatedPropertiesOfAbstractThematicSurface
;
import
org.citygml4j.model.deprecated.transportation.DeprecatedPropertiesOfAbstractTransportationSpace
;
import
org.citygml4j.model.deprecated.transportation.TransportationComplex
;
import
org.citygml4j.model.deprecated.vegetation.DeprecatedPropertiesOfPlantCover
;
import
org.citygml4j.model.deprecated.vegetation.DeprecatedPropertiesOfSolitaryVegetationObject
;
import
org.citygml4j.model.deprecated.waterbody.DeprecatedPropertiesOfWaterBody
;
import
org.citygml4j.model.landuse.LandUse
;
import
org.citygml4j.model.relief.TINRelief
;
import
org.citygml4j.model.transportation.AuxiliaryTrafficArea
;
import
org.citygml4j.model.transportation.TrafficArea
;
import
org.citygml4j.model.vegetation.PlantCover
;
import
org.citygml4j.model.vegetation.SolitaryVegetationObject
;
import
org.citygml4j.model.waterbody.WaterBody
;
import
org.citygml4j.visitor.ObjectWalker
;
import
org.locationtech.proj4j.BasicCoordinateTransform
;
import
org.locationtech.proj4j.ProjCoordinate
;
import
org.xmlobjects.gml.model.geometry.AbstractGeometry
;
import
org.xmlobjects.gml.model.geometry.GeometricPositionList
;
import
org.xmlobjects.gml.model.geometry.GeometryProperty
;
import
org.xmlobjects.gml.model.geometry.primitives.AbstractRing
;
import
org.xmlobjects.gml.model.geometry.primitives.AbstractRingProperty
;
import
org.xmlobjects.gml.model.geometry.primitives.LinearRing
;
import
org.xmlobjects.gml.model.geometry.primitives.Triangle
;
import
org.xmlobjects.gml.model.geometry.primitives.TriangulatedSurface
;
import
de.hft.stuttgart.citygml.viewer.datastructure.Polygon
;
import
de.hft.stuttgart.citygml.viewer.datastructure.Ring
;
import
de.hft.stuttgart.citygml.viewer.math.Vector3d
;
public
class
FeatureMapper
extends
ObjectWalker
{
private
Color
groundColor
=
new
Color
(
0.9411765f
,
0.9019608f
,
0.54901963f
);
private
Color
roofColor
=
Color
.
RED
;
private
Color
doorColor
=
Color
.
ORANGE
;
private
Color
windowColor
=
new
Color
(
0.0f
,
0.5019608f
,
0.5019608f
);
private
Color
wallColor
=
Color
.
WHITE
;
private
Color
bridgeColor
=
new
Color
(
1.0f
,
0.49803922f
,
0.3137255f
);
private
Color
landColor
=
new
Color
(
0.64705884f
,
0.16470589f
,
0.16470589f
);
private
Color
transportationColor
=
new
Color
(
1.0f
,
1.0f
,
0.0f
);
private
Color
vegetationColor
=
new
Color
(
0.5647059f
,
0.93333334f
,
0.5647059f
);
private
Color
waterColor
=
new
Color
(
0.5294118f
,
0.80784315f
,
0.98039216f
);
private
ParserConfiguration
config
;
private
List
<
Polygon
>
lod1Polygons
;
private
List
<
Polygon
>
lod2Polygons
;
private
List
<
Polygon
>
lod3Polygons
;
private
List
<
Polygon
>
lod4Polygons
;
private
List
<
Polygon
>
currentPolygons
=
null
;
private
Ring
currentRing
;
private
Color
currentColor
;
private
ProjCoordinate
p1
=
new
ProjCoordinate
();
private
ProjCoordinate
p2
=
new
ProjCoordinate
();
public
FeatureMapper
(
ParserConfiguration
config
)
throws
IOException
{
try
(
FileReader
reader
=
new
FileReader
(
"color.properties"
))
{
Properties
props
=
new
Properties
();
props
.
load
(
reader
);
Color
parsedGroundColor
=
parseColor
(
props
.
getProperty
(
"groundColor"
));
if
(
parsedGroundColor
!=
null
)
{
groundColor
=
parsedGroundColor
;
}
Color
parsedRoofColor
=
parseColor
(
props
.
getProperty
(
"roofColor"
));
if
(
parsedRoofColor
!=
null
)
{
roofColor
=
parsedRoofColor
;
}
Color
parsedDoorColor
=
parseColor
(
props
.
getProperty
(
"doorColor"
));
if
(
parsedDoorColor
!=
null
)
{
doorColor
=
parsedDoorColor
;
}
Color
parsedWindowColor
=
parseColor
(
props
.
getProperty
(
"windowColor"
));
if
(
parsedWindowColor
!=
null
)
{
windowColor
=
parsedWindowColor
;
}
Color
parsedWallColor
=
parseColor
(
props
.
getProperty
(
"wallColor"
));
if
(
parsedWallColor
!=
null
)
{
wallColor
=
parsedWallColor
;
}
Color
parsedBridgeColor
=
parseColor
(
props
.
getProperty
(
"bridgeColor"
));
if
(
parsedBridgeColor
!=
null
)
{
bridgeColor
=
parsedBridgeColor
;
}
Color
parsedLandColor
=
parseColor
(
props
.
getProperty
(
"landColor"
));
if
(
parsedLandColor
!=
null
)
{
landColor
=
parsedLandColor
;
}
Color
parsedTransportationColor
=
parseColor
(
props
.
getProperty
(
"transportationColor"
));
if
(
parsedTransportationColor
!=
null
)
{
transportationColor
=
parsedTransportationColor
;
}
Color
parsedVegetationColor
=
parseColor
(
props
.
getProperty
(
"vegetationColor"
));
if
(
parsedVegetationColor
!=
null
)
{
vegetationColor
=
parsedVegetationColor
;
}
Color
parsedWaterColor
=
parseColor
(
props
.
getProperty
(
"waterColor"
));
if
(
parsedWaterColor
!=
null
)
{
waterColor
=
parsedWaterColor
;
}
}
this
.
config
=
config
;
lod1Polygons
=
new
ArrayList
<>();
lod2Polygons
=
new
ArrayList
<>();
lod3Polygons
=
new
ArrayList
<>();
lod4Polygons
=
new
ArrayList
<>();
}
private
Color
parseColor
(
String
colorString
)
{
if
(
colorString
==
null
)
{
return
null
;
}
try
{
String
[]
split
=
colorString
.
split
(
" "
);
float
r
=
Float
.
parseFloat
(
split
[
0
]);
float
g
=
Float
.
parseFloat
(
split
[
1
]);
float
b
=
Float
.
parseFloat
(
split
[
2
]);
return
new
Color
(
r
,
g
,
b
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
return
null
;
}
}
@Override
public
void
visit
(
org
.
xmlobjects
.
gml
.
model
.
geometry
.
primitives
.
Polygon
gmlPoly
)
{
if
(
currentPolygons
==
null
)
{
return
;
}
Polygon
viewerPoly
=
new
Polygon
(
currentColor
);
// parse rings
Ring
extRing
=
new
Ring
();
viewerPoly
.
setExteriorRing
(
extRing
);
mapRing
(
gmlPoly
.
getExterior
(),
extRing
);
if
(
gmlPoly
.
getInterior
()
!=
null
)
{
for
(
AbstractRingProperty
arp
:
gmlPoly
.
getInterior
())
{
if
(
arp
.
getObject
()
!=
null
)
{
Ring
innerRing
=
new
Ring
();
viewerPoly
.
addInteriorRing
(
innerRing
);
mapRing
(
arp
,
innerRing
);
}
}
}
currentPolygons
.
add
(
viewerPoly
);
}
@Override
public
void
visit
(
Triangle
triangle
)
{
if
(
currentPolygons
==
null
)
{
return
;
}
// triangle is only a special case of a polygon
// so use a polygon
Polygon
viewerPoly
=
new
Polygon
(
currentColor
);
// parse rings
Ring
extRing
=
new
Ring
();
viewerPoly
.
setExteriorRing
(
extRing
);
mapRing
(
triangle
.
getExterior
(),
extRing
);
currentPolygons
.
add
(
viewerPoly
);
}
private
void
mapRing
(
AbstractRingProperty
gmlRing
,
Ring
viewerRing
)
{
if
(
gmlRing
==
null
||
gmlRing
.
getObject
()
==
null
)
{
return
;
}
AbstractRing
ringGeometry
=
gmlRing
.
getObject
();
currentRing
=
viewerRing
;
// jump to LinearRing or Ring visit
ringGeometry
.
accept
(
this
);
}
@Override
public
void
visit
(
LinearRing
linearRing
)
{
if
(
linearRing
.
getControlPoints
()
!=
null
)
{
int
dimension
=
getDimension
(
linearRing
);
parseControlPoints
(
linearRing
.
getControlPoints
(),
dimension
);
}
}
private
int
getDimension
(
LinearRing
linearRing
)
{
int
dimension
=
3
;
if
(
linearRing
.
getSrsDimension
()
!=
null
)
{
dimension
=
linearRing
.
getSrsDimension
();
}
return
dimension
;
}
private
void
parseControlPoints
(
GeometricPositionList
controlPoints
,
int
dimension
)
{
List
<
Double
>
coords
=
controlPoints
.
toCoordinateList3D
();
switch
(
dimension
)
{
case
1
:
for
(
int
i
=
0
;
i
<
coords
.
size
();
i
++)
{
createVertex
(
coords
.
get
(
i
),
0
,
0
);
}
break
;
case
2
:
for
(
int
i
=
0
;
i
<
coords
.
size
();
i
=
i
+
2
)
{
createVertex
(
coords
.
get
(
i
+
0
),
coords
.
get
(
i
+
1
),
0
);
}
break
;
case
3
:
for
(
int
i
=
0
;
i
<
coords
.
size
();
i
=
i
+
3
)
{
createVertex
(
coords
.
get
(
i
+
0
),
coords
.
get
(
i
+
1
),
coords
.
get
(
i
+
2
));
}
break
;
default
:
throw
new
UnsupportedOperationException
(
"Cannot parse Coordinates with dimension:"
+
dimension
);
}
}
private
void
createVertex
(
double
x
,
double
y
,
double
z
)
{
// transform into utm, if available
BasicCoordinateTransform
trans
=
config
.
getTargetTransform
();
if
(
trans
!=
null
)
{
p1
.
setValue
(
x
,
y
);
trans
.
transform
(
p1
,
p2
);
x
=
p2
.
x
;
y
=
p2
.
y
;
}
Vector3d
v
=
new
Vector3d
(
x
,
y
,
z
);
currentRing
.
addPoint
(
v
);
}
@Override
public
void
visit
(
AbstractBuilding
ab
)
{
super
.
visit
(
ab
);
DeprecatedPropertiesOfAbstractBuilding
deprecatedProperties
=
ab
.
getDeprecatedProperties
();
parseAbstractGeometry
(
deprecatedProperties
.
getLod1MultiSurface
(),
lod1Polygons
,
wallColor
);
parseAbstractGeometry
(
ab
.
getLod2MultiSurface
(),
lod2Polygons
,
wallColor
);
parseAbstractGeometry
(
ab
.
getLod3MultiSurface
(),
lod3Polygons
,
wallColor
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod4MultiSurface
(),
lod4Polygons
,
wallColor
);
parseAbstractGeometry
(
ab
.
getLod1Solid
(),
lod1Polygons
,
wallColor
);
parseAbstractGeometry
(
ab
.
getLod2Solid
(),
lod2Polygons
,
wallColor
);
parseAbstractGeometry
(
ab
.
getLod3Solid
(),
lod3Polygons
,
wallColor
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod4Solid
(),
lod4Polygons
,
wallColor
);
}
@Override
public
void
visit
(
TINRelief
tinRelief
)
{
super
.
visit
(
tinRelief
);
if
(
tinRelief
.
getTin
()
==
null
||
tinRelief
.
getTin
().
getObject
()
==
null
)
{
return
;
}
TriangulatedSurface
object
=
tinRelief
.
getTin
().
getObject
();
currentPolygons
=
lod1Polygons
;
currentColor
=
landColor
;
object
.
accept
(
this
);
currentPolygons
=
null
;
currentColor
=
null
;
}
@Override
public
void
visit
(
WaterBody
wb
)
{
super
.
visit
(
wb
);
DeprecatedPropertiesOfWaterBody
deprecatedProperties
=
wb
.
getDeprecatedProperties
();
parseAbstractGeometry
(
deprecatedProperties
.
getLod1MultiSurface
(),
lod1Polygons
,
waterColor
);
parseAbstractGeometry
(
wb
.
getLod1Solid
(),
lod1Polygons
,
waterColor
);
parseAbstractGeometry
(
wb
.
getLod2Solid
(),
lod2Polygons
,
waterColor
);
parseAbstractGeometry
(
wb
.
getLod3Solid
(),
lod3Polygons
,
waterColor
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod4Solid
(),
lod4Polygons
,
waterColor
);
}
@Override
public
void
visit
(
PlantCover
pc
)
{
super
.
visit
(
pc
);
DeprecatedPropertiesOfPlantCover
deprecatedProperties
=
pc
.
getDeprecatedProperties
();
parseAbstractGeometry
(
deprecatedProperties
.
getLod1MultiSurface
(),
lod1Polygons
,
vegetationColor
);
parseAbstractGeometry
(
pc
.
getLod2MultiSurface
(),
lod2Polygons
,
vegetationColor
);
parseAbstractGeometry
(
pc
.
getLod3MultiSurface
(),
lod3Polygons
,
vegetationColor
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod4MultiSurface
(),
lod4Polygons
,
vegetationColor
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod1MultiSolid
(),
lod1Polygons
,
vegetationColor
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod2MultiSolid
(),
lod2Polygons
,
vegetationColor
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod3MultiSolid
(),
lod3Polygons
,
vegetationColor
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod4MultiSolid
(),
lod4Polygons
,
vegetationColor
);
}
@Override
public
void
visit
(
SolitaryVegetationObject
svo
)
{
super
.
visit
(
svo
);
DeprecatedPropertiesOfSolitaryVegetationObject
deprecatedProperties
=
svo
.
getDeprecatedProperties
();
parseAbstractGeometry
(
deprecatedProperties
.
getLod1Geometry
(),
lod1Polygons
,
vegetationColor
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod2Geometry
(),
lod2Polygons
,
vegetationColor
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod3Geometry
(),
lod3Polygons
,
vegetationColor
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod4Geometry
(),
lod4Polygons
,
vegetationColor
);
parseImplicitGeometry
(
svo
.
getLod1ImplicitRepresentation
(),
lod1Polygons
,
vegetationColor
);
parseImplicitGeometry
(
svo
.
getLod2ImplicitRepresentation
(),
lod2Polygons
,
vegetationColor
);
parseImplicitGeometry
(
svo
.
getLod3ImplicitRepresentation
(),
lod3Polygons
,
vegetationColor
);
parseImplicitGeometry
(
deprecatedProperties
.
getLod4ImplicitRepresentation
(),
lod4Polygons
,
vegetationColor
);
}
@Override
public
void
visit
(
AbstractThematicSurface
abs
)
{
super
.
visit
(
abs
);
Color
color
=
getBuildingSurfaceColor
(
abs
);
DeprecatedPropertiesOfAbstractThematicSurface
deprecatedProperties
=
abs
.
getDeprecatedProperties
();
parseAbstractGeometry
(
abs
.
getLod2MultiSurface
(),
lod2Polygons
,
color
);
parseAbstractGeometry
(
abs
.
getLod3MultiSurface
(),
lod3Polygons
,
color
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod4MultiSurface
(),
lod4Polygons
,
color
);
}
@Override
public
void
visit
(
LandUse
landUse
)
{
super
.
visit
(
landUse
);
DeprecatedPropertiesOfAbstractThematicSurface
deprecatedProperties
=
landUse
.
getDeprecatedProperties
();
parseAbstractGeometry
(
landUse
.
getLod1MultiSurface
(),
lod1Polygons
,
landColor
);
parseAbstractGeometry
(
landUse
.
getLod2MultiSurface
(),
lod2Polygons
,
landColor
);
parseAbstractGeometry
(
landUse
.
getLod3MultiSurface
(),
lod3Polygons
,
landColor
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod4MultiSurface
(),
lod4Polygons
,
landColor
);
}
@Override
public
void
visit
(
AuxiliaryTrafficArea
ata
)
{
super
.
visit
(
ata
);
DeprecatedPropertiesOfAbstractThematicSurface
deprecatedProperties
=
ata
.
getDeprecatedProperties
();
parseAbstractGeometry
(
ata
.
getLod2MultiSurface
(),
lod2Polygons
,
transportationColor
);
parseAbstractGeometry
(
ata
.
getLod3MultiSurface
(),
lod3Polygons
,
transportationColor
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod4MultiSurface
(),
lod4Polygons
,
transportationColor
);
}
@Override
public
void
visit
(
TrafficArea
ta
)
{
super
.
visit
(
ta
);
DeprecatedPropertiesOfAbstractThematicSurface
deprecatedProperties
=
ta
.
getDeprecatedProperties
();
parseAbstractGeometry
(
ta
.
getLod2MultiSurface
(),
lod2Polygons
,
transportationColor
);
parseAbstractGeometry
(
ta
.
getLod3MultiSurface
(),
lod3Polygons
,
transportationColor
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod4MultiSurface
(),
lod4Polygons
,
transportationColor
);
}
@Override
public
void
visit
(
TransportationComplex
tc
)
{
super
.
visit
(
tc
);
DeprecatedPropertiesOfAbstractTransportationSpace
deprecatedProperties
=
tc
.
getDeprecatedProperties
();
parseAbstractGeometry
(
deprecatedProperties
.
getLod1MultiSurface
(),
lod1Polygons
,
transportationColor
);
parseAbstractGeometry
(
tc
.
getLod2MultiSurface
(),
lod2Polygons
,
transportationColor
);
parseAbstractGeometry
(
tc
.
getLod3MultiSurface
(),
lod3Polygons
,
transportationColor
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod4MultiSurface
(),
lod4Polygons
,
transportationColor
);
}
private
Color
getBuildingSurfaceColor
(
AbstractThematicSurface
abs
)
{
if
(
abs
instanceof
RoofSurface
)
{
return
roofColor
;
}
if
(
abs
instanceof
GroundSurface
)
{
return
groundColor
;
}
return
wallColor
;
}
@Override
public
void
visit
(
AbstractFillingElement
ao
)
{
super
.
visit
(
ao
);
Color
color
=
getOpeningColor
(
ao
);
parseAbstractGeometry
(
ao
.
getLod1Solid
(),
lod1Polygons
,
color
);
parseAbstractGeometry
(
ao
.
getLod2Solid
(),
lod2Polygons
,
color
);
parseAbstractGeometry
(
ao
.
getLod3Solid
(),
lod3Polygons
,
color
);
parseAbstractGeometry
(
ao
.
getLod2MultiSurface
(),
lod2Polygons
,
color
);
parseAbstractGeometry
(
ao
.
getLod3MultiSurface
(),
lod3Polygons
,
color
);
parseImplicitGeometry
(
ao
.
getLod1ImplicitRepresentation
(),
lod1Polygons
,
color
);
parseImplicitGeometry
(
ao
.
getLod2ImplicitRepresentation
(),
lod2Polygons
,
color
);
parseImplicitGeometry
(
ao
.
getLod3ImplicitRepresentation
(),
lod3Polygons
,
color
);
}
private
Color
getOpeningColor
(
AbstractFillingElement
ao
)
{
if
(
ao
instanceof
Door
)
{
return
doorColor
;
}
if
(
ao
instanceof
Window
)
{
return
windowColor
;
}
return
wallColor
;
}
@Override
public
void
visit
(
AbstractBridge
ab
)
{
super
.
visit
(
ab
);
DeprecatedPropertiesOfAbstractBridge
deprecatedProperties
=
ab
.
getDeprecatedProperties
();
parseAbstractGeometry
(
deprecatedProperties
.
getLod1MultiSurface
(),
lod1Polygons
,
bridgeColor
);
parseAbstractGeometry
(
ab
.
getLod2MultiSurface
(),
lod2Polygons
,
bridgeColor
);
parseAbstractGeometry
(
ab
.
getLod3MultiSurface
(),
lod3Polygons
,
bridgeColor
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod4MultiSurface
(),
lod4Polygons
,
bridgeColor
);
parseAbstractGeometry
(
ab
.
getLod1Solid
(),
lod1Polygons
,
bridgeColor
);
parseAbstractGeometry
(
ab
.
getLod2Solid
(),
lod2Polygons
,
bridgeColor
);
parseAbstractGeometry
(
ab
.
getLod3Solid
(),
lod3Polygons
,
bridgeColor
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod4Solid
(),
lod4Polygons
,
bridgeColor
);
}
@Override
public
void
visit
(
BuildingInstallation
bi
)
{
super
.
visit
(
bi
);
DeprecatedPropertiesOfBuildingInstallation
deprecatedProperties
=
bi
.
getDeprecatedProperties
();
parseAbstractGeometry
(
deprecatedProperties
.
getLod2Geometry
(),
lod2Polygons
,
wallColor
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod3Geometry
(),
lod3Polygons
,
wallColor
);
parseAbstractGeometry
(
deprecatedProperties
.
getLod4Geometry
(),
lod4Polygons
,
wallColor
);
parseImplicitGeometry
(
bi
.
getLod2ImplicitRepresentation
(),
lod2Polygons
,
wallColor
);
parseImplicitGeometry
(
bi
.
getLod3ImplicitRepresentation
(),
lod3Polygons
,
wallColor
);
parseImplicitGeometry
(
deprecatedProperties
.
getLod4ImplicitRepresentation
(),
lod4Polygons
,
wallColor
);
}
private
void
parseImplicitGeometry
(
ImplicitGeometryProperty
irp
,
List
<
Polygon
>
polygons
,
Color
color
)
{
if
(
irp
==
null
||
irp
.
getObject
()
==
null
)
{
return
;
}
ImplicitGeometry
implicitGeometry
=
irp
.
getObject
();
parseAbstractGeometry
(
implicitGeometry
.
getRelativeGeometry
(),
polygons
,
color
);
}
private
void
parseAbstractGeometry
(
GeometryProperty
<?
extends
AbstractGeometry
>
geom
,
List
<
Polygon
>
polygons
,
Color
color
)
{
if
(
geom
==
null
||
geom
.
getObject
()
==
null
)
{
return
;
}
currentColor
=
color
;
currentPolygons
=
polygons
;
geom
.
getObject
().
accept
(
this
);
currentColor
=
null
;
currentPolygons
=
null
;
}
public
List
<
Polygon
>
getLod1Polygons
()
{
return
lod1Polygons
;
}
public
List
<
Polygon
>
getLod2Polygons
()
{
return
lod2Polygons
;
}
public
List
<
Polygon
>
getLod3Polygons
()
{
return
lod3Polygons
;
}
public
List
<
Polygon
>
getLod4Polygons
()
{
return
lod4Polygons
;
}
public
void
movePolygonsBy
(
Vector3d
center
)
{
movePolygonsBy
(
lod1Polygons
,
center
);
movePolygonsBy
(
lod2Polygons
,
center
);
movePolygonsBy
(
lod3Polygons
,
center
);
movePolygonsBy
(
lod4Polygons
,
center
);
}
private
void
movePolygonsBy
(
List
<
Polygon
>
polygons
,
Vector3d
center
)
{
for
(
Polygon
p
:
polygons
)
{
for
(
Vector3d
v
:
p
.
getExteriorRing
().
getVertices
())
{
movePointBy
(
v
,
center
);
}
for
(
Ring
r
:
p
.
getInteriorRings
())
{
for
(
Vector3d
v
:
r
.
getVertices
())
{
movePointBy
(
v
,
center
);
}
}
}
}
private
void
movePointBy
(
Vector3d
v
,
Vector3d
center
)
{
v
.
setX
(
v
.
getX
()
-
center
.
getX
());
v
.
setY
(
v
.
getY
()
-
center
.
getY
());
v
.
setZ
(
v
.
getZ
()
-
center
.
getZ
());
}
}
src/main/java/de/hft/stuttgart/citygml/viewer/parser/InputStreamListener.java
0 → 100644
View file @
0f66af82
/*-
* Copyright 2021 Hochschule für Technik Stuttgart
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
de.hft.stuttgart.citygml.viewer.parser
;
import
java.util.EventListener
;
/**
* Implementations of this listener will be informed about the (file) loading progress of ObservedInputStream
* instances. You have to register your implementation of this interface at the ObservedInputStream instance.
*
* @author Marcel Bruse
*/
public
interface
InputStreamListener
extends
EventListener
{
/**
* This method will be called by the observed input stream when a new chunk of bytes has been read.
*
* @param progress Should be a value between 0 and 1. 0 means no progress and 1 means loading finished.
*/
public
void
updateProgress
(
float
progress
);
}
src/main/java/de/hft/stuttgart/citygml/viewer/parser/LOD.java
0 → 100644
View file @
0f66af82
/*-
* Copyright 2021 Hochschule für Technik Stuttgart
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
de.hft.stuttgart.citygml.viewer.parser
;
public
enum
LOD
{
LOD_1
,
LOD_2
,
LOD_3
,
LOD_4
}
src/main/java/de/hft/stuttgart/citygml/viewer/parser/ObservedInputStream.java
0 → 100644
View file @
0f66af82
/*-
* Copyright 2021 Hochschule für Technik Stuttgart
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
de.hft.stuttgart.citygml.viewer.parser
;
import
java.io.BufferedInputStream
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.FileNotFoundException
;
import
java.io.FilterInputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.util.ArrayList
;
/**
* This ObservedInputStream will update its registered listeners about the reading process of the underlying file.
* Every time when the underlying input stream is read the registered listeners will be informed and updated with the
* new progress.
*
* @author Marcel Bruse
*/
public
class
ObservedInputStream
extends
FilterInputStream
{
/** List of registered progress listeners. */
private
ArrayList
<
InputStreamListener
>
listeners
=
new
ArrayList
<>();
/** The number of bytes of the file to be read. */
private
long
fileLength
;
/** The number of bytes read so far. */
private
long
location
;
/**
* Instantiates the ObservedInputStream with a given file handle.
*
* @param file The file that should be loaded.
* @throws FileNotFoundException If there is on file, you will get some of this.
*/
public
ObservedInputStream
(
File
file
)
throws
FileNotFoundException
{
super
(
new
BufferedInputStream
(
new
FileInputStream
(
file
)));
fileLength
=
file
.
length
();
}
public
ObservedInputStream
(
String
fileName
)
throws
FileNotFoundException
{
this
(
new
File
(
fileName
));
}
public
ObservedInputStream
(
InputStream
in
,
long
fileLength
)
{
super
(
new
BufferedInputStream
(
in
));
this
.
fileLength
=
fileLength
;
}
/**
* Calls all the registered listeners if the file loading process makes any progress.
* It calculates and passes the progress in percent.
*/
private
void
updateProgress
()
{
for
(
InputStreamListener
l
:
listeners
)
{
l
.
updateProgress
((
float
)
location
/
fileLength
);
}
}
/**
* Calls super and counts the number of read bytes.
*
* @see FilterInputStream
*/
@Override
public
int
read
()
throws
IOException
{
final
int
data
=
super
.
read
();
if
(
data
!=
-
1
)
{
location
++;
updateProgress
();
}
return
data
;
}
/**
* Calls super and counts the number of read bytes.
*
* @see FilterInputStream
*/
@Override
public
int
read
(
byte
[]
b
,
int
off
,
int
len
)
throws
IOException
{
final
int
byteCount
=
super
.
read
(
b
,
off
,
len
);
if
(
byteCount
!=
-
1
)
{
location
+=
byteCount
;
updateProgress
();
}
return
byteCount
;
}
/**
* Registers listeners. Every registered listener will get informed if the file loading process makes any
* progress.
*
* @param ps The progress listener to be registered.
*/
public
void
addListener
(
InputStreamListener
ps
)
{
listeners
.
add
(
ps
);
}
}
src/main/java/de/hft/stuttgart/citygml/viewer/parser/ParserConfiguration.java
0 → 100644
View file @
0f66af82
/*-
* Copyright 2021 Hochschule für Technik Stuttgart
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
de.hft.stuttgart.citygml.viewer.parser
;
import
java.io.Serializable
;
import
org.locationtech.proj4j.BasicCoordinateTransform
;
import
org.locationtech.proj4j.CRSFactory
;
import
org.locationtech.proj4j.CoordinateReferenceSystem
;
/**
* Container class to store the configuration needed to parse a file. Also
* contains information on transformation of vertices.
*
* @author Matthias Betz
*
*/
public
class
ParserConfiguration
implements
Serializable
{
private
static
final
long
serialVersionUID
=
6209047092991074661L
;
private
static
final
CRSFactory
CRS_FACTORY
=
new
CRSFactory
();
private
transient
BasicCoordinateTransform
targetTransform
=
null
;
private
transient
BasicCoordinateTransform
originalTransform
=
null
;
private
String
targetTransformString
;
private
String
originalTransformString
;
private
boolean
hasTransformation
=
false
;
public
void
setCoordinateSystem
(
CoordinateReferenceSystem
crs
,
CoordinateReferenceSystem
tgtCrs
)
{
if
(
crs
!=
null
&&
tgtCrs
!=
null
)
{
hasTransformation
=
true
;
targetTransformString
=
tgtCrs
.
getParameterString
();
originalTransformString
=
crs
.
getParameterString
();
targetTransform
=
new
BasicCoordinateTransform
(
crs
,
tgtCrs
);
originalTransform
=
new
BasicCoordinateTransform
(
tgtCrs
,
crs
);
}
}
public
BasicCoordinateTransform
getTargetTransform
()
{
if
(
hasTransformation
&&
targetTransform
==
null
)
{
createCoordinateTransforms
();
}
return
targetTransform
;
}
private
void
createCoordinateTransforms
()
{
CoordinateReferenceSystem
tgtCrs
=
null
;
CoordinateReferenceSystem
crs
=
null
;
synchronized
(
CRS_FACTORY
)
{
tgtCrs
=
CRS_FACTORY
.
createFromParameters
(
"Target"
,
targetTransformString
);
crs
=
CRS_FACTORY
.
createFromParameters
(
"Original"
,
originalTransformString
);
}
targetTransform
=
new
BasicCoordinateTransform
(
crs
,
tgtCrs
);
originalTransform
=
new
BasicCoordinateTransform
(
tgtCrs
,
crs
);
}
public
BasicCoordinateTransform
getOriginalTransform
()
{
if
(
hasTransformation
&&
originalTransform
==
null
)
{
createCoordinateTransforms
();
}
return
originalTransform
;
}
}
src/main/resources/fragment.frag
0 → 100644
View file @
0f66af82
#version 330
// Incoming interpolated (between vertices) color.
in
vec3
interpolatedColor
;
// Outgoing final color.
layout
(
location
=
0
)
out
vec4
outputColor
;
void
main
()
{
// We simply pad the interpolatedColor
outputColor
=
vec4
(
interpolatedColor
,
1
);
}
\ No newline at end of file
src/main/resources/vertex.vert
0 → 100644
View file @
0f66af82
#version 330
// Incoming vertex position, Model Space.
layout
(
location
=
0
)
in
vec3
position
;
// Incoming vertex color.
layout
(
location
=
1
)
in
vec3
color
;
// Projection, view and model matrix.
uniform
mat4
projViewModel
;
// Outgoing color.
out
vec3
interpolatedColor
;
void
main
()
{
// Normally gl_Position is in Clip Space and we calculate it by multiplying together all the matrices
gl_Position
=
projViewModel
*
vec4
(
position
,
1
);
// We assign the color to the outgoing variable.
interpolatedColor
=
color
;
}
\ No newline at end of file
Prev
1
2
Next
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