Subs union to server side
This commit is contained in:
parent
ed7c89476f
commit
ac4331edbd
10 changed files with 299 additions and 162 deletions
|
|
@ -3,89 +3,43 @@
|
|||
/* eslint-disable import/no-absolute-path */
|
||||
/* global L */
|
||||
|
||||
import { Map } from 'react-leaflet';
|
||||
import LGeo from 'leaflet-geodesy';
|
||||
import tunion from '@turf/union';
|
||||
import ttrunc from '@turf/truncate';
|
||||
import { check, Match } from 'meteor/check';
|
||||
|
||||
// https://stackoverflow.com/questions/35394577/leaflet-js-union-merge-circles
|
||||
const truncOptions = { precision: 6, coordinates: 2 };
|
||||
|
||||
function unify(polyList) {
|
||||
let unionTemp;
|
||||
for (let i = 0; i < polyList.length; i += 1) {
|
||||
const pol = polyList[i].toGeoJSON();
|
||||
const cleanPol = ttrunc(pol, truncOptions);
|
||||
if (i === 0) {
|
||||
unionTemp = cleanPol;
|
||||
} else {
|
||||
unionTemp = ttrunc(tunion(unionTemp, cleanPol), truncOptions);
|
||||
}
|
||||
}
|
||||
return unionTemp;
|
||||
}
|
||||
import calcUnion from '/imports/ui/components/Maps/SubsUnion/Unify';
|
||||
|
||||
const subsUnion = (union, options) => {
|
||||
// check(union, Match.Optional(Object));
|
||||
check(options, {
|
||||
map: Map,
|
||||
show: Boolean,
|
||||
subs: [Object],
|
||||
color: Match.Optional(String),
|
||||
fillcolor: Match.Optional(String),
|
||||
opacity: Match.Optional(Number),
|
||||
fit: Boolean
|
||||
});
|
||||
|
||||
const color = options.color || '#145A32';
|
||||
const fillColor = options.fillColor || 'green';
|
||||
const opacity = options.options || 0.1;
|
||||
|
||||
if (options.subs) {
|
||||
const lmap = options.map.leafletElement;
|
||||
// http://leafletjs.com/reference-1.2.0.html#layergroup
|
||||
// FeatureGroup has getBounds
|
||||
const unionGroup = new L.FeatureGroup();
|
||||
|
||||
if (union) {
|
||||
lmap.removeLayer(union);
|
||||
}
|
||||
union = null;
|
||||
|
||||
if (options.subs.length > 0 && options.show) {
|
||||
// http://leafletjs.com/reference-1.2.0.html#path
|
||||
const copts = {
|
||||
parts: 144
|
||||
};
|
||||
options.subs.forEach((sub) => {
|
||||
try {
|
||||
if (sub.location && sub.location.lat && sub.location.lon && sub.distance) {
|
||||
check(sub.location.lon, Number);
|
||||
check(sub.location.lat, Number);
|
||||
check(sub.distance, Number);
|
||||
const circle = LGeo.circle([sub.location.lat, sub.location.lon], sub.distance * 1000, copts);
|
||||
circle.addTo(unionGroup);
|
||||
} else {
|
||||
console.error(`Wrong subscription ${JSON.stringify(sub)}`);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
console.error(`Wrong subscription trying to make union ${JSON.stringify(sub)}`);
|
||||
if (options.show) {
|
||||
if (options.fromServer) {
|
||||
// We get the json from server side
|
||||
union = L.geoJson(JSON.parse(options.subs));
|
||||
union.setStyle({ color, fillColor, fillOpacity: opacity });
|
||||
union.addTo(lmap);
|
||||
if (options.fit && options.bounds) {
|
||||
// console.log(options.bounds);
|
||||
const bounds = JSON.parse(options.bounds);
|
||||
options.map.leafletElement.fitBounds(L.latLngBounds(bounds._northEast, bounds._southWest));
|
||||
}
|
||||
} else if (options.subs.length > 0) {
|
||||
const unionGroup = new L.FeatureGroup();
|
||||
const result = calcUnion(options.subs, unionGroup, sub => sub);
|
||||
const unionJson = result[0];
|
||||
const bounds = result[1];
|
||||
|
||||
union = L.geoJson(unionJson);
|
||||
union.setStyle({ color, fillColor, fillOpacity: opacity });
|
||||
union.addTo(lmap);
|
||||
if (options.fit) {
|
||||
options.map.leafletElement.fitBounds(bounds);
|
||||
}
|
||||
});
|
||||
const unionJson = unify(unionGroup.getLayers());
|
||||
union = L.geoJson(unionJson);
|
||||
union.setStyle({
|
||||
color,
|
||||
fillColor,
|
||||
fillOpacity: opacity
|
||||
});
|
||||
union.addTo(lmap);
|
||||
if (options.fit) {
|
||||
options.map.leafletElement.fitBounds(unionGroup.getBounds());
|
||||
}
|
||||
return union;
|
||||
}
|
||||
}
|
||||
return union;
|
||||
|
|
|
|||
48
imports/ui/components/Maps/SubsUnion/Unify.js
Normal file
48
imports/ui/components/Maps/SubsUnion/Unify.js
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import { check } from 'meteor/check';
|
||||
import LGeo from 'leaflet-geodesy';
|
||||
import tunion from '@turf/union';
|
||||
import ttrunc from '@turf/truncate';
|
||||
|
||||
// https://stackoverflow.com/questions/35394577/leaflet-js-union-merge-circles
|
||||
const truncOptions = { precision: 6, coordinates: 2 };
|
||||
|
||||
const unify = (polyList) => {
|
||||
let unionTemp;
|
||||
for (let i = 0; i < polyList.length; i += 1) {
|
||||
const pol = polyList[i].toGeoJSON();
|
||||
const cleanPol = ttrunc(pol, truncOptions);
|
||||
if (i === 0) {
|
||||
unionTemp = cleanPol;
|
||||
} else {
|
||||
unionTemp = ttrunc(tunion(unionTemp, cleanPol), truncOptions);
|
||||
}
|
||||
}
|
||||
return unionTemp;
|
||||
};
|
||||
|
||||
const calcUnion = (subs, group, decorated) => {
|
||||
const unionGroup = group;
|
||||
const copts = {
|
||||
parts: 144
|
||||
};
|
||||
subs.forEach((osub) => {
|
||||
try {
|
||||
if (osub.location && osub.location.lat && osub.location.lon && osub.distance) {
|
||||
check(osub.location.lon, Number);
|
||||
check(osub.location.lat, Number);
|
||||
check(osub.distance, Number);
|
||||
const dsub = decorated(osub);
|
||||
const circle = LGeo.circle([dsub.location.lat, dsub.location.lon], dsub.distance * 1000, copts);
|
||||
circle.addTo(unionGroup);
|
||||
} else {
|
||||
console.error(`Wrong subscription ${JSON.stringify(osub)}`);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e, `Wrong subscription trying to make union ${JSON.stringify(osub)}`);
|
||||
}
|
||||
});
|
||||
const unionJson = unify(unionGroup.getLayers());
|
||||
return [unionJson, unionGroup.getBounds()];
|
||||
};
|
||||
|
||||
export default calcUnion;
|
||||
|
|
@ -29,7 +29,6 @@ import ActiveFiresCollection from '/imports/api/ActiveFires/ActiveFires';
|
|||
import FireAlertsCollection from '/imports/api/FireAlerts/FireAlerts';
|
||||
import FalsePositivesCollection from '/imports/api/FalsePositives/FalsePositives';
|
||||
import SiteSettings from '/imports/api/SiteSettings/SiteSettings';
|
||||
import UserSubsToFiresCollection from '/imports/api/Subscriptions/Subscriptions';
|
||||
import { isNotHomeAndMobile, isChrome } from '/imports/ui/components/Utils/isMobile';
|
||||
import { isHome } from '/imports/ui/components/Utils/location';
|
||||
import ShareIt from '/imports/ui/components/ShareIt/ShareIt';
|
||||
|
|
@ -174,6 +173,8 @@ class FiresMap extends React.Component {
|
|||
map,
|
||||
subs: this.props.userSubs,
|
||||
show: this.state.showSubsUnion,
|
||||
bounds: this.props.userSubsBounds,
|
||||
fromServer: true,
|
||||
fit: false
|
||||
});
|
||||
}
|
||||
|
|
@ -181,7 +182,7 @@ class FiresMap extends React.Component {
|
|||
|
||||
render() {
|
||||
const { t } = this.props;
|
||||
console.log(`Rendering ${this.props.loading ? 'loading' : 'LOADED'} map ${this.props.activefires.length + this.props.firealerts.length} of ${this.props.activefirestotal} total. False positives: ${this.props.falsePositives.length}. Subs users ready ${this.props.subsready} (${this.props.userSubs.length}), reactive ${this.state.viewport.zoom >= MAXZOOMREACTIVE}`);
|
||||
console.log(`Rendering ${this.props.loading ? 'loading' : 'LOADED'} map ${this.props.activefires.length + this.props.firealerts.length} of ${this.props.activefirestotal} total. False positives: ${this.props.falsePositives.length}. Reactive ${this.state.viewport.zoom >= MAXZOOMREACTIVE}`);
|
||||
const title = `${t('AppName')}: ${t('Fuegos activos')}`;
|
||||
if (Meteor.isDevelopment) {
|
||||
console.log(`False positives total: ${this.props.falsePositivesTotal}`);
|
||||
|
|
@ -315,7 +316,8 @@ class FiresMap extends React.Component {
|
|||
FiresMap.propTypes = {
|
||||
loading: PropTypes.bool.isRequired,
|
||||
subsready: PropTypes.bool.isRequired,
|
||||
userSubs: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
userSubs: PropTypes.string,
|
||||
userSubsBounds: PropTypes.string,
|
||||
activefires: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
firealerts: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
falsePositives: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
|
|
@ -379,15 +381,17 @@ export default translate([], { wait: true })(withTracker(() => {
|
|||
|
||||
Meteor.subscribe('activefirestotal');
|
||||
Meteor.subscribe('falsePositivesTotal');
|
||||
Meteor.subscribe('settings');
|
||||
const userSubs = Meteor.subscribe('userSubsToFires');
|
||||
const settingsSubs = Meteor.subscribe('settings');
|
||||
const lastCheck = SiteSettings.findOne({ name: 'last-fire-check' });
|
||||
const userSubs = SiteSettings.findOne({ name: 'subs-public-union' });
|
||||
const userSubsBounds = SiteSettings.findOne({ name: 'subs-public-union-bounds' });
|
||||
const fireAlerts = FireAlertsCollection.find().fetch();
|
||||
const falsePositives = FalsePositivesCollection.find().fetch();
|
||||
return {
|
||||
loading: !subscription ? true : !subscription.ready(),
|
||||
userSubs: UserSubsToFiresCollection.find().fetch(),
|
||||
subsready: userSubs.ready(),
|
||||
loading: !subscription ? true : !(subscription.ready() && settingsSubs.ready()),
|
||||
userSubs: userSubs ? userSubs.value : null,
|
||||
userSubsBounds: userSubs ? userSubsBounds.value : null,
|
||||
subsready: settingsSubs.ready(),
|
||||
// Not reactive query depending on zoom level
|
||||
activefires: ActiveFiresCollection.find({}, { reactive: zoom.get() >= MAXZOOMREACTIVE }).fetch(),
|
||||
activefirestotal: Counter.get('countActiveFires') + fireAlerts.length,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import CenterInMyPosition from '/imports/ui/components/CenterInMyPosition/Center
|
|||
import subsUnion from '/imports/ui/components/Maps/SubsUnion/SubsUnion';
|
||||
import DefMapLayers from '/imports/ui/components/Maps/DefMapLayers';
|
||||
import Loading from '/imports/ui/components/Loading/Loading';
|
||||
import UserSubsToFiresCollection from '/imports/api/Subscriptions/Subscriptions';
|
||||
import SiteSettings from '/imports/api/SiteSettings/SiteSettings';
|
||||
import { isChrome } from '/imports/ui/components/Utils/isMobile';
|
||||
import { isHome } from '/imports/ui/components/Utils/location';
|
||||
import ShareIt from '/imports/ui/components/ShareIt/ShareIt';
|
||||
|
|
@ -66,6 +66,8 @@ class SubscriptionsMap extends React.Component {
|
|||
this.state.union = subsUnion(this.state.union, {
|
||||
map,
|
||||
subs: this.props.userSubs,
|
||||
bounds: this.props.userSubsBounds,
|
||||
fromServer: true,
|
||||
show: true,
|
||||
fit: this.state.init
|
||||
});
|
||||
|
|
@ -89,7 +91,7 @@ class SubscriptionsMap extends React.Component {
|
|||
render() {
|
||||
const { t } = this.props;
|
||||
const title = `${t('AppName')}: ${t('Zonas vigiladas')}`;
|
||||
console.log(`Rendering Subs users ready ${this.props.subsready} subs: ${this.props.userSubs.length} viewport: ${JSON.stringify(this.state.viewport)}`);
|
||||
console.log(`Rendering Subs users ready ${this.props.subsready} viewport: ${JSON.stringify(this.state.viewport)}`);
|
||||
return (
|
||||
<Fragment>
|
||||
{ !isHome() &&
|
||||
|
|
@ -153,16 +155,20 @@ class SubscriptionsMap extends React.Component {
|
|||
}
|
||||
|
||||
SubscriptionsMap.propTypes = {
|
||||
userSubs: PropTypes.string,
|
||||
userSubsBounds: PropTypes.string,
|
||||
subsready: PropTypes.bool.isRequired,
|
||||
userSubs: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
history: PropTypes.object.isRequired,
|
||||
t: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default translate([], { wait: true })(withTracker(() => {
|
||||
const userSubs = Meteor.subscribe('userSubsToFires');
|
||||
const settingsSubs = Meteor.subscribe('settings');
|
||||
const userSubs = SiteSettings.findOne({ name: 'subs-public-union' });
|
||||
const userSubsBounds = SiteSettings.findOne({ name: 'subs-public-union-bounds' });
|
||||
return {
|
||||
userSubs: UserSubsToFiresCollection.find().fetch(),
|
||||
subsready: userSubs.ready()
|
||||
userSubs: userSubs ? userSubs.value : null,
|
||||
userSubsBounds: userSubs ? userSubsBounds.value : null,
|
||||
subsready: settingsSubs.ready()
|
||||
};
|
||||
})(SubscriptionsMap));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue