Skip to content

Commit c0960f0

Browse files
perryr16Ross Perrykflemin
authored
Add footprint to detail and list map (#5113)
* footprint on detail * footprint on list map --------- Co-authored-by: Ross Perry <ross.perry@Rosss-MacBook-Pro-2.local> Co-authored-by: Katherine Fleming <2205659+kflemin@users.noreply.github.com>
1 parent 694cee2 commit c0960f0

File tree

4 files changed

+87
-98
lines changed

4 files changed

+87
-98
lines changed

seed/static/seed/js/controllers/inventory_detail_map_controller.js

Lines changed: 32 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ angular.module('SEED.controller.inventory_detail_map', []).controller('inventory
3939
const init = () => {
4040
$scope.bounding_box = $scope.item_state.bounding_box.replace(/^SRID=\d+;/, '');
4141
$scope.centroid = $scope.item_state.centroid.replace(/^SRID=\d+;/, '');
42+
const footprint = $scope.item_state.property_footprint || $scope.item_state.taxlot_footprint;
43+
$scope.footprint = footprint?.replace(/^SRID=\d+;/, '');
4244

4345
// store a mapping of layers z-index and visibility
4446
$scope.layers = {};
@@ -49,13 +51,15 @@ angular.module('SEED.controller.inventory_detail_map', []).controller('inventory
4951
$scope.layers.building_centroid_layer = { zIndex: 4, visible: 1 };
5052
$scope.layers.taxlot_bb_layer = { zIndex: 5, visible: 0 };
5153
$scope.layers.taxlot_centroid_layer = { zIndex: 6, visible: 0 };
54+
$scope.layers.footprint = { zIndex: 7, visible: 1 };
5255
} else {
5356
// taxlots
5457
$scope.layers.points_layer = { zIndex: 2, visible: 1 };
5558
$scope.layers.building_bb_layer = { zIndex: 3, visible: 0 };
5659
$scope.layers.building_centroid_layer = { zIndex: 4, visible: 0 };
5760
$scope.layers.taxlot_bb_layer = { zIndex: 5, visible: 1 };
5861
$scope.layers.taxlot_centroid_layer = { zIndex: 6, visible: 1 };
62+
$scope.layers.footprint = { zIndex: 7, visible: 1 };
5963
}
6064

6165
// Map
@@ -64,91 +68,35 @@ angular.module('SEED.controller.inventory_detail_map', []).controller('inventory
6468
zIndex: $scope.layers.base_layer.zIndex // Note: This is used for layer toggling.
6569
});
6670

67-
// This uses the bounding box instead of the lat/long. See BuildingPoint function in inventory_map_controller for reference
68-
const buildingBoundingBox = () => {
69-
const format = new ol.format.WKT();
70-
71-
const feature = format.readFeature($scope.bounding_box, {
72-
dataProjection: 'EPSG:4326',
73-
featureProjection: 'EPSG:3857'
74-
});
75-
76-
feature.setProperties($scope.item_state);
77-
return feature;
78-
};
79-
80-
const buildingSources = () => {
81-
const features = [buildingBoundingBox()];
82-
return new ol.source.Vector({ features });
83-
};
84-
85-
// Define building UBID bounding box
86-
const buildingBB = () => {
87-
const format = new ol.format.WKT();
88-
89-
const feature = format.readFeature($scope.bounding_box, {
90-
dataProjection: 'EPSG:4326',
91-
featureProjection: 'EPSG:3857'
92-
});
93-
feature.setProperties($scope.item_state);
94-
return feature;
95-
};
96-
97-
// Define building UBID centroid box
98-
const buildingCentroid = () => {
99-
const format = new ol.format.WKT();
100-
101-
const feature = format.readFeature($scope.centroid, {
102-
dataProjection: 'EPSG:4326',
103-
featureProjection: 'EPSG:3857'
104-
});
105-
feature.setProperties($scope.item_state);
106-
return feature;
107-
};
108-
109-
const buildingBBSources = () => {
110-
const features = [buildingBB()];
111-
return new ol.source.Vector({ features });
112-
};
113-
114-
const buildingCentroidSources = () => {
115-
const features = [buildingCentroid()];
116-
return new ol.source.Vector({ features });
117-
};
118-
119-
// Define taxlot UBID bounding box
120-
const taxlotBB = () => {
71+
const getFeature = (field) => {
12172
const format = new ol.format.WKT();
122-
123-
const feature = format.readFeature($scope.bounding_box, {
73+
const feature = format.readFeature(field, {
12474
dataProjection: 'EPSG:4326',
12575
featureProjection: 'EPSG:3857'
12676
});
12777
feature.setProperties($scope.item_state);
12878
return feature;
12979
};
13080

131-
// Define taxlot UBID centroid box
132-
const taxlotCentroid = () => {
133-
const format = new ol.format.WKT();
134-
135-
const feature = format.readFeature($scope.centroid, {
136-
dataProjection: 'EPSG:4326',
137-
featureProjection: 'EPSG:3857'
138-
});
139-
feature.setProperties($scope.item_state);
140-
return feature;
141-
};
81+
const getSources = (field) => {
82+
if (!field) return null;
14283

143-
const taxlotBBSources = () => {
144-
const features = [taxlotBB()];
84+
const features = [getFeature(field)];
14585
return new ol.source.Vector({ features });
14686
};
14787

148-
const taxlotCentroidSources = () => {
149-
const features = [taxlotCentroid()];
150-
return new ol.source.Vector({ features });
151-
};
88+
// This uses the bounding box instead of the lat/long. See BuildingPoint function in inventory_map_controller for reference
89+
const buildingSources = () => getSources($scope.bounding_box);
90+
// Property UBID bounding box
91+
const buildingBBSources = () => getSources($scope.bounding_box);
92+
// Property UBID Centroid
93+
const buildingCentroidSources = () => getSources($scope.centroid);
94+
// Building footprint polygon
95+
const buildingFootprintSources = () => getSources($scope.footprint);
96+
// Taxlot UBID bounding box
97+
const taxlotBBSources = () => getSources($scope.bounding_box);
98+
// Taxlot UBID Centroid
99+
const taxlotCentroidSources = () => getSources($scope.centroid);
152100

153101
const clusterSource = () => new ol.source.Cluster({
154102
source: buildingSources(),
@@ -183,6 +131,12 @@ angular.module('SEED.controller.inventory_detail_map', []).controller('inventory
183131
style: buildingStyle
184132
});
185133

134+
$scope.footprint_layer = new ol.layer.Vector({
135+
source: buildingFootprintSources(),
136+
zIndex: $scope.layers.footprint.zIndex,
137+
style: buildingStyle
138+
});
139+
186140
$scope.taxlot_bb_layer = new ol.layer.Vector({
187141
source: taxlotBBSources(),
188142
zIndex: $scope.layers.taxlot_bb_layer.zIndex,
@@ -202,6 +156,11 @@ angular.module('SEED.controller.inventory_detail_map', []).controller('inventory
202156
} else {
203157
layers = [base_layer, $scope.taxlot_bb_layer, $scope.taxlot_centroid_layer];
204158
}
159+
160+
if ($scope.footprint) {
161+
layers.push($scope.footprint_layer);
162+
}
163+
205164
$scope.map = new ol.Map({
206165
target: 'map',
207166
layers

seed/static/seed/js/controllers/inventory_map_controller.js

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,26 @@ angular.module('SEED.controller.inventory_map', []).controller('inventory_map_co
1515
'user_service',
1616
'organization_service',
1717
'labels',
18+
'footprint_column_name',
1819
'group',
1920
'urls',
2021
// eslint-disable-next-line func-names
21-
function ($scope, $stateParams, $state, $log, $uibModal, cycles, inventory_service, map_service, user_service, organization_service, labels, group, urls) {
22+
function (
23+
$scope,
24+
$stateParams,
25+
$state,
26+
$log,
27+
$uibModal,
28+
cycles,
29+
inventory_service,
30+
map_service,
31+
user_service,
32+
organization_service,
33+
labels,
34+
footprint_column_name,
35+
group,
36+
urls
37+
) {
2238
$scope.inventory_type = $stateParams.inventory_type;
2339
const isPropertiesTab = $scope.inventory_type === 'properties';
2440
if ($stateParams.group_id) {
@@ -113,7 +129,8 @@ angular.module('SEED.controller.inventory_map', []).controller('inventory_map_co
113129
property_centroid_layer: { zIndex: 4, visible: isPropertiesTab },
114130
taxlot_bb_layer: { zIndex: 5, visible: !isPropertiesTab },
115131
taxlot_centroid_layer: { zIndex: 6, visible: !isPropertiesTab },
116-
points_layer: { zIndex: 7, visible: true }
132+
points_layer: { zIndex: 7, visible: true },
133+
footprint_layer: { zIndex: 8, visible: true }
117134
};
118135

119136
const buildingSources = (records) => {
@@ -129,18 +146,18 @@ angular.module('SEED.controller.inventory_map', []).controller('inventory_map_co
129146
return new ol.source.Vector({ features });
130147
};
131148

132-
const boundingBoxSource = (records) => {
149+
const getSources = (records, field) => {
133150
const features = records.reduce((acc, record) => {
134-
if (record.bounding_box) {
151+
if (record[field]) {
135152
try {
136-
const feature = new ol.format.WKT().readFeature(record.bounding_box, {
153+
const feature = new ol.format.WKT().readFeature(record[field], {
137154
dataProjection: 'EPSG:4326',
138155
featureProjection: 'EPSG:3857'
139156
});
140157
feature.setProperties(record);
141158
acc.push(feature);
142159
} catch (e) {
143-
console.error(`Failed to process bounding box for id ${record.id}`);
160+
console.error(`Failed to process ${field} for id ${record.id}`);
144161
}
145162
}
146163
return acc;
@@ -149,25 +166,9 @@ angular.module('SEED.controller.inventory_map', []).controller('inventory_map_co
149166
return new ol.source.Vector({ features });
150167
};
151168

152-
const centroidSource = (records) => {
153-
const features = records.reduce((acc, record) => {
154-
if (record.centroid) {
155-
try {
156-
const feature = new ol.format.WKT().readFeature(record.centroid, {
157-
dataProjection: 'EPSG:4326',
158-
featureProjection: 'EPSG:3857'
159-
});
160-
feature.setProperties(record);
161-
acc.push(feature);
162-
} catch (e) {
163-
console.error(`Failed to process centroid for id ${record.id}`);
164-
}
165-
}
166-
return acc;
167-
}, []);
168-
169-
return new ol.source.Vector({ features });
170-
};
169+
const boundingBoxSource = (records) => getSources(records, 'bounding_box');
170+
const centroidSource = (records) => getSources(records, 'centroid');
171+
const footprintSource = (records) => getSources(records, footprint_column_name);
171172

172173
const censusTractSource = async () => {
173174
let geojson = {
@@ -276,6 +277,12 @@ angular.module('SEED.controller.inventory_map', []).controller('inventory_map_co
276277
style: propertyStyle
277278
});
278279

280+
$scope.footprint_layer = new ol.layer.Vector({
281+
source: footprintSource($scope.geocoded_properties),
282+
zIndex: $scope.layers.footprint_layer.zIndex,
283+
style: propertyStyle
284+
});
285+
279286
$scope.taxlot_bb_layer = new ol.layer.Vector({
280287
source: boundingBoxSource($scope.geocoded_taxlots),
281288
zIndex: $scope.layers.taxlot_bb_layer.zIndex,
@@ -487,6 +494,7 @@ angular.module('SEED.controller.inventory_map', []).controller('inventory_map_co
487494
$scope.filteredRecords = records.length;
488495

489496
$scope.points_layer.setSource(pointsSource(records));
497+
$scope.footprint_layer.setSource(footprintSource(records));
490498

491499
if (isPropertiesTab) {
492500
$scope.hexbin_layer.setSource(hexbinSource(records));

seed/static/seed/js/seed.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2186,6 +2186,14 @@
21862186
'label_service',
21872187
($stateParams, label_service) => label_service.get_labels($stateParams.inventory_type).then((labels) => _.filter(labels, (label) => !_.isEmpty(label.is_applied)))
21882188
],
2189+
footprint_column_name: [
2190+
'$stateParams',
2191+
'inventory_service',
2192+
($stateParams, inventory_service) => {
2193+
const get_columns = $stateParams.inventory_type === 'properties' ? inventory_service.get_property_columns : inventory_service.get_taxlot_columns;
2194+
return get_columns().then((columns) => columns.find((col) => col.column_name === 'property_footprint')?.name);
2195+
}
2196+
],
21892197
group: () => null
21902198
}
21912199
})

seed/static/seed/partials/inventory_map.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ <h1>{$:: 'Group - Map' | translate $}</h1>
107107
>Toggle Tax Lot UBID Centroids</a
108108
>
109109
</li>
110+
<li role="menuitem">
111+
<a ng-click="toggleLayer('footprint_layer')" translate
112+
>Toggle Footprints</a
113+
>
114+
</li>
110115
<li role="menuitem">
111116
<a ng-click="toggleLayer('census_tract_layer')" translate
112117
>Toggle Census Tracts</a
@@ -334,6 +339,15 @@ <h1>{$:: 'Group - Map' | translate $}</h1>
334339
/>
335340
{$:: 'Tax Lot UBID Centroids' | translate $}
336341
</label>
342+
<label>
343+
<input
344+
type="checkbox"
345+
name="footprints"
346+
ng-model="layers.footprint_layer.visible"
347+
ng-change="toggleLayer('footprint_layer', layers.footprint_layer.visible)"
348+
/>
349+
{$:: 'Footprints' | translate $}
350+
</label>
337351
<label>
338352
<input
339353
type="checkbox"

0 commit comments

Comments
 (0)