Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
sektorsim
CityGML Server
Commits
606a51e3
Commit
606a51e3
authored
Jul 16, 2026
by
Matthias Betz
Browse files
remove unused test resource
parent
e910bf8c
Changes
1
Show whitespace changes
Inline
Side-by-side
src/test/resources/index_geo.html
deleted
100644 → 0
View file @
e910bf8c
<!DOCTYPE html>
<html
lang=
"en"
>
<head>
<meta
charset=
"utf-8"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
>
<title>
Leaflet Polygon Selector (Background Download)
</title>
<link
rel=
"stylesheet"
href=
"https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
integrity=
"sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
crossorigin=
""
/>
<link
rel=
"stylesheet"
href=
"https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.css"
/>
<script
src=
"https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
integrity=
"sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
crossorigin=
""
></script>
<script
src=
"https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.js"
></script>
<style>
/* Basic CSS to make the map fullscreen */
html
,
body
{
height
:
100%
;
margin
:
0
;
padding
:
0
;
overflow
:
hidden
;
/* Prevent scrollbars on body */
}
#map
{
width
:
100%
;
height
:
100%
;
}
/* Style for the WKT output box */
#wkt-output
{
position
:
absolute
;
bottom
:
70px
;
/* Position above the download button */
right
:
10px
;
background
:
rgba
(
255
,
255
,
255
,
0.85
);
padding
:
5px
10px
;
border
:
1px
solid
#ccc
;
border-radius
:
4px
;
z-index
:
1000
;
/* Ensure it's above the map */
font-family
:
monospace
;
font-size
:
0.8em
;
max-width
:
300px
;
max-height
:
150px
;
overflow-y
:
auto
;
word-wrap
:
break-word
;
display
:
none
;
/* Hidden by default */
}
/* Simple instruction text */
#instructions
{
position
:
absolute
;
top
:
10px
;
left
:
50px
;
/* Position relative to default zoom controls */
background
:
rgba
(
255
,
255
,
255
,
0.85
);
padding
:
5px
10px
;
border
:
1px
solid
#ccc
;
border-radius
:
4px
;
z-index
:
1000
;
font-family
:
sans-serif
;
font-size
:
0.9em
;
}
/* Style for the Download button */
#download-button
{
position
:
absolute
;
bottom
:
30px
;
right
:
10px
;
z-index
:
1000
;
padding
:
8px
15px
;
cursor
:
pointer
;
background-color
:
#4CAF50
;
/* Green */
color
:
white
;
border
:
none
;
border-radius
:
4px
;
font-size
:
1em
;
display
:
none
;
/* Hidden by default */
}
#download-button
:hover
{
background-color
:
#45a049
;
}
#download-button
:disabled
{
background-color
:
#cccccc
;
cursor
:
not-allowed
;
}
/* Style for the Clear button */
#clear-button
{
position
:
absolute
;
bottom
:
30px
;
right
:
160px
;
/* Adjusted position */
z-index
:
1000
;
padding
:
8px
15px
;
cursor
:
pointer
;
background-color
:
#f44336
;
/* Red */
color
:
white
;
border
:
none
;
border-radius
:
4px
;
font-size
:
1em
;
display
:
none
;
/* Hidden by default, show while drawing or finished*/
}
#clear-button
:hover
{
background-color
:
#da190b
;
}
/* Ensure geocoder input is usable */
.leaflet-control-geocoder
{
z-index
:
1001
!important
;
/* Ensure search is above other elements */
}
.leaflet-control-geocoder-form
input
{
min-width
:
200px
;
/* Make search input wider */
}
#searchContainer
{
position
:
absolute
;
top
:
10px
;
left
:
50%
;
transform
:
translateX
(
-50%
);
/* horizontally center */
z-index
:
1000
;
background
:
rgba
(
255
,
255
,
255
,
0.9
);
padding
:
5px
10px
;
border
:
1px
solid
#ccc
;
border-radius
:
4px
;
display
:
flex
;
gap
:
8px
;
align-items
:
center
;
}
#searchContainer
input
{
padding
:
4px
8px
;
font-size
:
0.9em
;
}
#searchContainer
button
{
padding
:
5px
10px
;
font-size
:
0.9em
;
cursor
:
pointer
;
}
</style>
</head>
<body>
<div
id=
"searchContainer"
>
<input
id=
"searchInput"
type=
"text"
placeholder=
"Enter ID to search"
>
<button
id=
"searchButton"
>
Search
</button>
</div>
<div
id=
"map"
></div>
<div
id=
"instructions"
>
Click map to start drawing polygon.
</div>
<div
id=
"wkt-output"
></div>
<button
id=
"download-button"
>
Download Data
</button>
<button
id=
"clear-button"
>
Clear Polygon
</button>
<script>
const
qaColors
=
{
'
QA1
'
:
{
color
:
'
#e41a1c
'
,
fillColor
:
'
#fbb4ae
'
,
text
:
'
QA1 (EFH/2FA)
'
},
'
QA2
'
:
{
color
:
'
#377eb8
'
,
fillColor
:
'
#b3cde3
'
,
text
:
'
QA2 (Mehrgeschossig)
'
},
'
QA3
'
:
{
color
:
'
#4daf4a
'
,
fillColor
:
'
#ccebc5
'
,
text
:
'
QA3 (Innenstadt)
'
},
'
QA4
'
:
{
color
:
'
#984ea3
'
,
fillColor
:
'
#decbe4
'
,
text
:
'
QA4 (Großer Wohnungsbau)
'
},
'
QA5
'
:
{
color
:
'
#ff7f00
'
,
fillColor
:
'
#fed9a6
'
,
text
:
'
QA5 (Wohn- Geschäfts- Bürozentrum)
'
},
'
QA6
'
:
{
color
:
'
#a65628
'
,
fillColor
:
'
#fddbc7
'
,
text
:
'
QA6 (Stadtnahes Gewerbe)
'
},
'
QA7
'
:
{
color
:
'
#f781bf
'
,
fillColor
:
'
#fbb5d3
'
,
text
:
'
QA7 (Industrie- und Gewerbepark)
'
}
};
// Wait for the DOM to be fully loaded
document
.
addEventListener
(
'
DOMContentLoaded
'
,
function
()
{
// --- Configuration ---
const
SERVER_BASE_URL
=
"
https://citygml.hft-stuttgart.de/citygml
"
;
// Define server URL here
const
DEFAULT_FILENAME
=
"
data.gml
"
;
// Fallback filename for download
// --- Initialize Map ---
const
map
=
L
.
map
(
'
map
'
,
{
keyboard
:
true
}).
fitBounds
([[
47.53564
,
7.52587
],
[
49.78976
,
10.4856
]]);
// Center on BW
const
featureLayers
=
{};
let
highlightedLayer
=
null
;
// --- Load GeoJSON file ---
fetch
(
'
test.geojson
'
)
.
then
(
response
=>
response
.
json
())
.
then
(
data
=>
{
// Add the GeoJSON layer
const
geoJsonLayer
=
L
.
geoJSON
(
data
,
{
style
:
feature
=>
{
const
qa
=
feature
.
properties
.
Quarterarchetype
;
const
colors
=
qaColors
[
qa
]
||
{
color
:
'
gray
'
,
fillColor
:
'
lightgray
'
};
return
{
color
:
colors
.
color
,
weight
:
2
,
fillColor
:
colors
.
fillColor
,
fillOpacity
:
0.5
};
},
onEachFeature
:
function
(
feature
,
layer
)
{
// Save each layer by its ID property
if
(
feature
.
properties
&&
feature
.
properties
.
id
)
{
featureLayers
[
feature
.
properties
.
id
]
=
layer
;
}
// Optional: bind popup to show properties
if
(
feature
.
properties
)
{
layer
.
bindPopup
(
"
ID:
"
+
feature
.
properties
.
id
+
"
<br>Archetype:
"
+
feature
.
properties
.
Quarterarchetype
);
}
}
}).
addTo
(
map
);
map
.
fitBounds
(
geoJsonLayer
.
getBounds
());
// --- Add a Legend ---
const
legend
=
L
.
control
({
position
:
'
bottomleft
'
});
legend
.
onAdd
=
function
(
map
)
{
const
div
=
L
.
DomUtil
.
create
(
'
div
'
,
'
info legend
'
);
div
.
style
.
background
=
'
white
'
;
div
.
style
.
padding
=
'
8px
'
;
div
.
style
.
border
=
'
1px solid #ccc
'
;
div
.
style
.
borderRadius
=
'
4px
'
;
div
.
style
.
fontSize
=
'
0.9em
'
;
div
.
innerHTML
+=
'
<strong>QA Legend</strong><br>
'
;
for
(
const
qa
in
qaColors
)
{
const
{
fillColor
,
color
,
text
}
=
qaColors
[
qa
];
div
.
innerHTML
+=
`<i style="
background:
${
fillColor
}
;
border:2px solid
${
color
}
;
display:inline-block;
width:18px;
height:18px;
margin-right:6px;
vertical-align:middle;">
</i>
${
text
}
<br>`
;
}
return
div
;
};
legend
.
addTo
(
map
);
})
.
catch
(
err
=>
console
.
error
(
'
Error loading GeoJSON:
'
,
err
));
document
.
getElementById
(
'
searchButton
'
).
addEventListener
(
'
click
'
,
()
=>
{
const
value
=
document
.
getElementById
(
'
searchInput
'
).
value
.
trim
();
// Reset any previous highlight
if
(
highlightedLayer
)
{
geoJsonLayer
.
resetStyle
(
highlightedLayer
);
highlightedLayer
=
null
;
}
if
(
value
&&
featureLayers
[
value
])
{
highlightedLayer
=
featureLayers
[
value
];
// Highlight style
highlightedLayer
.
setStyle
({
color
:
'
yellow
'
,
weight
:
4
,
fillColor
:
'
gold
'
,
fillOpacity
:
0.7
});
// Bring to front (useful for polygons)
if
(
highlightedLayer
.
bringToFront
)
{
highlightedLayer
.
bringToFront
();
}
// Zoom to the layer
map
.
fitBounds
(
highlightedLayer
.
getBounds
());
// Optionally open its popup
highlightedLayer
.
openPopup
();
}
else
{
alert
(
'
No feature found with ID =
'
+
value
);
}
});
L
.
tileLayer
(
'
https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png
'
,
{
attribution
:
'
© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors
'
}).
addTo
(
map
);
// --- Add Geocoder (Search) Control ---
L
.
Control
.
geocoder
({
defaultMarkGeocode
:
true
}).
addTo
(
map
);
// --- State Variables ---
let
drawingEnabled
=
true
;
let
points
=
[];
let
tempMarkers
=
[];
let
tempPolyline
=
null
;
let
finalPolygon
=
null
;
let
firstMarker
=
null
;
let
currentWktString
=
null
;
// Store WKT for download button
// --- DOM Element References ---
const
wktOutputDiv
=
document
.
getElementById
(
'
wkt-output
'
);
const
downloadButton
=
document
.
getElementById
(
'
download-button
'
);
const
clearButton
=
document
.
getElementById
(
'
clear-button
'
);
const
instructionsDiv
=
document
.
getElementById
(
'
instructions
'
);
// --- Helper Functions ---
function
getFilenameFromHeader
(
header
)
{
if
(
!
header
)
return
null
;
// Simple regex for filename="..."; handles quotes, case-insensitive
const
match
=
header
.
match
(
/filename
\s
*=
\s
*"
?([^
"
]
+
)
"
?
/i
);
return
match
&&
match
[
1
]
?
match
[
1
]
:
null
;
}
function
updateInstructions
()
{
if
(
drawingEnabled
)
{
if
(
points
.
length
===
0
)
{
instructionsDiv
.
textContent
=
'
Click map to start drawing polygon.
'
;
}
else
if
(
points
.
length
<
3
)
{
instructionsDiv
.
textContent
=
`Points:
${
points
.
length
}
. Add
${
3
-
points
.
length
}
more point(s). Click first marker to close (min 3 points).`
;
}
else
{
instructionsDiv
.
textContent
=
`Points:
${
points
.
length
}
. Click first marker or add more points.`
;
}
}
else
{
instructionsDiv
.
textContent
=
'
Polygon finalized. Click Download or Clear.
'
;
}
}
function
resetDrawing
()
{
drawingEnabled
=
true
;
points
=
[];
currentWktString
=
null
;
tempMarkers
.
forEach
(
marker
=>
map
.
removeLayer
(
marker
));
tempMarkers
=
[];
if
(
firstMarker
)
{
firstMarker
.
off
(
'
click
'
);
// Remove specific listener
firstMarker
=
null
;
}
if
(
tempPolyline
)
{
map
.
removeLayer
(
tempPolyline
);
tempPolyline
=
null
;
}
if
(
finalPolygon
)
{
map
.
removeLayer
(
finalPolygon
);
finalPolygon
=
null
;
}
wktOutputDiv
.
style
.
display
=
'
none
'
;
wktOutputDiv
.
textContent
=
''
;
downloadButton
.
style
.
display
=
'
none
'
;
downloadButton
.
disabled
=
false
;
// Re-enable button
downloadButton
.
textContent
=
'
Download Data
'
;
// Reset button text
clearButton
.
style
.
display
=
'
none
'
;
updateInstructions
();
console
.
log
(
"
Drawing reset.
"
);
}
function
finalizePolygon
()
{
if
(
points
.
length
<
3
)
return
;
console
.
log
(
"
Finalizing polygon...
"
);
drawingEnabled
=
false
;
// Remove temporary items
tempMarkers
.
forEach
(
marker
=>
map
.
removeLayer
(
marker
));
tempMarkers
=
[];
if
(
tempPolyline
)
{
map
.
removeLayer
(
tempPolyline
);
tempPolyline
=
null
;
}
if
(
firstMarker
)
{
firstMarker
.
off
(
'
click
'
);
firstMarker
=
null
;
// Ref only needed during drawing
}
if
(
finalPolygon
)
map
.
removeLayer
(
finalPolygon
);
finalPolygon
=
L
.
polygon
(
points
,
{
color
:
'
blue
'
}).
addTo
(
map
);
// Generate and store WKT
let
wktCoords
=
points
.
map
(
p
=>
`
${
p
.
lng
}
${
p
.
lat
}
`
);
wktCoords
.
push
(
`
${
points
[
0
].
lng
}
${
points
[
0
].
lat
}
`
);
// Close ring
currentWktString
=
`POLYGON((
${
wktCoords
.
join
(
'
,
'
)}
))`
;
// Store for download
// Display WKT
wktOutputDiv
.
textContent
=
`WKT (WGS84):\n
${
currentWktString
}
`
;
wktOutputDiv
.
style
.
display
=
'
block
'
;
// Show buttons
downloadButton
.
style
.
display
=
'
block
'
;
clearButton
.
style
.
display
=
'
block
'
;
updateInstructions
();
}
// --- Event Listeners ---
// Map Click: Add points
map
.
on
(
'
click
'
,
function
(
e
)
{
if
(
!
drawingEnabled
)
return
;
const
latlng
=
e
.
latlng
;
points
.
push
(
latlng
);
if
(
points
.
length
>
0
)
{
clearButton
.
style
.
display
=
'
block
'
;
}
const
newMarker
=
L
.
marker
(
latlng
).
addTo
(
map
);
tempMarkers
.
push
(
newMarker
);
if
(
points
.
length
===
1
)
{
firstMarker
=
newMarker
;
// Store reference to the first marker
// Add the specific click listener for closing
firstMarker
.
on
(
'
click
'
,
function
(
ev
)
{
L
.
DomEvent
.
stopPropagation
(
ev
);
// Prevent map click
if
(
drawingEnabled
&&
points
.
length
>=
3
)
{
finalizePolygon
();
}
else
if
(
drawingEnabled
)
{
console
.
log
(
"
Click on first marker, but not enough points (<3).
"
);
// Optional: Provide user feedback here
}
});
}
if
(
tempPolyline
)
map
.
removeLayer
(
tempPolyline
);
if
(
points
.
length
>
1
)
{
tempPolyline
=
L
.
polyline
(
points
,
{
color
:
'
red
'
,
weight
:
2
,
dashArray
:
'
5, 5
'
}).
addTo
(
map
);
}
updateInstructions
();
});
// Download Button Click: Fetch data and trigger download
downloadButton
.
addEventListener
(
'
click
'
,
async
function
()
{
if
(
!
currentWktString
)
{
console
.
error
(
"
Download clicked, but no WKT available.
"
);
return
;
}
const
encodedWkt
=
encodeURIComponent
(
currentWktString
);
// Correctly escapes () etc.
const
fullUrl
=
`
${
SERVER_BASE_URL
}
?wktPolygon=
${
encodedWkt
}
`
;
console
.
log
(
"
Requesting data from:
"
,
fullUrl
);
downloadButton
.
disabled
=
true
;
downloadButton
.
textContent
=
'
Downloading...
'
;
try
{
const
response
=
await
fetch
(
fullUrl
);
if
(
!
response
.
ok
)
{
// Handle HTTP errors (e.g., 404, 500)
throw
new
Error
(
`HTTP error! status:
${
response
.
status
}
${
response
.
statusText
}
`
);
}
// Get data as a Blob
const
blob
=
await
response
.
blob
();
// Determine filename
const
contentDisposition
=
response
.
headers
.
get
(
'
Content-Disposition
'
);
const
filename
=
getFilenameFromHeader
(
contentDisposition
)
||
DEFAULT_FILENAME
;
// Create a temporary link to trigger download
const
tempLink
=
document
.
createElement
(
'
a
'
);
const
objectUrl
=
URL
.
createObjectURL
(
blob
);
tempLink
.
href
=
objectUrl
;
tempLink
.
download
=
filename
;
// Set the desired filename
document
.
body
.
appendChild
(
tempLink
);
// Append necessary for Firefox
tempLink
.
click
();
// Simulate click
// Cleanup
document
.
body
.
removeChild
(
tempLink
);
URL
.
revokeObjectURL
(
objectUrl
);
console
.
log
(
`Download triggered for file:
${
filename
}
`
);
downloadButton
.
textContent
=
'
Download Complete
'
;
// Give feedback
}
catch
(
error
)
{
console
.
error
(
"
Download failed:
"
,
error
);
alert
(
`Failed to download data:
${
error
.
message
}
`
);
// Notify user
downloadButton
.
textContent
=
'
Download Failed
'
;
// Give feedback
}
finally
{
// Re-enable button after a delay, or keep it as 'Complete'/'Failed'
// For simplicity, let's re-enable and reset text on clear/new polygon.
// If keeping status, disable clear until download complete/failed?
// Let's just allow clear anytime.
// Reset button state after a small delay to show status
setTimeout
(()
=>
{
if
(
!
drawingEnabled
)
{
// Only reset if still in finalized state
downloadButton
.
disabled
=
false
;
downloadButton
.
textContent
=
'
Download Data
'
;
}
},
3000
);
// Reset text after 3 seconds
}
});
// Clear Button Click
clearButton
.
addEventListener
(
'
click
'
,
function
()
{
console
.
log
(
"
Clear button clicked.
"
);
resetDrawing
();
});
// Optional: Reset on double-click (if not drawing)
map
.
on
(
'
dblclick
'
,
function
(
e
)
{
if
(
!
drawingEnabled
)
{
resetDrawing
();
}
});
// --- Initial State ---
updateInstructions
();
});
// End DOMContentLoaded
</script>
</body>
</html>
\ No newline at end of file
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