/**
* @ngdoc directive
* @name MapaAreaDeAtuacao
* @module s4c.directives.MapaAreaDeAtuacao
*
* @description
* `MapaAreaDeAtuacaoCtrl` Controller do módulo do mapa da área de atuação
*
* @example <mapa-area-de-atuacao style="width: 55%; height: 500px;"></mapa-area-de-atuacao>
*
*/
(function () {
'use strict';
angular.module('s4c.directives.mapa-area-de-atuacao', [])
.directive('mapaAreaDeAtuacao', MapaAreaDeAtuacao);
MapaAreaDeAtuacaoCtrl.$inject = ['$scope', 'leafletData', 'MapaAreaDeAtuacao', 'PlanejamentoDesenhoService', 'MainState', '$mdDialog'];
function MapaAreaDeAtuacaoCtrl($scope, leafletData, MapaAreaDeAtuacao, PlanejamentoDesenhoService, MainState, $mdDialog) {
$scope.center = {
lat: -22.9009167,
lng: -43.1795591,
zoom: 13
};
/**
* Criação das funções do módulo do mapa da area de atuação
*
* @method buildMap
*
*
* @param callback {Function}
* @param areaAtuacao {Object}
*
*/
function buildMap(callBack, areaAtuacao) {
$scope.areaAtuacao = areaAtuacao;
leafletData
.getMap('mapa-area-de-atuacao')
.then(function (map) {
/*map.on('draw:created', function(e) {
map.addLayer(e.layer);
e.layer.on('edit', function () {
MapaAreaDeAtuacao.trigger('areaDeAtuacaoEditada');
});
e.layer.editing.enable();
MapaAreaDeAtuacao._layer = e.layer;
MapaAreaDeAtuacao.trigger('areaDeAtuacaoEditada');
})*/
if (map.options.drawControl === false) {
var saveLayer = L.Control.extend({
options: {
position: 'topleft'
},
onAdd: function (map) {
var container = L.DomUtil.create('div', 'control-savelayer');
L.DomEvent
.addListener(container, 'click', L.DomEvent.stopPropagation)
.addListener(container, 'click', L.DomEvent.preventDefault)
return container;
},
onRemove: function (map) {
this._map = null;
}
});
// Initialise the FeatureGroup to store editable layers
$scope.drawnItems = new L.FeatureGroup();
map.addLayer($scope.drawnItems);
map.options.allowIntersection = false;
L.Planejamento = L.DrawToolbar.extend({
options: {
position: 'topleft'
}
});
L.Planejamento.include({
getModeHandlers: function (map) {
var ret = [];
ret.push({
enabled: this.options.polygon,
handler: new L.Draw.Polygon(map, this.options.polygon),
title: L.drawLocal.draw.toolbar.buttons.polygon
});
return ret;
}
});
L.Control.CustomDraw = L.Control.Draw.extend({
initialize: function (options) {
L.Control.prototype.initialize.call(this, options);
var toolbar;
this._toolbars = {};
// Initialize toolbars
if (L.Planejamento && this.options.draw) {
toolbar = new L.Planejamento(this.options.draw);
this._toolbars[L.DrawToolbar.TYPE] = toolbar;
// Listen for when toolbar is enabled
this._toolbars[L.DrawToolbar.TYPE].on('enable', this._toolbarEnabled, this);
}
if (L.EditToolbar && this.options.edit) {
toolbar = new L.EditToolbar(this.options.edit);
this._toolbars[L.EditToolbar.TYPE] = toolbar;
// Listen for when toolbar is enabled
this._toolbars[L.EditToolbar.TYPE].on('enable', this._toolbarEnabled, this);
}
}
});
// Initialise the draw control and pass it the FeatureGroup of editable layers
$scope.drawControl = new L.Control.CustomDraw({
position: 'topleft',
draw: {
polygon: {
shapeOptions: {
color: 'red'
},
allowIntersection: false,
drawError: {
color: 'orange',
timeout: 1000
},
showArea: true,
metric: false,
repeatMode: false
}
},
edit: {
edit: false,
remove: true,
featureGroup: $scope.drawnItems
}
});
map.addControl($scope.drawControl);
map.options.drawControl = true;
$scope.planejando = true;
$scope.planejamentoArray = L.geoJson();
//$scope.router.setWaypoints([]);
map.on('draw:drawstart', function (e) {
if (!MapaAreaDeAtuacao._regiao) {
map.fire('draw:cancel', { handler: e.type });
return;
}
var offsetX = $scope.drawControl._container.offsetLeft;
var offsetY = $scope.drawControl._container.offsetTop;
});
map.on('draw:edited', function (e) {
if (!$scope.planejando) {
return;
}
});
}
map.off('draw:created', drawCreated);
map.on('draw:created', drawCreated);
MapaAreaDeAtuacao._map = map;
callBack();
});
}
/**
* Criação das funções de desenho do mapa da area de atuação
*
* @method drawCreated
*
*
* @param e {event}
*
*/
function drawCreated(e) {
if (!MapaAreaDeAtuacao._regiao) {
MapaAreaDeAtuacao._map.fire('draw:cancel', { handler: e.type });
$mdDialog
.show($mdDialog.alert()
.title($scope.res('COMUM_ERRO'))
.content($scope.res('REGIAO_SELECIONAR'))
.ok($scope.res('COMUM_OK')));
return;
}
var type = e.layerType,
layer = e.layer;
var intersection = false;
_.each(MapaAreaDeAtuacao._array_layer, function (layer_inserted) {
var checked = crossCheck(layer_inserted, layer);
if (checked.geometries.length > 0) {
intersection = true;
}
/*if( layer.getBounds().intersects(layer_inserted.getBounds()) ){
intersection = true;
}*/
});
if (intersection) {
MapaAreaDeAtuacao._map.fire('draw:cancel', { handler: e.type });
$mdDialog
.show($mdDialog.alert()
.title($scope.res('COMUM_ERRO'))
.content($scope.res('REGIAO_INTERSECAO'))
.ok($scope.res('COMUM_OK')));
return;
}
layer.editing.disable();
layer.setStyle({
weight: 5,
color: $scope.areaAtuacao.cor,
dashArray: '',
fillOpacity: 0.8
});
$scope.drawnItems.addLayer(layer);
MapaAreaDeAtuacao._layer = layer;
layer.data = MapaAreaDeAtuacao._regiao;
MapaAreaDeAtuacao._array_layer.push(layer);
MapaAreaDeAtuacao.trigger('areaDeAtuacaoEditada');
}
/**
* Retorna a Área que faz interseção entre 2 lines string
*
* @method lineStringsIntersect
*
*
* @param l1 {Object}
* @param l2 {Object}
*
* @returns Intersects
*
*/
function lineStringsIntersect(l1, l2) {
var intersects = [];
for (var i = 0; i <= l1.coordinates.length - 2; ++i) {
for (var j = 0; j <= l2.coordinates.length - 2; ++j) {
var a1Latlon = L.latLng(l1.coordinates[i][1], l1.coordinates[i][0]),
a2Latlon = L.latLng(l1.coordinates[i + 1][1], l1.coordinates[i + 1][0]),
b1Latlon = L.latLng(l2.coordinates[j][1], l2.coordinates[j][0]),
b2Latlon = L.latLng(l2.coordinates[j + 1][1], l2.coordinates[j + 1][0]),
a1 = L.Projection.SphericalMercator.project(a1Latlon),
a2 = L.Projection.SphericalMercator.project(a2Latlon),
b1 = L.Projection.SphericalMercator.project(b1Latlon),
b2 = L.Projection.SphericalMercator.project(b2Latlon),
ua_t = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x),
ub_t = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x),
u_b = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y);
if (u_b != 0) {
var ua = ua_t / u_b,
ub = ub_t / u_b;
if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {
var pt_x = a1.x + ua * (a2.x - a1.x),
pt_y = a1.y + ua * (a2.y - a1.y),
pt_xy = {
"x": pt_x,
"y": pt_y
},
pt_latlon = L.Projection.SphericalMercator.unproject(pt_xy);
intersects.push({
'type': 'Point',
'coordinates': [pt_latlon.lng, pt_latlon.lat]
});
}
}
}
}
if (intersects.length == 0) intersects = false;
return intersects;
}
//takes GeoJSON as input, creates a GeoJSON GeometryCollection of linestrings as output
/**
* Takes GeoJSON as input, creates a GeoJSON GeometryCollection of linestrings as output
*
* @method lineify
*
*
* @param inputGeom {Object}
*
* @returns GeometryCollection of linestrings
*/
function lineify(inputGeom) {
var outputLines = {
"type": "GeometryCollection",
"geometries": []
}
switch (inputGeom.type) {
case "GeometryCollection":
for (var i in inputGeom.geometries) {
var geomLines = lineify(inputGeom.geometries[i]);
if (geomLines) {
for (var j in geomLines.geometries) {
outputLines.geometries.push(geomLines.geometries[j]);
}
} else {
outputLines = false;
}
}
break;
case "Feature":
var geomLines = lineify(inputGeom.geometry);
if (geomLines) {
for (var j in geomLines.geometries) {
outputLines.geometries.push(geomLines.geometries[j]);
}
} else {
outputLines = false;
}
break;
case "FeatureCollection":
for (var i in inputGeom.features) {
var geomLines = lineify(inputGeom.features[i].geometry);
if (geomLines) {
for (var j in geomLines.geometries) {
outputLines.geometries.push(geomLines.geometries[j]);
}
} else {
outputLines = false;
}
}
break;
case "LineString":
outputLines.geometries.push(inputGeom);
break;
case "MultiLineString":
case "Polygon":
for (var i in inputGeom.coordinates) {
outputLines.geometries.push({
"type": "LineString",
"coordinates": inputGeom.coordinates[i]
});
}
break;
case "MultiPolygon":
for (var i in inputGeom.coordinates) {
for (var j in inputGeom.coordinates[i]) {
outputLines.geometries.push({
"type": "LineString",
"coordinates": inputGeom.coordinates[i][j]
});
}
}
break;
default:
outputLines = false;
}
return outputLines;
}
//takes Leaflet layers as input; produces geoJSON points of their intersections as output
/**
* Takes Leaflet layers as input; produces geoJSON points of their intersections as output
*
* @method crossCheck
*
*
* @param baseLayer {Object}
* @param drawLayer {Object}
*
* @returns Gera um geojson com os pontos de interseção
*/
function crossCheck(baseLayer, drawLayer) {
var baseJson = baseLayer.toGeoJSON(),
drawJson = drawLayer.toGeoJSON(),
baseLines = lineify(baseJson),
drawLines = lineify(drawJson),
crossPoints = {
type: "GeometryCollection",
geometries: []
};
if (baseLines && drawLines) {
for (var i in drawLines.geometries) {
for (var j in baseLines.geometries) {
var crossTest = lineStringsIntersect(drawLines.geometries[i], baseLines.geometries[j]);
if (crossTest) {
for (var k in crossTest) {
crossPoints.geometries.push(crossTest[k]);
}
}
}
}
}
return crossPoints;
}
angular.extend($scope, {
$api: {
buildMap: buildMap
}
});
MainState.registerDirective('mapaAreaDeAtuacao', $scope.$api);
$scope.$on('$destroy', function () {
MainState.unregisterDirective('mapaAreaDeAtuacao');
});
}
function MapaAreaDeAtuacao() {
return {
$scope: {
desenhar: '@'
},
templateUrl: 'app/directives/mapa-area-de-atuacao/mapa-area-de-atuacao.html',
controller: MapaAreaDeAtuacaoCtrl
}
};
}());