aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetri Hienonen <petri.hienonen@gmail.com>2025-11-13 21:25:00 +0200
committerPetri Hienonen <petri.hienonen@gmail.com>2025-11-13 21:30:59 +0200
commitc06dccd86e8cd40fb98cbe0b734428d60ab39e32 (patch)
tree00a06764550ec07a2905439c9aa726d234a1dac1
parente92bf0544d423f0ab2ff7801f02b17f863a97387 (diff)
downloadhousing-c06dccd86e8cd40fb98cbe0b734428d60ab39e32.tar.zst
Simplify
-rw-r--r--app/map.js136
1 files changed, 33 insertions, 103 deletions
diff --git a/app/map.js b/app/map.js
index 5e69d4e..d27a009 100644
--- a/app/map.js
+++ b/app/map.js
@@ -1,14 +1,5 @@
-import { Bounds, Feature, FeatureCollection, LineString, MultiLineString, Point } from "geom";
-import {
- AreaParam,
- Collection,
- District,
- House,
- HouseParameter,
- StatisticalArea,
- TrainStation,
- TrainTracks,
-} from "models";
+import { Bounds, Feature, LineString, MultiLineString, Point } from "geom";
+import { AreaParam, Collection, District, House, HouseParameter, StatisticalArea } from "models";
import { Svg, SvgOptions } from "svg";
/**
@@ -68,8 +59,6 @@ export class MapEl {
#collection = null;
/** @type {SVGGElement|null} */
#housesGroup = null;
- /** @type {SVGGElement|null} */
- #statAreasGroup = null;
/** @type {Function} */
#onHouseClick;
/** @type {Function} */
@@ -196,14 +185,14 @@ export class MapEl {
/**
* Initialize map with empty content
- * @param {Collection} collection
+ * @param {Collection} c
* @param {HouseParameter} houseParameter
* @param {AreaParam} areaParameter
* @returns {SVGSVGElement}
*/
- initialize(collection, houseParameter, areaParameter) {
- this.#collection = collection;
- this.#setInitialViewBox(District.bounds(collection.districts));
+ initialize(c, houseParameter, areaParameter) {
+ this.#collection = c;
+ this.#setInitialViewBox(District.bounds(c.districts));
const transformGroup = Svg.g(
new SvgOptions({
attributes: { transform: "scale(1, -1)" },
@@ -214,8 +203,8 @@ export class MapEl {
"pointer-events": "none",
},
children: [
- ...MapEl.#getStatisticalAreas(collection.statisticalAreas, areaParameter),
- ...MapEl.#getStatisticalAreaLabels(collection.statisticalAreas),
+ ...MapEl.#getStatisticalAreas(c.statisticalAreas, areaParameter),
+ ...MapEl.#getStatisticalAreaLabels(c.statisticalAreas),
],
id: "statistical-areas",
}),
@@ -227,8 +216,16 @@ export class MapEl {
"stroke-width": "0.0005",
},
children: [
- ...MapEl.#getCoastLine(collection.coastLine),
- ...MapEl.#getRoads(collection.mainRoads),
+ ...c.coastLine.features
+ .map((x) =>
+ MapEl.#renderLineFeature(x, {
+ stroke: "rgba(25, 25, 112, 1)",
+ }),
+ )
+ .filter((x) => x !== null),
+ ...c.mainRoads.features
+ .map((x) => MapEl.#renderLineFeature(x))
+ .filter((x) => x !== null),
],
id: "background",
}),
@@ -241,7 +238,7 @@ export class MapEl {
stroke: "rgba(255, 68, 68, 1)",
"stroke-width": "0.001",
},
- children: MapEl.#getTracks(collection.trainTracks),
+ children: c.trainTracks.map((track) => Svg.path(track.lineString)),
id: "train-tracks",
}),
),
@@ -254,7 +251,7 @@ export class MapEl {
stroke: "rgba(204, 0, 0, 1)",
"stroke-width": "0.001",
},
- children: MapEl.#getStations(collection.trainStations),
+ children: c.trainStations.map((station) => Svg.circle(station.polygon.centroid())),
id: "train-stations",
}),
),
@@ -267,7 +264,7 @@ export class MapEl {
stroke: "rgba(255, 255, 0, 1)",
"stroke-width": "0.001",
},
- children: MapEl.#getStations(collection.lightRailStops),
+ children: c.lightRailStops.map((stop) => Svg.circle(stop.polygon.centroid())),
id: "light_rail",
}),
),
@@ -280,7 +277,7 @@ export class MapEl {
stroke: "rgba(0, 255, 0, 1)",
"stroke-width": "0.001",
},
- children: MapEl.#renderFeatures(collection.jokerTramStops),
+ children: c.jokerTramStops.features.map((x) => Svg.circle(x.geometry)),
id: "tram-stations",
}),
),
@@ -288,8 +285,8 @@ export class MapEl {
new SvgOptions({
attributes: {},
children: [
- ...MapEl.#getDistricts(collection.districts),
- ...MapEl.#getDistrictLabels(collection.districts),
+ ...MapEl.#getDistricts(c.districts),
+ ...MapEl.#getDistrictLabels(c.districts),
],
id: "districts",
}),
@@ -303,7 +300,7 @@ export class MapEl {
"stroke-linecap": "butt",
"stroke-width": "0.001",
},
- children: this.#getHouses(collection.houses, houseParameter),
+ children: this.#getHouses(c.houses, houseParameter),
id: "houses",
}),
),
@@ -312,10 +309,10 @@ export class MapEl {
}),
);
this.svg.append(transformGroup);
-
- const coastBounds = Bounds.union(collection.coastLine.features.map((f) => f.geometry.bounds()));
- const roadBounds = Bounds.union(collection.mainRoads.features.map((f) => f.geometry.bounds()));
- this.#fullBounds = Bounds.union([coastBounds, roadBounds]);
+ this.#fullBounds = Bounds.union([
+ Bounds.union(c.coastLine.features.map((f) => f.geometry.bounds())),
+ Bounds.union(c.mainRoads.features.map((f) => f.geometry.bounds())),
+ ]);
return this.svg;
}
@@ -593,7 +590,7 @@ export class MapEl {
e.preventDefault();
const delta = -e.deltaY;
- const scaleFactor = delta > 0 ? 0.8 : 1.25;
+ const scaleFactor = delta > 0 ? 0.9 : 1.15;
const ctm = svg.getScreenCTM();
if (ctm) {
@@ -789,81 +786,14 @@ export class MapEl {
}
/**
- * @param {FeatureCollection} roads
- */
- static #getRoads(roads) {
- return roads.features
- .map((feature) =>
- MapEl.#renderLineFeature(feature, {
- stroke: "rgba(0, 0, 0, 1)",
- }),
- )
- .filter((x) => x !== null);
- }
-
- /**
- * @param {FeatureCollection} coastline
- */
- static #getCoastLine(coastline) {
- return coastline.features
- .map((feature) =>
- MapEl.#renderLineFeature(feature, {
- stroke: "rgba(25, 25, 112, 1)",
- }),
- )
- .filter((x) => x !== null);
- }
-
- /**
- * @param {FeatureCollection} c
- */
- static #renderFeatures(c) {
- return c.features
- .map((feature) => {
- if (feature.geometry instanceof MultiLineString) {
- return Svg.path(new LineString(feature.geometry.simplify(30).coordinates.flat()));
- } else if (feature.geometry instanceof LineString) {
- return Svg.path(feature.geometry.simplify(30));
- } else if (feature.geometry instanceof Point) {
- return Svg.circle(feature.geometry);
- }
- return null;
- })
- .filter((x) => x !== null);
- }
-
- /**
- * Set train infrastructure data
- * @param {TrainTracks[]} tracks
- */
- static #getTracks(tracks) {
- return tracks.map((track) => {
- return Svg.path(track.lineString, new SvgOptions({}));
- });
- }
-
- /**
- * @param {TrainStation[]} stations
- */
- static #getStations(stations) {
- return stations.map((station) => {
- const exterior = station.polygon.getExterior();
- const point = new Point(exterior[0][0], exterior[0][1]);
- return Svg.circle(
- point,
- new SvgOptions({
- attributes: {},
- }),
- );
- });
- }
-
- /**
* Update house colors based on current color parameter
* @param {HouseParameter} param
*/
updateHousesColor(param) {
const values = this.#collection?.houses.map((house) => house.get(param)).sort();
+ if (!values) {
+ return;
+ }
const range = { max: Math.max(...values), min: Math.min(...values) };
switch (param) {
case HouseParameter.price: // No prices available for each house. Take some from the bottom