diff --git a/module/css/vmap.less b/module/css/vmap.less
index 0afd13f194d292e38f188753422b6b48c5ebab8c..fa7278d2fcf13ac3cdd3f2529f01158bff52c206 100644
--- a/module/css/vmap.less
+++ b/module/css/vmap.less
@@ -236,7 +236,7 @@ html, body {
     position: relative;
     height: 100%;
 }
-app-map > div {
+app-map > div,  app-map-compare > div{
     width: auto;
     height: 100%;
     background-color: @background;
@@ -380,7 +380,7 @@ input[readonly] {
     display: -ms-flex !important;
     display: flex !important;
 }
-#map-container{
+#map-container, #map-container-compare{
     -webkit-transition: all 300ms ease-out 0s;
     -o-transition: all 300ms ease-out 0s;
     transition: all 300ms ease-out 0s;
@@ -389,8 +389,37 @@ input[readonly] {
     height: ~"-webkit-calc(100% - 32px)";
     height: ~"-o-calc(100% - 32px)";
     height: ~"calc(100% - 32px)";
+    width : 100%;
 }
-#map-container.minus{
+#map-container.half,#map-container-compare.half{
+    width : calc(50% ~"-" @right-sidebar-width/2);
+    float: left;
+}
+#map-container-compare.half{
+  border-left: solid 2px #4a4a41;
+}
+/*#map-container.right-module-bar-present{
+   width : calc(100% ~"-" @right-sidebar-width);
+}*/
+/*#map-container.left-map-manager-open{
+   width : calc(100% ~"-" @right-sidebar-width ~"-" @left-sidebar-content-width);
+}*/
+#map-container.half.left-map-manager-open, #map-container-compare.half.left-map-manager-open{
+   width : calc(50% ~"-" @right-sidebar-width/2 ~"-" @left-sidebar-content-width/2);
+}
+#map-container.half.right-module-bar-present,#map-container-compare.half.right-module-bar-present{
+    width : calc(50% ~"-" @right-sidebar-width/2 ~"-" @left-sidebar-width/2);
+}
+#map-container.half.right-module-bar-present.left-map-manager-open,#map-container-compare.half.right-module-bar-present.left-map-manager-open{
+    width : calc(50% ~"-" @right-sidebar-width/2 ~"-" @left-sidebar-width/2 ~"-" @left-sidebar-content-width/2);
+}
+#map-container.half.right-module-bar-present.right-module-manager-open,#map-container-compare.half.right-module-bar-present.right-module-manager-open{
+    width : calc(50% ~"-" @right-sidebar-width/2 ~"-" @left-sidebar-width/2 ~"-" @right-sidebar-content-width/2);
+}
+#map-container.half.right-module-bar-present.left-map-manager-open.right-module-manager-open,#map-container-compare.half.right-module-bar-present.left-map-manager-open.right-module-manager-open{
+    width : calc(50% ~"-" @right-sidebar-width/2 ~"-" @left-sidebar-width/2 ~"-" @left-sidebar-content-width/2 ~"-" @right-sidebar-content-width/2);
+}
+#map-container.minus,#map-container-compare.minus{
     height: 95%;
     height: ~"-moz-calc(100% - 47px)";
     height: ~"-webkit-calc(100% - 47px)";
@@ -399,13 +428,13 @@ input[readonly] {
     font-size: 12px;
     padding: 0px 0px;
 }
-#map-container.open{
+#map-container.open, #map-container-compare.open{
     height: -moz-calc(100% ~"-" @botom-open-height ~"-" 47px);
     height: -webkit-calc(100% ~"-" @botom-open-height ~"-" 47px);
     height: -o-calc(100% ~"-" @botom-open-height ~"-" 47px);
     height: calc(100% ~"-" @botom-open-height ~"-" 47px);
 }
-#map-container.open2{
+#map-container.open2, #map-container-compare.open2{
     height: -moz-calc(100% ~"-" @botom-open2-height ~"-" 47px);
     height: -webkit-calc(100% ~"-" @botom-open2-height ~"-" 47px);
     height: -o-calc(100% ~"-" @botom-open2-height ~"-" 47px);
@@ -810,6 +839,35 @@ app-layertree button:hover {
     text-align: center;
     background-color: transparent;
 }
+
+.ol-target-overlay .ol-target
+{	border: 1px solid transparent;
+	box-shadow: 0 0 1px 1px #fff;
+	display: block;
+	height: 20px;
+	width: 0;
+}
+
+.ol-target-overlay .ol-target:after,
+.ol-target-overlay .ol-target:before
+{	content:"";
+	border: 1px solid #369;
+	box-shadow: 0 0 1px 1px #fff;
+	display: block;
+	width: 20px;
+	height: 0;
+	position:absolute;
+	top:9px;
+	left:-9px;
+}
+.ol-target-overlay .ol-target:after
+{	box-shadow: none;
+	height: 20px;
+	width: 0;
+	top:0px;
+	left:0px;
+}
+
 #map-name, #current-projection{
     position: initial;
 }
@@ -2371,3 +2429,32 @@ div.vmap-select-scale-alert{
     max-width: 197px !important;
     text-align: center !important;
 }
+
+#basic-tools-dropdown-comapremode{
+    margin: -10px -1px;
+    width: 30%;
+    min-width: 450px;
+    max-width: 550px;
+    min-height: 55px;
+    padding-top: 15px !important;
+}
+
+.basic-tools-element>span.icon-mirror {
+    font-size: 16px;
+    line-height: 0;
+}
+
+.layerstree-nav {
+    margin-left: 40px;
+}
+
+.layerstree-nav>li>a {
+    padding: 0px 15px;
+    border: 1px solid #8a8a8a !important;
+    color: #333;
+}
+
+.ol-current-projection-compare{
+    bottom: 29px;
+    margin-left: -16%;
+}
diff --git a/module/forms/configuration/configuration_vitis_configuration_vmapConfig.json b/module/forms/configuration/configuration_vitis_configuration_vmapConfig.json
index eed719d9aedd5f8c8024774e31b13b187c9ae6cc..4304e1397892ff9d425bc986d7d2e91706722ca7 100755
--- a/module/forms/configuration/configuration_vitis_configuration_vmapConfig.json
+++ b/module/forms/configuration/configuration_vitis_configuration_vmapConfig.json
@@ -1,21 +1,46 @@
 {
     "datasources": {
-        "datasource_1": {
+        "datasource_tools": {
             "type": "object",
             "dataType": "text",
             "name": "avaliable_controls",
             "description": "",
             "options": [
-                "FORM_TOOLS_ATTRIBUTION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|Attribution",
-                "FORM_TOOLS_MOUSE_POSITION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|MousePosition",
-                "FORM_TOOLS_CURRENT_PROJECTION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|CurrentProjection",
-                "FORM_TOOLS_MAP_NAME_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|MapName",
-                "FORM_TOOLS_SCALE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|Scale",
-                "FORM_TOOLS_SCALE_LINE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|ScaleLine",
-                "FORM_TOOLS_OVERVIEW_MAP_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|OverviewMap",
-                "FORM_TOOLS_ZOOM_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|Zoom",
-                "FORM_TOOLS_ZOOM_SLIDER_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|ZoomSlider",
-                "FORM_TOOLS_REFRESH_SOCKET_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|RefreshSocket"
+                "FORM_TOOLS_MAP_MANAGER_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|MapManager",
+                "FORM_TOOLS_LOCATION_SEARCH_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|LocationSearch",
+                "FORM_TOOLS_LOCATION_HOME_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|LocationHome",
+                "FORM_TOOLS_LOCATION_REFRESH_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|LocationRefresh",
+                "FORM_TOOLS_LOCATION_MAX_EXTENT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|LocationMaxExtent",
+                "FORM_TOOLS_LOCATION_MY_POSITION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|LocationMyPosition",
+                "FORM_TOOLS_LOCATION_XY_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|LocationXY",
+                "FORM_TOOLS_LOCATION_PREC_NEXT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|LocationPrecNext",
+                "FORM_TOOLS_URL_GENERATOR_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|URLGenerator",
+                "FORM_TOOLS_MAP_COMPARE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|MapCompare",
+                "FORM_TOOLS_MESURE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|Mesure",
+                "FORM_TOOLS_SELECT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|Select",
+                "FORM_TOOLS_ADVANCED_SELECT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|AdvancedSelect",
+                "FORM_TOOLS_INSERT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|Insert",
+                "FORM_TOOLS_PRINT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|Print",
+                "FORM_TOOLS_CONFIG_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|Config",
+                "FORM_TOOLS_USER_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|User"
+            ]
+        },
+        "datasource_controls": {
+            "type": "object",
+            "dataType": "text",
+            "name": "avaliable_controls",
+            "description": "",
+            "options": [
+                "FORM_CONTROLS_ATTRIBUTION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|Attribution",
+                "FORM_CONTROLS_MOUSE_POSITION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|MousePosition",
+                "FORM_CONTROLS_CURRENT_PROJECTION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|CurrentProjection",
+                "FORM_CONTROLS_MAP_NAME_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|MapName",
+                "FORM_CONTROLS_SCALE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|Scale",
+                "FORM_CONTROLS_SCALE_LINE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|ScaleLine",
+                "FORM_CONTROLS_OVERVIEW_MAP_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|OverviewMap",
+                "FORM_CONTROLS_ZOOM_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|Zoom",
+                "FORM_CONTROLS_ZOOM_SLIDER_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|ZoomSlider",
+                "FORM_CONTROLS_REFRESH_SOCKET_CONFIGURATION_CONFIGURATION_VMAP_CONFIG|RefreshSocket"
             ]
         }
     },
@@ -252,19 +277,53 @@
                 "fields": [
                     {
                         "type": "double_select",
-                        "name": "controls.active_controls",
+                        "name": "controls.active_tools",
                         "label_from": "FORM_AVALIABLE_TOOLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG",
                         "label_to": "FORM_ACTIVE_TOOLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG",
                         "required": false,
                         "nb_cols": 12,
                         "size": 10,
-                        "id": "Element_0_1_1",
+                        "name_to": "controls.active_tools",
+                        "name_from": "controls.active_tool",
+                        "datasource": {
+                            "datasource_id": "datasource_tools"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "double_select",
+                        "name": "controls.public_active_tools",
+                        "label_from": "FORM_AVALIABLE_PUBLIC_TOOLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG",
+                        "label_to": "FORM_ACTIVE_PUBLIC_TOOLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG",
+                        "required": false,
+                        "nb_cols": 12,
+                        "size": 10,
+                        "name_to": "controls.public_active_tools",
+                        "name_from": "controls.public_active_tool",
+                        "datasource": {
+                            "datasource_id": "datasource_tools"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "double_select",
+                        "name": "controls.active_controls",
+                        "label_from": "FORM_AVALIABLE_CONTROLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG",
+                        "label_to": "FORM_ACTIVE_CONTROLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG",
+                        "required": false,
+                        "nb_cols": 12,
+                        "size": 10,
                         "name_to": "controls.active_controls",
                         "name_from": "controls.active_control",
                         "datasource": {
-                            "datasource_id": "datasource_1"
-                        },
-                        "id_from": "Element_0_1_1_from"
+                            "datasource_id": "datasource_controls"
+                        }
                     }
                 ]
             },
diff --git a/module/forms/vmap_business_object/vmap_business_object_vmap_business_object.js b/module/forms/vmap_business_object/vmap_business_object_vmap_business_object.js
index ad663b75ea42b64cae3ef34ae7ed92a5700ea8f9..6a1ab146892cecec6567b3fa5ecc9a3e3bfe53f1 100644
--- a/module/forms/vmap_business_object/vmap_business_object_vmap_business_object.js
+++ b/module/forms/vmap_business_object/vmap_business_object_vmap_business_object.js
@@ -250,6 +250,26 @@ var oFormScope;
                         oFormValues['id_field']['options'] = aColumnsOptions;
                     }
                 }
+                if (angular.isDefined(oFormValues['sorted_by'])) {
+                    if (angular.isDefined(oFormValues['sorted_by']['options'])) {
+                        oFormValues['sorted_by']['options'] = aColumnsOptions;
+                    }
+                }
+                if (angular.isDefined(oFormValues['geom_column'])) {
+                    if (angular.isDefined(oFormValues['geom_column']['options'])) {
+                        oFormValues['geom_column']['options'] = aColumnsOptions;
+                    }
+                }
+                if (angular.isDefined(oFormValues['search_field'])) {
+                    if (angular.isDefined(oFormValues['search_field']['options'])) {
+                        oFormValues['search_field']['options'] = aColumnsOptions;
+                    }
+                }
+                if (angular.isDefined(oFormValues['result_field'])) {
+                    if (angular.isDefined(oFormValues['result_field']['options'])) {
+                        oFormValues['result_field']['options'] = aColumnsOptions;
+                    }
+                }
             });
 
         },
diff --git a/module/forms/vmap_business_object/vmap_business_object_vmap_business_object.json b/module/forms/vmap_business_object/vmap_business_object_vmap_business_object.json
index b5697404c934a44fa2069f9ed2ce3be2fec2b480..e0168f15efdbb3674d714c7de0f294e58283bb88 100644
--- a/module/forms/vmap_business_object/vmap_business_object_vmap_business_object.json
+++ b/module/forms/vmap_business_object/vmap_business_object_vmap_business_object.json
@@ -280,52 +280,98 @@
             },
             {
                 "fields": [{
-                        "type": "text",
+                        "type": "editable_select",
                         "name": "sorted_by",
                         "label": "FORM_SORTED_BY_DEVELOPMENT_0",
                         "required": false,
-                        "pattern": "",
-                        "nb_cols": 6,
-                        "id": "New_el_9_11_1"
+                        "nb_cols": 5
+                    }, {
+                        "type": "button",
+                        "class": "btn-group btn-group-sm margin-top-20",
+                        "nb_cols": 1,
+                        "buttons": [{
+                                "type": "button",
+                                "name": "table-datalist",
+                                "label": "FORM_SORTED_BY_DEVELOPMENT_0",
+                                "class": "btn-primary",
+                                "event": "loadVMapBoFormColumns()",
+                                "glyphicon": "refresh"
+                            }
+                        ]
                     }]
             },
             {
                 "fields": [{
-                        "type": "text",
+                        "type": "editable_select",
                         "name": "geom_column",
                         "label": "FORM_GEOM_COLUMN_DEVELOPMENT_0",
                         "required": true,
-                        "pattern": "",
-                        "nb_cols": 6,
-                        "id": "New_el_10_12_1"
+                        "nb_cols": 5
+                    }, {
+                        "type": "button",
+                        "class": "btn-group btn-group-sm margin-top-20",
+                        "nb_cols": 1,
+                        "buttons": [{
+                                "type": "button",
+                                "name": "table-datalist",
+                                "label": "FORM_GEOM_COLUMN_DEVELOPMENT_0",
+                                "class": "btn-primary",
+                                "event": "loadVMapBoFormColumns()",
+                                "glyphicon": "refresh"
+                            }
+                        ]
                     }]
             },
             {
                 "fields": [{
-                        "type": "text",
+                        "type": "editable_select",
                         "name": "search_field",
                         "label": "FORM_SEARCH_FIELD_0",
-                        "nb_cols": 6,
-                        "id": "New_el_11_13_1",
+                        "nb_cols": 5,
                         "tooltip": {
                             "title": "",
                             "content": "FORM_SEARCH_FIELD_0_TOOLTIP",
                             "container": "body"
                         }
+                    }, {
+                        "type": "button",
+                        "class": "btn-group btn-group-sm margin-top-20",
+                        "nb_cols": 1,
+                        "buttons": [{
+                                "type": "button",
+                                "name": "table-datalist",
+                                "label": "FORM_SEARCH_FIELD_0",
+                                "class": "btn-primary",
+                                "event": "loadVMapBoFormColumns()",
+                                "glyphicon": "refresh"
+                            }
+                        ]
                     }]
             },
             {
                 "fields": [{
-                        "type": "text",
+                        "type": "editable_select",
                         "name": "result_field",
                         "label": "FORM_RESULT_FIELD_0",
-                        "nb_cols": 6,
-                        "id": "New_el_12_14_1",
+                        "nb_cols": 5,
                         "tooltip": {
                             "title": "",
                             "content": "FORM_RESULT_FIELD_0_TOOLTIP",
                             "container": "body"
                         }
+                    }, {
+                        "type": "button",
+                        "class": "btn-group btn-group-sm margin-top-20",
+                        "nb_cols": 1,
+                        "buttons": [{
+                                "type": "button",
+                                "name": "table-datalist",
+                                "label": "FORM_RESULT_FIELD_0",
+                                "class": "btn-primary",
+                                "event": "loadVMapBoFormColumns()",
+                                "glyphicon": "refresh"
+                            }
+                        ]
                     }]
             },
             {
@@ -674,52 +720,98 @@
             },
             {
                 "fields": [{
-                        "type": "text",
+                        "type": "editable_select",
                         "name": "sorted_by",
                         "label": "FORM_SORTED_BY_DEVELOPMENT_0",
                         "required": false,
-                        "pattern": "",
-                        "nb_cols": 6,
-                        "id": "New_el_9_11_1"
+                        "nb_cols": 5
+                    }, {
+                        "type": "button",
+                        "class": "btn-group btn-group-sm margin-top-20",
+                        "nb_cols": 1,
+                        "buttons": [{
+                                "type": "button",
+                                "name": "table-datalist",
+                                "label": "FORM_SORTED_BY_DEVELOPMENT_0",
+                                "class": "btn-primary",
+                                "event": "loadVMapBoFormColumns()",
+                                "glyphicon": "refresh"
+                            }
+                        ]
                     }]
             },
             {
                 "fields": [{
-                        "type": "text",
+                        "type": "editable_select",
                         "name": "geom_column",
                         "label": "FORM_GEOM_COLUMN_DEVELOPMENT_0",
                         "required": true,
-                        "pattern": "",
-                        "nb_cols": 6,
-                        "id": "New_el_10_12_1"
+                        "nb_cols": 5
+                    }, {
+                        "type": "button",
+                        "class": "btn-group btn-group-sm margin-top-20",
+                        "nb_cols": 1,
+                        "buttons": [{
+                                "type": "button",
+                                "name": "table-datalist",
+                                "label": "FORM_GEOM_COLUMN_DEVELOPMENT_0",
+                                "class": "btn-primary",
+                                "event": "loadVMapBoFormColumns()",
+                                "glyphicon": "refresh"
+                            }
+                        ]
                     }]
             },
             {
                 "fields": [{
-                        "type": "text",
+                        "type": "editable_select",
                         "name": "search_field",
                         "label": "FORM_SEARCH_FIELD_0",
-                        "nb_cols": 6,
-                        "id": "New_el_11_13_1",
+                        "nb_cols": 5,
                         "tooltip": {
                             "title": "",
                             "content": "FORM_SEARCH_FIELD_0_TOOLTIP",
                             "container": "body"
                         }
+                    }, {
+                        "type": "button",
+                        "class": "btn-group btn-group-sm margin-top-20",
+                        "nb_cols": 1,
+                        "buttons": [{
+                                "type": "button",
+                                "name": "table-datalist",
+                                "label": "FORM_SEARCH_FIELD_0",
+                                "class": "btn-primary",
+                                "event": "loadVMapBoFormColumns()",
+                                "glyphicon": "refresh"
+                            }
+                        ]
                     }]
             },
             {
                 "fields": [{
-                        "type": "text",
+                        "type": "editable_select",
                         "name": "result_field",
                         "label": "FORM_RESULT_FIELD_0",
-                        "nb_cols": 6,
-                        "id": "New_el_12_14_1",
+                        "nb_cols": 5,
                         "tooltip": {
                             "title": "",
                             "content": "FORM_RESULT_FIELD_0_TOOLTIP",
                             "container": "body"
                         }
+                    }, {
+                        "type": "button",
+                        "class": "btn-group btn-group-sm margin-top-20",
+                        "nb_cols": 1,
+                        "buttons": [{
+                                "type": "button",
+                                "name": "table-datalist",
+                                "label": "FORM_RESULT_FIELD_0",
+                                "class": "btn-primary",
+                                "event": "loadVMapBoFormColumns()",
+                                "glyphicon": "refresh"
+                            }
+                        ]
                     }]
             },
             {
diff --git a/module/javascript/app/modules/Cadastre/cadastre.js b/module/javascript/app/modules/Cadastre/cadastre.js
index eaed9561ddf04f859db73cc3d68093fbb45210e4..91a57bf08b978aba916e302d0bbed6393037e661 100644
--- a/module/javascript/app/modules/Cadastre/cadastre.js
+++ b/module/javascript/app/modules/Cadastre/cadastre.js
@@ -274,7 +274,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController = function
             sString = oVmap.checkLink(sString);
         }else{
             sString = oVmap.parseLink(sString, 'link');
-        }
+        }        
         return $sce.trustAsHtml(sString);
     };
 };
@@ -926,7 +926,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
             }
             tmp = Date.now();
             setTimeout(function () {
-                var aSelected = $(parcelleTable).bootstrapTable('getSelections');
+                var aSelected = $(parcelleTable).bootstrapTable('getAllSelections');
                 this_['tablesSelection'][parcelleTable] = aSelected;
             });
         };
@@ -986,7 +986,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
 nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.displayParcelleDescriptiveSheetByTable = function (parcelleTable) {
     oVmap.log('nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.displayParcelleDescriptiveSheetByTable');
 
-    var selectedParcelles = $(parcelleTable).bootstrapTable('getSelections');
+    var selectedParcelles = $(parcelleTable).bootstrapTable('getAllSelections');
 
     if (selectedParcelles.length !== 1) {
         $.notify('Veuillez sélectionner une unique parcelle', 'info');
@@ -1128,7 +1128,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
 nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.displayUrbanismeSheetByTable = function (parcelleTable) {
     oVmap.log('nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.displayUrbanismeSheetByTable');
 
-    var selectedParcelles = $(parcelleTable).bootstrapTable('getSelections');
+    var selectedParcelles = $(parcelleTable).bootstrapTable('getAllSelections');
 
     if (selectedParcelles.length !== 1) {
         $.notify('Veuillez sélectionner une unique parcelle', 'info');
@@ -1482,7 +1482,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
 nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.displayReleveDeProprieteSheetParcelle = function (parcelleTable) {
     oVmap.log('nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.displayReleveDeProprieteSheetTiers');
 
-    var selectedParcelles = $(parcelleTable).bootstrapTable('getSelections');
+    var selectedParcelles = $(parcelleTable).bootstrapTable('getAllSelections');
 
     if (selectedParcelles.length !== 1) {
         $.notify('Veuillez sélectionner une unique parcelle', 'info');
@@ -1508,7 +1508,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
 nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.displayReleveDeProprieteSheetStandard = function (compteTable) {
     oVmap.log('nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.displayReleveDeProprieteSheetStandard');
 
-    var selectedComptes = $(compteTable).bootstrapTable('getSelections');
+    var selectedComptes = $(compteTable).bootstrapTable('getAllSelections');
 
     if (selectedComptes.length !== 1) {
         $.notify('Veuillez sélectionner un unique compte', 'info');
@@ -1535,7 +1535,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
 nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.displayReleveDeProprieteSheetTiers = function (compteTable) {
     oVmap.log('nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.displayReleveDeProprieteSheetTiers');
 
-    var selectedComptes = $(compteTable).bootstrapTable('getSelections');
+    var selectedComptes = $(compteTable).bootstrapTable('getAllSelections');
 
     if (selectedComptes.length !== 1) {
         $.notify('Veuillez sélectionner un unique compte', 'info');
@@ -1583,7 +1583,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
 nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.displayRapportParcelle = function (parcelleTable, rapportType, bOpenWindow) {
     oVmap.log('nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.displayRapportParcelle');
 
-    var selectedParcelles = $(parcelleTable).bootstrapTable('getSelections');
+    var selectedParcelles = $(parcelleTable).bootstrapTable('getAllSelections');
 
     bOpenWindow = goog.isDef(bOpenWindow) ? bOpenWindow : true;
 
@@ -2084,7 +2084,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
  */
 nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.addSelectionFromTable = function (path, param, tableId, tabCode, callBack) {
     oVmap.log('nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.addSelectionFromTable');
-    var tableSelections = $(tableId).bootstrapTable('getSelections');
+    var tableSelections = $(tableId).bootstrapTable('getAllSelections');
     if (this['cadastreAPI_'] === "cadastre") {
         var paramField = param;
     } else {
@@ -2235,7 +2235,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
     tableParam = goog.isDef(tableParam) ? tableParam : param;
 
     var cadastreController = this;
-    var tableSelections = $(tableId).bootstrapTable('getSelections');
+    var tableSelections = $(tableId).bootstrapTable('getAllSelections');
     var url = oVmap['properties']['api_url'] + '/' + path;
 
     var loadHttp = function () {
@@ -2628,7 +2628,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
 
             var data = response['data']['data'];
 
-            // Ajoute le type de voie
+            // Ajoute le type de voie 
             for (var i = 0; i < data.length; i++) {
                 if (goog.isDefAndNotNull(data[i]['L_NATURE_VOIE'])) {
                     data[i]['NOM_VOIE'] = data[i]['L_NATURE_VOIE'] + ' ' + data[i]['DVOILIB'];
@@ -2925,7 +2925,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
             $(tableId).off('check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table');
             $(tableId).on('check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table', function (e, row) {
                 $(parcelleTableId).bootstrapTable('removeAll');
-                cadastreController.getBaseParcellesByProprietaireOnTable(row['ID_COM'], $(tableId).bootstrapTable('getSelections'), parcelleTableId);
+                cadastreController.getBaseParcellesByProprietaireOnTable(row['ID_COM'], $(tableId).bootstrapTable('getAllSelections'), parcelleTableId);
             });
             // Si une seule ligne est proposée, alors on la sélectionne
             if (data.length === 1) {
@@ -3212,7 +3212,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
                 $(invariantsTableId).bootstrapTable('removeAll');
                 $(parcellesTableId).bootstrapTable('removeAll');
 
-                cadastreController.getBatiBaseInvariantsOnTable($(tableId).bootstrapTable('getSelections'), invariantsTableId, parcellesTableId);
+                cadastreController.getBatiBaseInvariantsOnTable($(tableId).bootstrapTable('getAllSelections'), invariantsTableId, parcellesTableId);
             });
 
             // Si une seule ligne est proposée, alors on la sélectionne
@@ -3305,7 +3305,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
                 $(tableId).off('check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table');
                 $(tableId).on('check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table', function (e, row) {
                     $(parcellesTableId).bootstrapTable('removeAll');
-                    cadastreController.getBatiBaseParcellesOnTable($(tableId).bootstrapTable('getSelections'), parcellesTableId);
+                    cadastreController.getBatiBaseParcellesOnTable($(tableId).bootstrapTable('getAllSelections'), parcellesTableId);
                 });
 
                 // Si une seule ligne est proposée, alors on la sélectionne
@@ -3500,7 +3500,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
     }
 
     // Ajoute les infos de la section
-    if ($(tableSection).bootstrapTable('getSelections').length > 0) {
+    if ($(tableSection).bootstrapTable('getAllSelections').length > 0) {
         this.aFormList_.push('veremes_cadastre_section');
 
         // Crée l'onglet correspondant
@@ -3550,7 +3550,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
     }
 
     // Ajoute les infos du lieu dit
-    if ($(tableLieuDit).bootstrapTable('getSelections').length > 0) {
+    if ($(tableLieuDit).bootstrapTable('getAllSelections').length > 0) {
         this.aFormList_.push('veremes_cadastre_lieu_dit');
 
         // Crée l'onglet correspondant
@@ -3615,7 +3615,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
     }
 
     // Ajoute les infos de la Parcelle
-    if ($(tableParcelle).bootstrapTable('getSelections').length > 0) {
+    if ($(tableParcelle).bootstrapTable('getAllSelections').length > 0) {
         this.aFormList_.push('veremes_cadastre_parcelle');
 
         // Crée l'onglet correspondant
@@ -3668,7 +3668,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
     }
 
     // Ajoute les infos de la Voie
-    if ($(tableVoie).bootstrapTable('getSelections').length > 0) {
+    if ($(tableVoie).bootstrapTable('getAllSelections').length > 0) {
         this.aFormList_.push('veremes_cadastre_voie');
 
         // Crée l'onglet correspondant
@@ -3703,7 +3703,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
         this.addSelectionFromSelect(oVmap["properties"]["cadastre"]["api"] + '/parcelles', 'id_par', selectAdresse, 'veremes_cadastre_parcelle');
 
         // Si on choisit de voir toutes les géométries
-    } else if ($(tableVoie).bootstrapTable('getSelections').length > 0 && this['aAdresses'].length > 0) {
+    } else if ($(tableVoie).bootstrapTable('getAllSelections').length > 0 && this['aAdresses'].length > 0) {
         this.aFormList_.push('veremes_cadastre_parcelle');
 
         // Crée l'onglet correspondant
@@ -3730,7 +3730,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
 
     if ($(selectAdresse).val() !== "")
         this.localiseFromSelect(oVmap["properties"]["cadastre"]["api"] + '/parcelles', 'id_par', selectAdresse);
-    else if ($(tableVoie).bootstrapTable('getSelections').length > 0) {
+    else if ($(tableVoie).bootstrapTable('getAllSelections').length > 0) {
         this.localiseFromArray(oVmap["properties"]["cadastre"]["api"] + '/parcelles', 'id_par', this['aAdresses'], 'ID_PAR');
     }
 };
@@ -3775,7 +3775,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
     }
 
     // Ajoute les infos du propriétaire
-    if ($(tableProprietaires).bootstrapTable('getSelections').length > 0) {
+    if ($(tableProprietaires).bootstrapTable('getAllSelections').length > 0) {
         this.aFormList_.push('veremes_cadastre_proprietaire');
 
         // Crée l'onglet correspondant
@@ -3783,13 +3783,13 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
             oVmap.getToolsManager().getInfoContainer().addTab({tabCode: 'veremes_cadastre_proprietaire', tabName: 'Propriétaire', actions: ['delete']});
 
         // Ajoute les infos
-        var proprietaire = $(tableProprietaires).bootstrapTable('getSelections')[0];
+        var proprietaire = $(tableProprietaires).bootstrapTable('getAllSelections')[0];
         this.addSelectionFrom2Values(oVmap["properties"]["cadastre"]["api"] + '/proprietaires', 'DDENOM', proprietaire['DDENOM'], 'ID_COM', proprietaire['ID_COM'], 'veremes_cadastre_proprietaire');
 
     }
 
     // Ajoute les infos du compte
-    if ($(tableComptes).bootstrapTable('getSelections').length > 0) {
+    if ($(tableComptes).bootstrapTable('getAllSelections').length > 0) {
         this.aFormList_.push('veremes_cadastre_compte');
 
         // Crée l'onglet correspondant
@@ -3797,7 +3797,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
             oVmap.getToolsManager().getInfoContainer().addTab({tabCode: 'veremes_cadastre_compte', tabName: 'Compte', actions: ['delete']});
 
         // Ajoute les infos
-        var aComptes = $(tableComptes).bootstrapTable('getSelections');
+        var aComptes = $(tableComptes).bootstrapTable('getAllSelections');
         if (this['cadastreAPI_'] === "cadastre") {
             var id_com = 'ID_COM';
             var dnupro = 'DNUPRO';
@@ -3829,7 +3829,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
     }
 
     // Ajoute les infos de la parcelle
-    if ($(tableParcelles).bootstrapTable('getSelections').length > 0) {
+    if ($(tableParcelles).bootstrapTable('getAllSelections').length > 0) {
         this.aFormList_.push('veremes_cadastre_parcelle');
 
         // Crée l'onglet correspondant
@@ -3837,7 +3837,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
             oVmap.getToolsManager().getInfoContainer().addTab({tabCode: 'veremes_cadastre_parcelle', tabName: 'Parcelle', actions: ['zoom', 'delete']});
 
         // Ajoute les infos
-        var aParcelles = $(tableParcelles).bootstrapTable('getSelections');
+        var aParcelles = $(tableParcelles).bootstrapTable('getAllSelections');
         this.addSelectionFromArray(oVmap["properties"]["cadastre"]["api"] + '/parcelles', 'id_par', aParcelles, 'ID_PAR', 'veremes_cadastre_parcelle');
     }
 
@@ -3897,7 +3897,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
     }
 
     // Ajoute les infos du propriétaire
-    if ($(tableProprietaires).bootstrapTable('getSelections').length > 0) {
+    if ($(tableProprietaires).bootstrapTable('getAllSelections').length > 0) {
         this.aFormList_.push('veremes_cadastre_proprietaire');
 
         // Crée l'onglet correspondant
@@ -3905,19 +3905,19 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
             oVmap.getToolsManager().getInfoContainer().addTab({tabCode: 'veremes_cadastre_proprietaire', tabName: 'Propriétaire', actions: ['delete']});
 
         // Ajoute les infos
-        var proprietaire = $(tableProprietaires).bootstrapTable('getSelections')[0];
+        var proprietaire = $(tableProprietaires).bootstrapTable('getAllSelections')[0];
         this.addSelectionFrom2Values(oVmap["properties"]["cadastre"]["api"] + '/proprietaires', ddenomF, proprietaire['DDENOM'], id_comF, proprietaire['ID_COM'], 'veremes_cadastre_proprietaire');
     }
 
     // Ajoute les infos du compte
-    if ($(tableComptes).bootstrapTable('getSelections').length > 0) {
+    if ($(tableComptes).bootstrapTable('getAllSelections').length > 0) {
         this.aFormList_.push('veremes_cadastre_compte');
 
         // Crée l'onglet correspondant
         if (oVmap.getToolsManager().getInfoContainer().getTabByCode('veremes_cadastre_compte') === undefined)
             oVmap.getToolsManager().getInfoContainer().addTab({tabCode: 'veremes_cadastre_compte', tabName: 'Compte', actions: ['delete']});
 
-        var aComptes = $(tableComptes).bootstrapTable('getSelections');
+        var aComptes = $(tableComptes).bootstrapTable('getAllSelections');
         if (this['cadastreAPI_'] === "cadastre") {
             var id_com = 'ID_COM';
             var dnupro = 'DNUPRO';
@@ -3951,7 +3951,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
     }
 
     // Ajoute les infos de l'invariant
-    if ($(tableInvariants).bootstrapTable('getSelections').length > 0) {
+    if ($(tableInvariants).bootstrapTable('getAllSelections').length > 0) {
         this.aFormList_.push('veremes_cadastre_invariant');
 
         // Crée l'onglet correspondant
@@ -3963,7 +3963,7 @@ nsVmap.nsToolsManager.nsModules.Cadastre.prototype.cadastreController.prototype.
     }
 
     // Ajoute les infos de la parcelle
-    if ($(tableParcelles).bootstrapTable('getSelections').length > 0) {
+    if ($(tableParcelles).bootstrapTable('getAllSelections').length > 0) {
         this.aFormList_.push('veremes_cadastre_parcelle');
 
         // Crée l'onglet correspondant
diff --git a/module/javascript/app/vmap/map/map.js b/module/javascript/app/vmap/map/map.js
index 7c0ba9a4a13165ccacc01ee5c7584bd9b561101d..fbd9fabb1a9b9305ce02faa83d8b38f4bfa9b227 100644
--- a/module/javascript/app/vmap/map/map.js
+++ b/module/javascript/app/vmap/map/map.js
@@ -389,6 +389,12 @@ nsVmap.Map = function () {
     if (oVmap['properties']['is_mobile']) {
         this_.trackGPSPosition();
     }
+
+    // Termine les dessins par le clic droit
+    this.oOpenLayersMap_.getViewport().addEventListener('contextmenu', function (evt) {
+        evt.preventDefault();
+        this_.termineDrawInteractions();
+    })
 };
 
 /**
@@ -1209,6 +1215,29 @@ nsVmap.Map.prototype.trackGPSPosition = function () {
     }
 };
 
+/**
+ * Termine all the draw interactions
+ *  
+ */
+nsVmap.Map.prototype.termineDrawInteractions = function () {
+    oVmap.log('nsVmap.Map.prototype.termineDrawInteractions');
+
+    for (var i = 0; i < this.vmapInteractions_.length; i++) {
+        if (this.vmapInteractions_[i] instanceof ol.interaction.Draw) {
+            try {
+                // Termine le dessin en cours
+                this.vmapInteractions_[i].finishDrawing();
+                // Desactive la fonctionnalié pour ne pas commencer un autre dessin
+                this.vmapInteractions_[i].setActive(false);
+                // Réactive la fonctionnalité
+                setTimeout(angular.bind(this, function(oDrawInteraction){
+                    oDrawInteraction.setActive(true);
+                }, this.vmapInteractions_[i]), 500);
+            } catch (e) {}
+        }
+    }
+};
+
 /********************************************
  *           INTERFACE MOBILE
  *******************************************/
diff --git a/module/javascript/app/vmap/map/mapcompare.js b/module/javascript/app/vmap/map/mapcompare.js
new file mode 100644
index 0000000000000000000000000000000000000000..b3304a3c7800e0e991cc42b0c80bd0a11e4ee882
--- /dev/null
+++ b/module/javascript/app/vmap/map/mapcompare.js
@@ -0,0 +1,807 @@
+/* global nsVmap, ol, oVmap, goog, angular, vitisApp, bootbox */
+
+/**
+ * @author: Anthony Borghi
+ * @Description: Fichier contenant la classe nsVmap.MapCompare
+ * cette classe permet l'initialisation de la carte
+ */
+
+goog.provide('nsVmap.MapCompare');
+
+goog.require('oVmap');
+
+goog.require('ol.Map');
+goog.require('ol.View');
+goog.require('MapJSON');
+goog.require('ol.Overlay');
+goog.require('ol.source.Vector');
+goog.require('ol.layer.Vector');
+goog.require('goog.async.AnimationDelay');
+
+/**
+ * @classdesc
+ * Class {@link nsVmap.MapCompare}: initializes the map to compare
+ *
+ * @constructor
+ * @export
+ */
+nsVmap.MapCompare = function () {
+    oVmap.log("nsVmap.MapCompare");
+
+    var this_ = this;
+
+    /**
+     * Map layers
+     * @type {Array.<ol.layer>}
+     * @private
+     */
+    this.olLayers_ = [];
+
+    /**
+     * Map view
+     * @type {ol.View}
+     * @private
+     */
+    this.olView_ = new ol.View({
+        center: [0, 0],
+        zoom: 2
+    });
+
+    /**
+     * Map
+     * @type {ol.map}
+     * @private
+     */
+    this.oOpenLayersMap_ = new ol.Map({
+        layers: this.olLayers_,
+        view: this.olView_,
+        moveTolerance: 5
+    });
+
+    this.oOpenLayersMap_.getViewport().setAttribute('id', 'map1Compare');
+    /**
+     * Contient les évènements ajoutés sur la carte par la méthode addEventOnMap ou setEventOnMap
+     * @type {array}
+     * @private
+     */
+    this.vmapEvents_ = [];
+
+    /**
+     * Contient les évènements ajoutés sur la carte par la méthode addDrawInteraction ou setDrawInteraction
+     * @type {array}
+     * @private
+     */
+    this.vmapInteractions_ = [];
+
+    /**
+     * Contient les tooltips ajoutés par addTooltip
+     * @type {array}
+     * @private
+     */
+    this.vmapOverlays_ = [];
+
+    /**
+     * Initialisé dans le controlleur
+     * @type {nsVmap.Map.MapTooltip}
+     * @private
+     */
+    this.vmapTooltip_ = {};
+
+    // Ajoute les couches à reprojeter en cas de changement de carte dans layersToTransform_
+    this.layersToTransform_ = [];
+
+    // Vide les controls par défaut
+    var controls = this.oOpenLayersMap_.getControls().getArray();
+    for (var i = 0; i < controls.length; i++) {
+        this.oOpenLayersMap_.removeControl(controls[i]);
+    }
+}
+
+/**
+ * nsVmap.Map.oOpenLayersMap_ getter
+ * @return {ol.map} Used map
+ * @export
+ * @api experimental
+ */
+nsVmap.MapCompare.prototype.getOLMap = function () {
+    return this.oOpenLayersMap_;
+};
+
+/**
+ * nsVmap.Map.olView_ setter
+ * @param {ol.View} view View to use
+ * @export
+ * @api experimental
+ */
+nsVmap.MapCompare.prototype.setOpenLayersView = function (view) {
+    this.olView_ = view;
+    this.oOpenLayersMap_.setView(this.olView_);
+};
+
+/**
+ * Use this function to add a new vector layer
+ * @param {object} opt_options
+ * @param {object} opt_options.style
+ * @param {object} opt_options.extent
+ * @param {object} opt_options.minResolution
+ * @param {object} opt_options.maxResolution
+ * @param {object} opt_options.opacity
+ * @param {object} opt_options.properties
+ * @param {object} opt_options.visible
+ * @param {object} opt_options.zIndex
+ * @returns {undefined}
+ */
+nsVmap.MapCompare.prototype.addVectorLayer = function (opt_options) {
+    oVmap.log('nsVmap.MapCompare.prototype.addVectorLayer');
+
+    var vectorLayer = new ol.layer.Vector({
+        map: this.oOpenLayersMap_,
+        source: new ol.source.Vector({
+            useSpatialIndex: false
+        }),
+        updateWhileAnimating: true,
+        updateWhileInteracting: true
+    });
+
+    if (goog.isDef(opt_options)) {
+        if (goog.isDef(opt_options.style))
+            vectorLayer.setStyle(opt_options.style);
+
+        if (goog.isDef(opt_options.extent))
+            vectorLayer.setExtent(opt_options.extent);
+
+        if (goog.isDef(opt_options.minResolution))
+            vectorLayer.setMinResolution(opt_options.minResolution);
+
+        if (goog.isDef(opt_options.maxResolution))
+            vectorLayer.setMaxResolution(opt_options.maxResolution);
+
+        if (goog.isDef(opt_options.opacity))
+            vectorLayer.setOpacity(opt_options.opacity);
+
+        if (goog.isDef(opt_options.properties))
+            vectorLayer.setProperties(opt_options.properties);
+
+        if (goog.isDef(opt_options.visible))
+            vectorLayer.setVisible(opt_options.visible);
+
+        if (goog.isDef(opt_options.zIndex))
+            vectorLayer.setZIndex(opt_options.zIndex);
+    }
+
+    // Ajoute la couche à layersToTransform_ pour que les features soient reprojetés en cas de changement de projection
+    this.layersToTransform_.push(vectorLayer);
+
+    return vectorLayer;
+};
+
+/**
+ * Remove events and interactions and then add a interaction
+ * @param {ol.interaction.Interaction} interaction
+ * @param {string|undefined} currentAction name of the current action
+ * @returns {ol.interaction.Interaction}
+ */
+nsVmap.MapCompare.prototype.setInteraction = function (interaction, currentAction) {
+    oVmap.log('nsVmap.MapCompare.prototype.setInteraction');
+    // Supprime les anciens évènements et interractions
+    this.removeActionsOnMap();
+    // Ajoute la nouvelle interaction
+    this.addInteraction(interaction);
+    // Définit l'action en cours
+    if (goog.isDef(currentAction))
+        this.setCurrentAction(currentAction);
+    return interaction;
+};
+
+/**
+ * Add a interaction
+ * @param {ol.interaction.Interaction} interaction
+ * @param {string|undefined} currentAction name of the current action
+ * @returns {ol.interaction.Interaction}
+ */
+nsVmap.MapCompare.prototype.addInteraction = function (interaction, currentAction) {
+    oVmap.log('nsVmap.MapCompare.prototype.addInteraction');
+    // Ajout de l'interaction
+    this.oOpenLayersMap_.addInteraction(interaction);
+    // Stocke l'interaction
+    this.vmapInteractions_.push(interaction);
+    // Définit l'action en cours
+    if (goog.isDef(currentAction))
+        this.setCurrentAction(currentAction);
+    return interaction;
+};
+
+/**
+ * currentAction setter
+ * @param {string} currentAction
+ * @export
+ */
+nsVmap.MapCompare.prototype.setCurrentAction = function (currentAction) {
+    var scope = angular.element($("#map1Compare")).scope();
+    scope.$evalAsync(function (scope) {
+        scope['ctrl']['currentAction'] = currentAction;
+    });
+};
+
+/**
+ * Remove the mapTooltip and the actions added by addEventOnMap, setEventOnMap, addDrawInteraction or setDrawInteraction
+ * @returns {undefined}
+ * @export
+ */
+nsVmap.MapCompare.prototype.removeActionsAndTooltips = function () {
+    this.removeActionsOnMap();
+    //this.getMapTooltip().hide();
+    for (var i = 0; i < this.vmapOverlays_.length; i++) {
+        this.vmapOverlays_[i].getElement().style.display = "none";
+    }
+};
+
+/**
+ * Remove the events and draw interactions added by addEventOnMap, setEventOnMap, addDrawInteraction or setDrawInteraction
+ * @returns {undefined}
+ * @export
+ */
+nsVmap.MapCompare.prototype.removeActionsOnMap = function () {
+    oVmap.log('nsVmap.Map.prototype.removeActionsOnMap');
+    // Supprime les évènements
+    for (var i = 0; i < this.vmapEvents_.length; i++) {
+        ol.Observable.unByKey(this.vmapEvents_[i]);
+    }
+
+    // Supprime les interractions
+    for (var i = 0; i < this.vmapInteractions_.length; i++) {
+
+        // Supprime les features occasionelles
+        if (goog.isDef(this.vmapInteractions_[i].getFeatures))
+            this.vmapInteractions_[i].getFeatures().clear();
+        this.oOpenLayersMap_.removeInteraction(this.vmapInteractions_[i]);
+    }
+
+    // Définit l'action en cours
+    this.setCurrentAction('');
+};
+
+/**
+ * Set a event on the map and remove the others.
+ * @param {string|Array.<string>} type The event type or array of event types.
+ * @param {function(?): ?} listener The listener function.
+ * @param {Object=} opt_this The object to use as `this` in `listener`.
+ * @param {string|undefined} currentAction name of the current action
+ * @return {goog.events.Key} Unique key for the listener.
+ * @export
+ */
+nsVmap.MapCompare.prototype.setEventOnMap = function (type, listener, opt_this, currentAction) {
+    oVmap.log('nsVmap.Map.prototype.setEventOnMap');
+    if (!goog.isDef(type)) {
+        console.error('setEventOnMap: type not defined');
+        return 0;
+    }
+
+    if (!goog.isDef(listener)) {
+        console.error('setEventOnMap: listener not defined');
+        return 0;
+    }
+
+    opt_this = goog.isDef(opt_this) ? opt_this : '';
+    // Supprime les anciens évènements et interractions
+    this.removeActionsOnMap();
+    // Ajoute le nouvel évènement
+    var event = this.addEventOnMap(type, listener, opt_this);
+    // Définit l'action en cours
+    if (goog.isDef(currentAction))
+        this.setCurrentAction(currentAction);
+    return event;
+};
+
+/**
+ * Add a certain type of event on the map.
+ * @param {string|Array.<string>} type The event type or array of event types.
+ * @param {function(?): ?} listener The listener function.
+ * @param {Object=} opt_this The object to use as `this` in `listener`.
+ * @param {string|undefined} currentAction name of the current action
+ * @return {goog.events.Key} Unique key for the listener.
+ * @export
+ */
+nsVmap.MapCompare.prototype.addEventOnMap = function (type, listener, opt_this, currentAction) {
+
+    if (!goog.isDef(type)) {
+        console.error('setEventOnMap: type not defined');
+        return 0;
+    }
+
+    if (!goog.isDef(listener)) {
+        console.error('setEventOnMap: listener not defined');
+        return 0;
+    }
+
+    opt_this = goog.isDef(opt_this) ? opt_this : '';
+    // Active l'évènement
+    var event = this.oOpenLayersMap_.on(type, listener, opt_this);
+    // Stocke l'évènement
+    this.vmapEvents_.push(event);
+    // Définit l'action en cours
+    if (goog.isDef(currentAction))
+        this.setCurrentAction(currentAction);
+    return event;
+};
+
+/**
+ * Get the current scale
+ * @param {object} opt_options
+ * @param {boolean|undefined} opt_options.pretty true for pretty format (ex: 1:25,000)
+ * @returns {Number|String}
+ * @export
+ */
+nsVmap.MapCompare.prototype.getScale = function (opt_options) {
+    oVmap.log('nsVmap.MapCompare.prototype.getScale');
+
+    opt_options = goog.isDef(opt_options) ? opt_options : {};
+    opt_options['pretty'] = goog.isDef(opt_options['pretty']) ? opt_options['pretty'] : false;
+
+    var wgs84Sphere_ = new ol.Sphere(6378137);
+    var projection = this.oOpenLayersMap_.getView().getProjection();
+
+    var map = oVmap.getMapCompare().getOLMap();
+
+    // récupère les coordonnées d'une ligue de 1cm (avec le zoom en cours)
+    var line = map.getView().calculateExtent([37.795275591, 0]);
+    var c1 = ol.proj.transform([line[0], line[1]], projection, 'EPSG:4326');
+    var c2 = ol.proj.transform([line[2], line[3]], projection, 'EPSG:4326');
+
+    // Récuère la longueur sur la carte de la ligne de 1cm
+    var length = wgs84Sphere_.haversineDistance(c1, c2);
+
+    // donc 1m sur la carte correspond à (length mètres dans la réalité x 100)
+    var scale = length * 100;
+
+    // Rend l'échelle sous format (1:25,000)
+    if (opt_options['pretty'] === true) {
+        scale = this.getPrettyScale(scale);
+    }
+
+    return scale;
+};
+
+/**
+ * Set the map scale
+ * @param {number} scale
+ * @returns {number} new scale
+ * @export
+ */
+nsVmap.MapCompare.prototype.setScale = function (scale) {
+    oVmap.log('nsVmap.Map.prototype.setScale');
+
+    // calcule et va à l'échelle celon une règle de 3
+    var currentScale = this.getScale();
+    var currentResolution = this.oOpenLayersMap_.getView().getResolution();
+
+    var scaleResolution = scale * currentResolution / currentScale;
+    this.oOpenLayersMap_.getView().setResolution(scaleResolution);
+
+    // Ajuste l'échelle en augementant la résolution
+    currentScale = this.getScale();
+
+    oVmap.log(currentScale);
+};
+
+/**
+ * Get the scale like (1:25,000)
+ * @param {number} scale
+ * @returns {String} scale (pretty)
+ */
+nsVmap.MapCompare.prototype.getPrettyScale = function (scale) {
+
+    // Rend l'échelle sous format (1:25,000)
+    scale = String(Math.round(scale));
+    var j = 1;
+    for (var i = scale.length - 1; i > 0; i--) {
+        if (j % 3 === 0)
+            scale = scale.slice(0, i) + ',' + scale.slice(i + Math.abs(0));
+        j++;
+    }
+    scale = '1:' + scale;
+
+    return scale;
+};
+
+/**
+ * App-specific directive wrapping the ngeo map directive. The directive's
+ * controller has a property "map" including a reference to the OpenLayers
+ * map.
+ *
+ * @return {angular.Directive} The directive specs.
+ * @constructor
+ */
+nsVmap.MapCompare.prototype.mapCompareDirective = function () {
+    oVmap.log("nsVmap.MapCompare.prototype.mapCompareDirective");
+    return {
+        restrict: 'E',
+        scope: {
+            'map': '=appMap',
+            'currentAction': '=appAction'
+        },
+        controller: 'AppMapCompareController',
+        controllerAs: 'ctrl',
+        bindToController: true,
+        template: '<div id="olMapCompare"></div>'
+    };
+};
+
+/**
+ * The application's main controller.
+ * @ngInject
+ * @constructor
+ */
+nsVmap.MapCompare.prototype.mapCompareController = function ($scope, $window, $element, $timeout) {
+    oVmap.log("nsVmap.MapCompare.prototype.mapController");
+    var this_ = this;
+
+    /**
+     * @private
+     */
+    this.$scope_ = $scope;
+
+    /**
+     * @type {object}
+     */
+    this.element = $element;
+
+    /**
+     * Animation duration
+     * @type Number
+     * @private
+     */
+    this.duration = 1000;
+
+    /**
+     * Timestamp of the last map center sync
+     */
+    this.lastMapSyncCenter_ = 0;
+
+    /**
+     * Timestamp of the last map compare center sync
+     */
+    this.lastCompareMapSyncCenter_ = 0;
+
+    /**
+     * Timestamp of the last map scale sync
+     */
+    this.lastMapSyncScale_ = 0;
+
+    /**
+     * Timestamp of the last map compare scale sync
+     */
+    this.lastCompareMapSyncScale_ = 0;
+
+    /**
+     * @type {ol.Map}
+     * @private
+     */
+    this.map = this['map'];
+    /**
+     * @type {ol.Overlay}
+     * @private
+     */
+    this.targetOverlay_ = null;
+
+    /**
+     * Objet permettant de lancer des fonctions utiles
+     * pour parser la définition de la carte
+     * @type MapJSON
+     */
+    var oMapJSON = new MapJSON({
+        'properties': oVmap['properties']
+    });
+
+    var tileSize = [oVmap['properties']['vmap']['wmsTilesWidth'], oVmap['properties']['vmap']['wmsTilesHeight']];
+
+    /**
+     * Contains the tileloaderror and imageloaderror events
+     * @private
+     */
+    this.loadErrorEventsContainer_ = [];
+
+    this.map.setTarget('olMapCompare');
+
+    $scope.$on("mapCompareChanged", function(){
+        // MAJ de la taille du composant
+        this_.map.setSize([document.getElementById('olMapCompare').offsetWidth, document.getElementById('olMapCompare').offsetHeight]);
+        if (this_.map.getLayers().getArray().length > 0)
+        this_.map.getLayers().clear();
+
+        var tree_ = oVmap.getMapManager().getCompareLayersTree();
+        var olView_ = oMapJSON.getViewFromDef(tree_, {
+            'size': this_.map.getSize(),
+            'tileSize': tileSize
+        });
+
+        var olLayers_ = oMapJSON.getLayersFromDef(tree_, {
+            'size': this_.map.getSize(),
+            'tileSize': tileSize
+        });
+
+        // Définit la vue de la carte
+        this_.addView(olView_);
+
+        // Définit les couches de la carte
+        for (var i = 0; i < olLayers_.length; i++) {
+            this_.addLayer(olLayers_[i]);
+        }
+        $timeout(function(){
+            this_.synchronizeMap();
+        }, 10);
+
+        // Rafraichit l'échelle
+        setTimeout(function () {
+            this_.updateCompareScaleMap();
+        });
+
+        // Affiche le nom de la carte
+        this_.displayMapName();
+
+        // Affiche le nom de la carte
+        this_.displayMapProj();
+    })
+
+    /**
+     * Update the map size with animation
+     * @type goog.async.AnimationDelay
+     */
+    this.animationDelay = new goog.async.AnimationDelay(
+            function () {
+                this_.map.updateSize();
+                this_.map.renderSync();
+                if (goog.now() - start < this_.duration) {
+                    this_.animationDelay.start();
+                }
+            }, $window);
+
+    /**
+     * Watch for resizing
+     */
+    $scope.$watchCollection(function () {
+        return [this_.element.children()[0]['clientWidth'], this_.element.children()[0]['clientHeight']];
+    }, function () {
+        this_.startAnimation();
+    });
+};
+
+// Définit les directives et controlleurs
+oVmap.module.directive('appMapCompare', nsVmap.MapCompare.prototype.mapCompareDirective);
+oVmap.module.controller('AppMapCompareController', nsVmap.MapCompare.prototype.mapCompareController);
+
+/**
+ * Update the map size with animation
+ * @returns {undefined}
+ * @export
+ */
+nsVmap.MapCompare.prototype.mapCompareController.prototype.startAnimation = function () {
+    oVmap.log('nsVmap.MapCompare.prototype.mapCompareController.prototype.startAnimation');
+    start = goog.now();
+    this.animationDelay.stop();
+    this.animationDelay.start();
+};
+
+/**
+ * Update the map size with animation
+ * @returns {undefined}
+ */
+nsVmap.MapCompare.prototype.mapCompareController.prototype.synchronizeMap = function () {
+    oVmap.log('nsVmap.MapCompare.prototype.mapCompareController.prototype.synchronizeMap');
+
+    var this_ = this;
+
+    // Synchro Échelle
+    this_.map.getTargetElement().addEventListener('mouseleave', function(){
+        oVmap.getMap().getOLMap().on("moveend", this_.updateCompareScaleMap, this_);
+        this_.map.un("moveend", this_.updateScaleMap, this_);
+    });
+    this_.map.getTargetElement().addEventListener('mouseenter', function(){
+      oVmap.getMap().getOLMap().un("moveend", this_.updateCompareScaleMap, this_);
+      this_.map.on("moveend", this_.updateScaleMap, this_);
+    });
+
+    // Synchro centre
+    oVmap.getMap().getOLMap().on("pointerdrag", this_.updateCenterCompareMap, this_);
+    this_.map.on("pointerdrag", this_.updateCenterMap, this_);
+
+    // Synchro curseur sur l'autre carte
+    oVmap.getMap().getOLMap().on('pointermove', function(e){
+      var coord = e.coordinate;
+      //si le composant existe sur l'autre composant on le supprime
+      if(angular.element(".over-map-compare.ol-target-overlay").length > 0){
+        this_.targetOverlay_.setPosition(undefined);
+        this_.map.removeOverlay(this_.targetOverlay_);
+        this_.targetOverlay_ = undefined;
+        angular.element(".over-map-compare.ol-target-overlay").remove();
+      }
+      // si le composant n'existe pas on le crée
+      if (!this_.targetOverlay_){
+        var element = document.createElement("div");
+    		element.classList.add("ol-target");
+    		this_.targetOverlay_ = new ol.Overlay({ 'element': element });
+    		this_.targetOverlay_.setPositioning('center-center');
+    		this_.map.addOverlay(this_.targetOverlay_);
+    		element.parentElement.classList.add("ol-target-overlay");
+    		element.parentElement.classList.add("over-map");
+    		// hack to render targetOverlay before positioning it
+    		this_.targetOverlay_.setPosition([0,0]);
+    	}
+
+      var oldProjection = oVmap.getMap().getOLMap().getView().getProjection().getCode();
+      var newProjection = this_.map.getView().getProjection().getCode();
+
+      var convertCoord = ol.proj.transform(coord, oldProjection, newProjection)
+
+    	this_.targetOverlay_.setPosition(convertCoord);
+    });
+    this_.map.on('pointermove', function(e){
+      var coord = e.coordinate;
+      //si le composant existe sur l'autre composant on le supprime
+      if(angular.element(".over-map.ol-target-overlay").length > 0){
+        this_.targetOverlay_.setPosition(undefined);
+        oVmap.getMap().getOLMap().removeOverlay(this_.targetOverlay_);
+        this_.targetOverlay_ = undefined;
+        angular.element(".over-map-compare.ol-target-overlay").remove();
+      }
+      // si le composant n'existe pas on le crée
+      if (!this_.targetOverlay_){
+        var element = document.createElement("div");
+        element.classList.add("ol-target");
+        this_.targetOverlay_ = new ol.Overlay({ 'element': element });
+        this_.targetOverlay_.setPositioning('center-center');
+        oVmap.getMap().getOLMap().addOverlay(this_.targetOverlay_);
+        element.parentElement.classList.add("ol-target-overlay");
+        element.parentElement.classList.add("over-map-compare");
+        // hack to render targetOverlay before positioning it
+        this_.targetOverlay_.setPosition([0,0]);
+      }
+
+      var oldProjection = this_.map.getView().getProjection().getCode();
+      var newProjection = oVmap.getMap().getOLMap().getView().getProjection().getCode();
+
+      var convertCoord = ol.proj.transform(coord, oldProjection, newProjection)
+
+      this_.targetOverlay_.setPosition(convertCoord);
+    });
+};
+
+/**
+ * Update the map extent with animation
+ * @returns {undefined}
+ */
+nsVmap.MapCompare.prototype.mapCompareController.prototype.updateCompareScaleMap = function(e) { console.log('updateCompareScaleMap');
+    var this_ = this
+    this_.updateCenterCompareMap();
+    oVmap.getMapCompare().setScale(oVmap.getMap().getScale());
+
+    this.lastCompareMapSyncScale_ = Date.now();
+}
+
+/**
+ * Update the map extent with animation
+ * @returns {undefined}
+ */
+nsVmap.MapCompare.prototype.mapCompareController.prototype.updateScaleMap = function(e) { console.log('updateScaleMap');
+    var this_ = this
+    this_.updateCenterMap();
+    oVmap.getMap().setScale(oVmap.getMapCompare().getScale());
+
+    this.lastMapSyncScale_ = Date.now();
+}
+
+/**
+* Update the map extent with animation
+* @returns {undefined}
+*/
+nsVmap.MapCompare.prototype.mapCompareController.prototype.updateCenterMap = function(e) {
+
+    var this_ = this
+    // Récupère l'étendue de la carte principale
+    var oldCenter = this_.map.getView().getCenter();
+
+    // Récupère l'ancienne et la nouvelle projection
+    var newProjection = oVmap.getMap().getOLMap().getView().getProjection().getCode();
+    var oldProjection = this_.map.getView().getProjection().getCode();
+
+    var newCenter = ol.proj.transform(oldCenter, oldProjection, newProjection);
+    oVmap.getMap().getOLMap().getView().setCenter(newCenter);
+
+    this.lastMapSyncCenter_ = Date.now();
+}
+
+/**
+* Update the map extent with animation
+* @returns {undefined}
+*/
+nsVmap.MapCompare.prototype.mapCompareController.prototype.updateCenterCompareMap = function(e) {
+
+    var this_ = this;
+    // Récupère l'étendue de la carte principale
+    var oldCenter = oVmap.getMap().getOLMap().getView().getCenter();
+
+    // Récupère l'ancienne et la nouvelle projection
+    var oldProjection = oVmap.getMap().getOLMap().getView().getProjection().getCode();
+    var newProjection = this_.map.getView().getProjection().getCode();
+
+    var newCenter = ol.proj.transform(oldCenter, oldProjection, newProjection);
+    this_['map'].getView().setCenter(newCenter);
+
+    this.lastCompareMapSyncCenter_ = Date.now();
+}
+
+/**
+ * Add a layer on the map
+ * @param {object} olLayer
+ */
+nsVmap.MapCompare.prototype.mapCompareController.prototype.addLayer = function (olLayer) {
+    oVmap.log('nsVmap.MapCompare.prototype.mapCompareController.prototype.addLayer');
+    this['map'].addLayer(olLayer);
+};
+
+/**
+ * Add the olView
+ * @param {object} olView
+ * @returns {undefined}
+ */
+nsVmap.MapCompare.prototype.mapCompareController.prototype.addView = function (olView) {
+    oVmap.log('nsVmap.nsMapManager.LayersTree.prototype.LayertreeController.prototype.addView');
+
+    // Récupère l'étendue de la carte principale
+    var oldExtent = oVmap.getMap().getOLMap().getView().calculateExtent(this['map'].getSize());
+
+    // Récupère l'ancienne et la nouvelle projection
+    var oldProjection = oVmap.getMap().getOLMap().getView().getProjection().getCode();
+    var newProjection = olView.getProjection().getCode();
+
+    // Set le home position pour cette vue
+    olView.set('homePosition', {
+        center: olView.getCenter(),
+        resolution: olView.getResolution()
+    });
+
+    oVmap.getMapCompare().setOpenLayersView(olView);
+    this['map'].setView(olView);
+    this['proj'] = olView.getProjection().getCode();
+
+    // Reprojette en cas de changment de carte
+    if (goog.isDef(oldProjection) && goog.isDef(newProjection) && goog.isDef(oldExtent) /*&& goog.isDef(oldPosition)*/) {
+        // Reprojette l'étendue
+        var newExtent = ol.proj.transformExtent(oldExtent, oldProjection, newProjection);
+        this['map'].getView().fit(newExtent, {
+            nearest: true
+        });
+    }
+};
+
+/**
+ * Display the map name tool
+ */
+nsVmap.MapCompare.prototype.mapCompareController.prototype.displayMapName = function () {
+    oVmap.log('nsVmap.nsMapManager.LayersTree.prototype.LayertreeController.prototype.displayMapName');
+
+    if ($("#map-name-compare").length == 0) {
+        $('#olMapCompare').children().children('.ol-overlaycontainer-stopevent').append('<div class="ol-map-name ol-map-name-compare ol-unselectable"><span id="map-name-compare" class="ol-control"></span></div>');
+    }
+
+    var vMapCatalog = oVmap.getMapManager().getMapCatalog();
+    for (var i = 0; i < vMapCatalog['maps'].length; i++) {
+        if (vMapCatalog['maps'][i]['compare'] === true) {
+            var currentMapName = vMapCatalog['maps'][i]['name'];
+        }
+    }
+    $("#map-name-compare").html(currentMapName);
+}
+
+/**
+ * Display the map proj tool
+ */
+nsVmap.MapCompare.prototype.mapCompareController.prototype.displayMapProj = function () {
+    oVmap.log('nsVmap.nsMapManager.LayersTree.prototype.LayertreeController.prototype.displayMapProj');
+
+    if ($("#current-projection-compare").length == 0) {
+        $('#olMapCompare').children().children('.ol-overlaycontainer-stopevent').append('<div class="ol-current-projection ol-unselectable ol-current-projection-compare"><span id="current-projection-compare" class="ol-control"></span></div>');
+    }
+
+    $("#current-projection-compare").html(oVmap['oProjections'][oVmap.getMapCompare().getOLMap().getView().getProjection().getCode()]);
+}
diff --git a/module/javascript/app/vmap/mapmanager/layerstree.js b/module/javascript/app/vmap/mapmanager/layerstree.js
index 673cb4e0f66ff2e60cc0b2faab5137030da12bb0..2a5fe743b519e0186dae873e6317327fee403212 100644
--- a/module/javascript/app/vmap/mapmanager/layerstree.js
+++ b/module/javascript/app/vmap/mapmanager/layerstree.js
@@ -117,6 +117,19 @@ nsVmap.nsMapManager.LayersTree.prototype.LayertreeController = function ($scope,
      */
     $scope['tree'] = oVmap.getMapManager().getLayersTree();
 
+
+    /**
+     * The map compare layersTree
+     * @type {object}
+     */
+    $scope['compareTree'] = {};
+
+
+    /**
+     * The active map
+     */
+    $scope['activeMap'] = 1;
+
     /**
      * The current properties
      */
@@ -194,6 +207,17 @@ nsVmap.nsMapManager.LayersTree.prototype.LayertreeController = function ($scope,
 };
 oVmap.module.controller('AppLayertreeController', nsVmap.nsMapManager.LayersTree.prototype.LayertreeController);
 
+/**
+ * Resize the layertools
+ */
+nsVmap.nsMapManager.LayersTree.prototype.LayertreeController.prototype.resize = function () {
+    oVmap.log('nsVmap.nsMapManager.LayersTree.LayertreeController.resize');
+
+    setTimeout(function () {
+        oVmap.resizeLayerTools();
+    });
+}
+
 /**
  * Set a layer visible or not
  * @param {ol.layer.Base} olLayer
@@ -270,6 +294,8 @@ nsVmap.nsMapManager.LayersTree.prototype.LayertreeController.prototype.setGroupV
     }
 
     this.memoriseGroupVisible(node);
+
+    oVmap['scope'].$broadcast('layersChanged');
 };
 
 /**
@@ -350,6 +376,14 @@ nsVmap.nsMapManager.LayersTree.prototype.LayertreeController.prototype.reloadTre
     // relance le chargement des couches avec le nouvel arbre
     this.loadTree();
 
+    // Arbre pour la comparaison
+    if(this.scope_["$root"]["compare_enabled"]){
+        var oCompareTree = jQuery.extend(true, {}, oVmap.getMapManager().getCompareLayersTree());
+        this.scope_['compareTree'] = oCompareTree;
+    } else {
+        this.scope_['compareTree'] = {};
+    }
+
     oVmap.resizeLayerTools(false);
 };
 
@@ -638,6 +672,20 @@ nsVmap.nsMapManager.LayersTree.prototype.LayertreeController.prototype.closeLaye
             }
         }
     }
+
+    if (goog.isDefAndNotNull(this.scope_['compareTree'])) {
+        if (goog.isArray(this.scope_['compareTree']['children'])) {
+            for (var i = 0; i < this.scope_['compareTree']['children'].length; i++) {
+                if (goog.isDefAndNotNull(this.scope_['compareTree']['children'][i]['children'])) {
+                    for (var ii = 0; ii < this.scope_['compareTree']['children'][i]['children'].length; ii++) {
+                        if (goog.isDefAndNotNull(this.scope_['compareTree']['children'][i]['children'][ii]['olLayer'])) {
+                            this.scope_['compareTree']['children'][i]['children'][ii]['displayedMenu'] = false;
+                        }
+                    }
+                }
+            }
+        }
+    }
 };
 
 /**
diff --git a/module/javascript/app/vmap/mapmanager/maplegend.js b/module/javascript/app/vmap/mapmanager/maplegend.js
index 48d2e54ec1915eb1e28b91b4908630d62aa5b32c..c6759068d12cdca81139276cf329080ba8fe1adf 100644
--- a/module/javascript/app/vmap/mapmanager/maplegend.js
+++ b/module/javascript/app/vmap/mapmanager/maplegend.js
@@ -136,7 +136,17 @@ nsVmap.nsMapManager.MapLegend.prototype.maplegendController = function ($scope)
     /**
      * @private
      */
-    this['aUrls'] = [];
+    this['oUrls'] = {};
+
+    /**
+     * @private
+     */
+    this['oCompareUrls'] = {};
+
+    /**
+     * The active map
+     */
+    $scope['activeMap'] = 1;
 
     /**
      * Contains the events stocked by listenLayers()
@@ -158,6 +168,18 @@ nsVmap.nsMapManager.MapLegend.prototype.maplegendController = function ($scope)
     });
 };
 
+
+/**
+ * Resize the layertools
+ */
+nsVmap.nsMapManager.MapLegend.prototype.maplegendController.prototype.resize = function () {
+    oVmap.log('nsVmap.nsMapManager.MapLegend.maplegendController.resize');
+
+    setTimeout(function () {
+        oVmap.resizeLayerTools();
+    });
+}
+
 /**
  * Loads the legend
  * @export
@@ -165,18 +187,26 @@ nsVmap.nsMapManager.MapLegend.prototype.maplegendController = function ($scope)
 nsVmap.nsMapManager.MapLegend.prototype.maplegendController.prototype.loadLegend = function () {
     oVmap.log('nsVmap.nsMapManager.MapLegend.maplegendController.loadLegend');
 
-    this['oUrls'] = this.getLegendUrls();
+    this['oUrls'] = this.getLegendUrls(oVmap.getMap().getOLMap());
     this.downloadLegendImgs(this['oUrls']);
+
+    if(this.$scope_["$root"]["compare_enabled"]){
+        this['oCompareUrls'] = this.getLegendUrls(oVmap.getMapCompare().getOLMap());
+        this.downloadLegendImgs(this['oCompareUrls']);
+    } else {
+        this['oCompareUrls'] = {};
+    }
 };
 
 /**
  * Get the legend URLs
+ * @param {object} olMap
  * @returns {object}
  */
-nsVmap.nsMapManager.MapLegend.prototype.maplegendController.prototype.getLegendUrls = function () {
+nsVmap.nsMapManager.MapLegend.prototype.maplegendController.prototype.getLegendUrls = function (olMap) {
     oVmap.log('nsVmap.nsMapManager.MapLegend.maplegendController.getLegendUrls');
 
-    var aLayers = oVmap.getMap().getOLMap().getLayers().getArray();
+    var aLayers = olMap.getLayers().getArray();
     var oUrls = {};
 
     // Récupération des URL WMS
diff --git a/module/javascript/app/vmap/mapmanager/mapmanager.js b/module/javascript/app/vmap/mapmanager/mapmanager.js
index c13c9aae888788c3844528a192df7f652b71cb9a..d42d368d9bce08e8b42bcc399a3efab62aee2ec9 100644
--- a/module/javascript/app/vmap/mapmanager/mapmanager.js
+++ b/module/javascript/app/vmap/mapmanager/mapmanager.js
@@ -45,6 +45,12 @@ nsVmap.nsMapManager.MapManager = function () {
      * @private
      */
     this.oLayersTree_ = {};
+    /**
+     * Object which contains the layers tree
+     * @type {object}
+     * @private
+     */
+    this.oCompareLayersTree_ = {};
 
     /**
      * Objet which contains the map modal manager tool
@@ -281,20 +287,73 @@ nsVmap.nsMapManager.MapManager.prototype.loadMap = function (element) {
     });
 };
 
+/**
+ * Load a new map to compare
+ * @param {object} element Html element witch contains the url to the map.json file
+ * @param {object} element.url link to the map.json file
+ * @export
+ */
+nsVmap.nsMapManager.MapManager.prototype.loadCompareMap = function (element) {
+    oVmap.log('nsVmap.nsMapManager.MapManager.loadCompareMap');
+
+    if (oVmap['properties']['is_mobile']) {
+        oVmap.getToolsManager().getBasicTools().hideMobileMenu();
+    }
+
+    // Récupère l'url
+    var sUrl = element.getAttribute("url");
+
+    if (!goog.isDefAndNotNull(sUrl)) {
+        return 0;
+    }
+    if (sUrl.length === 0) {
+        return 0;
+    }
+
+    // Récupère l'arbre de couches
+    var this_ = this;
+    this_.getAjaxLayersTree(sUrl, function(oTree){
+
+        oVmap.log("oCompareTree: ", oTree);
+
+        // Change la variable oLayersTree
+        this_.setCompareLayersTree(oTree);
+
+        // Rafraichit la carte
+        this_.reloadMap();
+
+        // Signale que c'est la carte utilisée
+        for (var i = 0; i < this_.oMapCatalog_['maps'].length; i++) {
+            if (this_.oMapCatalog_['maps'][i]['url'] === sUrl)
+            this_.oMapCatalog_['compareMap'] = i;
+        }
+        this_.setUsedMap('compare');
+
+        oVmap.log("oVmap.event: mapCompareChanged");
+        oVmap['scope'].$broadcast('mapCompareChanged');
+        angular.element('#map-compare-tool-btn').click();
+        setTimeout(function () {
+            oVmap.resizeLayerTools();
+        }, 1000);
+    });
+};
+
 /**
  * Put the used map to used
  * @returns {undefined}
  */
-nsVmap.nsMapManager.MapManager.prototype.setUsedMap = function () {
+nsVmap.nsMapManager.MapManager.prototype.setUsedMap = function (sKey) {
     oVmap.log('nsVmap.nsMapManager.MapManager.prototype.setUsedMap');
 
+    sKey = (goog.isDefAndNotNull(sKey)) ? sKey : 'used';
+
     // Met toutes les cartes à used = false
     for (var i = 0; i < this.oMapCatalog_['maps'].length; i++) {
-        this.oMapCatalog_['maps'][i]['used'] = false;
+        this.oMapCatalog_['maps'][i][sKey] = false;
     }
 
     // Met la carte utilisée à used = true
-    this.oMapCatalog_['maps'][this.oMapCatalog_['usedMap']]['used'] = true;
+    this.oMapCatalog_['maps'][this.oMapCatalog_[sKey + 'Map']][sKey] = true;
 
     oVmap.resizeLayerTools(false);
 };
@@ -868,7 +927,7 @@ nsVmap.nsMapManager.MapManager.prototype.ajaxGetMapCatalog = function (sUrl) {
  * @return {object<LayersTree>}
  */
 nsVmap.nsMapManager.MapManager.prototype.getAjaxLayersTree = function (sUrl, callback) {
-    var LayersTree;
+    var oLayersTree;
 
     ajaxRequest({
         'method': 'GET',
@@ -878,11 +937,9 @@ nsVmap.nsMapManager.MapManager.prototype.getAjaxLayersTree = function (sUrl, cal
         'success': function (response) {
             var data = JSON.parse(response['data']);
             if (goog.isDef(data['mapjsons'])) {
-                LayersTree = data['mapjsons'][0];
+                oLayersTree = data['mapjsons'][0];
             }
-
-            oVmap.log(LayersTree);
-            callback.call(this, LayersTree);
+            callback.call(this, oLayersTree);
         }
     });
 };
@@ -1206,16 +1263,59 @@ nsVmap.nsMapManager.MapManager.prototype.getLayersTree = function () {
     return this.oLayersTree_;
 };
 
+/**
+ * LayersTree_ getter (also set the visibility of the layers with the new ones)
+ * @return {object} Layers tree
+ * @api experimental
+ * @export
+ */
+nsVmap.nsMapManager.MapManager.prototype.getCompareLayersTree = function () {
+
+    var oMap = oVmap.getMapCompare().getOLMap();
+    var aLayers = oMap.getLayers().getArray();
+
+    /**
+     * Recursive function that update parameters recursively
+     * @param {object} node
+     */
+    var updateOnTree = function (node) {
+        // Recursive
+        if (goog.isDef(node['children'])) {
+            for (var i = 0; i < node['children'].length; i++) {
+                updateOnTree(node['children'][i]);
+            }
+        }
+        // Update
+        if (goog.isDef(node['olLayer'])) {
+            node['visible'] = node['olLayer'].getVisible();
+            node['index'] = aLayers.indexOf(node['olLayer']);
+            node['opacity'] = node['olLayer'].getOpacity();
+        }
+    };
+
+    for (var i = 0; i < this.oCompareLayersTree_['children'].length; i++) {
+        updateOnTree(this.oCompareLayersTree_['children'][i]);
+    }
+
+    return this.oCompareLayersTree_;
+};
+
 /**
  * Get the JSON layers tree
  * @returns {String}
  * @export
  */
-nsVmap.nsMapManager.MapManager.prototype.getJSONLayersTree = function () {
+nsVmap.nsMapManager.MapManager.prototype.getJSONLayersTree = function ($bCompareLayersTree) {
 
     // recupère une copie de l'arbre des couches
     var oLayersTree = jQuery.extend(true, {}, oVmap.getMapManager().getLayersTree());
     var oMap = oVmap.getMap().getOLMap();
+
+    if($bCompareLayersTree){
+      oLayersTree = jQuery.extend(true, {}, oVmap.getMapManager().getCompareLayersTree());
+      oMap = oVmap.getMapCompare().getOLMap();
+    }
+
     var aDiscardedAttributes = [
         'olLayer',
         '$$hashKey',
@@ -1281,6 +1381,15 @@ nsVmap.nsMapManager.MapManager.prototype.getJSONLayersTree = function () {
 nsVmap.nsMapManager.MapManager.prototype.setLayersTree = function (oTree) {
     this.oLayersTree_ = oTree;
 };
+/**
+ * LayersTree_ setter
+ * @param {object} oTree Layers tree
+ * @api experimental
+ * @export
+ */
+nsVmap.nsMapManager.MapManager.prototype.setCompareLayersTree = function (oTree) {
+    this.oCompareLayersTree_ = oTree;
+};
 
 /**
  * oMapCatalog_ getter
diff --git a/module/javascript/app/vmap/mapmanager/mapmodal/maplistlitle.js b/module/javascript/app/vmap/mapmanager/mapmodal/maplistlitle.js
index bd1150b4f386c2807fa30a27b3638aeeb84a8c26..0782d0c2dc9c6cb82acca40e873c11c7c2ec3bb9 100644
--- a/module/javascript/app/vmap/mapmanager/mapmodal/maplistlitle.js
+++ b/module/javascript/app/vmap/mapmanager/mapmodal/maplistlitle.js
@@ -42,7 +42,11 @@ nsVmap.nsMapManager.nsMapModal.MapListLitle.prototype.maplistlitleDirective = fu
         controller: 'AppMaplistlitleController',
         controllerAs: 'ctrl',
         bindToController: true,
-        templateUrl: oVmap['properties']['vmap_folder'] + '/' + 'template/layers/mapmodal/' + (oVmap['properties']['is_mobile'] ? 'maplistlitle_mobile.html' : 'maplistlitle.html')
+        templateUrl: oVmap['properties']['vmap_folder'] + '/' + 'template/layers/mapmodal/' + (oVmap['properties']['is_mobile'] ? 'maplistlitle_mobile.html' : 'maplistlitle.html'),
+        link : function ($scope, $element, $attrs){
+          $scope["compare"] = goog.isDefAndNotNull($attrs["compare"]);
+          $attrs.$observe("compare", function(){$scope["compare"] = goog.isDefAndNotNull($attrs["compare"])});
+        }
     };
 };
 
diff --git a/module/javascript/app/vmap/requires.js b/module/javascript/app/vmap/requires.js
index 2eae1b6a727b42ff523d7e606e3dfa5baecbe4fd..997cb30e697bb1d836e3591af4d3f28eb68c81c6 100755
--- a/module/javascript/app/vmap/requires.js
+++ b/module/javascript/app/vmap/requires.js
@@ -8,7 +8,8 @@
 goog.provide('vmap');
 goog.require('oVmap');
 goog.require('nsVmap.Map');
+goog.require('nsVmap.MapCompare');
 goog.require('nsVmap.Map.MapTooltip');
 goog.require('nsVmap.Map.MapPopup');
 goog.require('nsVmap.nsMapManager.MapManager');
-goog.require('nsVmap.nsToolsManager.ToolsManager');
\ No newline at end of file
+goog.require('nsVmap.nsToolsManager.ToolsManager');
diff --git a/module/javascript/app/vmap/tools/basictools.js b/module/javascript/app/vmap/tools/basictools.js
index f53955c43cccd66024db099c860b32b003b11aca..32d672545e8e07809eef979e646647a798855dd1 100644
--- a/module/javascript/app/vmap/tools/basictools.js
+++ b/module/javascript/app/vmap/tools/basictools.js
@@ -17,6 +17,7 @@ goog.require('nsVmap.nsToolsManager.Select');
 goog.require('nsVmap.nsToolsManager.Insert');
 goog.require('nsVmap.nsToolsManager.Print');
 goog.require('nsVmap.nsToolsManager.Urlexporter');
+goog.require('nsVmap.nsToolsManager.Compare');
 
 
 /**
@@ -429,4 +430,4 @@ nsVmap.nsToolsManager.BasicTools.prototype.basictoolsController.prototype.locati
 
 // Définit la directive et le controller
 oVmap.module.directive('appBasictools', nsVmap.nsToolsManager.BasicTools.prototype.basictoolsDirective);
-oVmap.module.controller('AppBasictoolsController', nsVmap.nsToolsManager.BasicTools.prototype.basictoolsController);
\ No newline at end of file
+oVmap.module.controller('AppBasictoolsController', nsVmap.nsToolsManager.BasicTools.prototype.basictoolsController);
diff --git a/module/javascript/app/vmap/tools/compare.js b/module/javascript/app/vmap/tools/compare.js
new file mode 100644
index 0000000000000000000000000000000000000000..076766831e9746bc36e12cac715b641048b9b8ed
--- /dev/null
+++ b/module/javascript/app/vmap/tools/compare.js
@@ -0,0 +1,81 @@
+/* global oVmap, nsVmap, goog, ol, vitisApp */
+
+/**
+ * @author: Anthony Borghi
+ * @Description: Fichier contenant la classe nsVmap.nsToolsManager.Urlexporter
+ * cette classe permet à l'utilisateur d'exporter une url pour un autre utilisateur
+ */
+goog.provide('nsVmap.nsToolsManager.Compare');
+
+goog.require('oVmap');
+
+/**
+ * @classdesc
+ * Class {@link nsVmap.nsToolsManager.VmapUser}
+ * @constructor
+ * @export
+ */
+nsVmap.nsToolsManager.compare = function () {
+    oVmap.log('nsVmap.nsToolsManager.Compare');
+};
+
+
+
+/**
+ * Directive
+ * @return {angular.Directive} The directive specs.
+ * @constructor
+ */
+nsVmap.nsToolsManager.compare.prototype.compareDirective = function () {
+    oVmap.log("nsVmap.nsToolsManager.compare.prototype.compareDirective");
+    return {
+        restrict: 'A',
+        scope: {
+            'map': '=appMap',
+            'lang': '=appLang'
+        },
+        controller: 'AppCompareMode',
+        controllerAs: 'ctrl',
+        bindToController: true,
+        templateUrl: oVmap['properties']['vmap_folder'] + '/' + 'template/tools/comparemapmanager.html'
+    };
+};
+
+/**
+ * Controler
+ * @constructor
+ * @param {object} $scope
+ * @returns {undefined}
+ * @ngInject
+ */
+nsVmap.nsToolsManager.compare.prototype.compareController = function ($scope, $element) {
+    oVmap.log("nsVmap.nsToolsManager.compare.prototype.compareController");
+
+    var this_ = this;
+
+    this.$scope_ = $scope;
+
+    /**
+     * The current properties
+     */
+    this['properties'] = oVmap['properties'];
+
+    /**
+     * The current token
+     */
+    this['token'] = oVmap['properties']['token'];
+
+    /**
+     * @type {boolean}
+     */
+    this["useCompareMode"] = false;
+
+    $scope.$watch("ctrl.useCompareMode", function(){
+        $scope.$root["compare_enabled"] = this_["useCompareMode"];
+    })
+
+};
+
+// Définit la directive et le controller
+oVmap.module.directive('appCompareMode', nsVmap.nsToolsManager.compare.prototype.compareDirective);
+oVmap.module.controller('AppCompareMode', nsVmap.nsToolsManager.compare.prototype.compareController);
diff --git a/module/javascript/app/vmap/tools/controls.js b/module/javascript/app/vmap/tools/controls.js
index 67b20e2e0fa4df43af05829b3365f6282f0ae60d..6fee41a7d7821c2ffb37070543fbe7aaef4e23df 100755
--- a/module/javascript/app/vmap/tools/controls.js
+++ b/module/javascript/app/vmap/tools/controls.js
@@ -31,7 +31,7 @@ goog.require('ol.format.TopoJSON');
 /**
  * @classdesc
  * Class {@link nsVmap.nsToolsManager.Controls}: Add the controls defined in data/tools.json,
- * available : Attribution, FullScreen, MousePosition, OverviewMap, Rotate, ScaleLine, Zoom, ZoomSlider, 
+ * available : Attribution, FullScreen, MousePosition, OverviewMap, Rotate, ScaleLine, Zoom, ZoomSlider,
  * ZoomToExtent, CurrentProjection, DragAndDrop (GPX,GeoJSON,IGC,KML,TopoJSON)
  * @param {array} aControls Controls to set
  * @constructor
@@ -273,7 +273,7 @@ nsVmap.nsToolsManager.Controls.prototype.addControl = function (control) {
 /**
  * Toggle a control to the ol map
  * @param {string} control Control to toggle
- * @param {boolean} bActive 
+ * @param {boolean} bActive
  * @export
  */
 nsVmap.nsToolsManager.Controls.prototype.setToolActive = function (control, bActive) {
@@ -426,4 +426,4 @@ nsVmap.nsToolsManager.Controls.prototype.getOverviewMap = function () {
 
 // Définit la directive et le controller
 oVmap.module.directive('appControls', nsVmap.nsToolsManager.Controls.prototype.controlsDirective);
-oVmap.module.controller('AppControlsController', nsVmap.nsToolsManager.Controls.prototype.controlsController);
\ No newline at end of file
+oVmap.module.controller('AppControlsController', nsVmap.nsToolsManager.Controls.prototype.controlsController);
diff --git a/module/javascript/app/vmap/tools/infocontainer.js b/module/javascript/app/vmap/tools/infocontainer.js
index e04b0496471f34d663bfaed78a3dfe88d0e20ac2..e499814f2fbb84c8edcb52ff224fbab69d70bd8a 100644
--- a/module/javascript/app/vmap/tools/infocontainer.js
+++ b/module/javascript/app/vmap/tools/infocontainer.js
@@ -662,6 +662,7 @@ nsVmap.nsToolsManager.InfoContainer.prototype.infocontainerController.prototype.
         $("#opener-bottombar").css("visibility", "visible");
     }
     $("#map-container").addClass('minus');
+    $("#map-container-compare").addClass('minus');
 
     // Ouvre la barre
     this.$timeout(function () {
diff --git a/module/javascript/app/vmap/tools/insert.js b/module/javascript/app/vmap/tools/insert.js
index 803d13add3e95a2916e129c4eb60e6db3b981b01..ce07b2686567b9c5002a2441209ecb8a80568318 100644
--- a/module/javascript/app/vmap/tools/insert.js
+++ b/module/javascript/app/vmap/tools/insert.js
@@ -187,6 +187,7 @@ nsVmap.nsToolsManager.Insert.prototype.inserttoolController = function ($scope,
         this['snapOptions']['mode'] = oVmap['properties']['snapping']['defaut_snapp_mode'];
         this['snapOptions']['limit'] = oVmap['properties']['snapping']['defaut_limit'];
         this['snapOptions']['visible'] = oVmap['properties']['snapping']['defaut_visibility'];
+        this['snapOptions']['avoidSuperpositions'] = {};
     }
 
     /**
@@ -257,6 +258,11 @@ nsVmap.nsToolsManager.Insert.prototype.inserttoolController = function ($scope,
      */
     $scope['aQueryableBOs'] = oVmap.getMapManager().getQueryableBusinessObjectsAsArray(true);
 
+    /**
+     * Business objects avaliable for avoiding superpositions
+     */
+    $scope['aAvoidSuperpositionsBOs'] = [];
+
     /**
      * Object to insert
      * oInsertObject.sFormDefinitionName name of the form (insert, upload, display)
@@ -311,6 +317,19 @@ nsVmap.nsToolsManager.Insert.prototype.inserttoolController = function ($scope,
     // Supprime du trou de la feature (si il existe) feature lors de la sélection sur l'interaction this.deleteHole_
     this.deleteHole_.on('select', this.deleteHole, this);
 
+    // Évite les superpositions à l'édition
+    this.modify_.on('modifyend', function (evt) {
+
+        // Récupère la feature ajoutée
+        var aFeatures = evt.features.getArray();
+
+        var j = 0;
+        for (var i = 0; i < aFeatures.length; i++) {
+            // Évite les superpositions avec les autres couches si besoin
+            this_.avoidSuperpositions(aFeatures[i]);
+        }
+    });
+
     // Lance updateInsertObjectFeature lors de chaque changement sur this.oOverlayFeatures_
     // si il n'y a pas eut de changements pendant 500ms
     var iTmpChanges = 0;
@@ -318,6 +337,7 @@ nsVmap.nsToolsManager.Insert.prototype.inserttoolController = function ($scope,
 
         // Retire les anciennes features si on est pas en mode multi
         var sGeomType = $scope['oInsertObject']['sGeomType'];
+
         // Si il ne s'agit pas d'une géométrie multiple
         if (goog.isDefAndNotNull(sGeomType)) {
             if (sGeomType.substr(0, 5) !== 'MULTI' && sGeomType !== 'GEOMETRYCOLLECTION') {
@@ -366,8 +386,10 @@ nsVmap.nsToolsManager.Insert.prototype.inserttoolController = function ($scope,
 
     // Au changement d'objet métier en cours d'insertion
     this.$scope_.$watch('selectedBoId', function () {
-        this_.updateInsertForm();
-        this_.selectCurrentBoForSnapping();
+        this_.updateInsertForm(null, function(){
+            this_.selectCurrentBoForSnapping();
+            this_.loadAvoidSuperpositionBos();
+        });
     });
 
     // Affiche les modales en plein écran pour la version mobile
@@ -411,6 +433,7 @@ nsVmap.nsToolsManager.Insert.prototype.inserttoolController.prototype.loadInsert
     });
 
     this.checkEditionScale();
+    this.loadAvoidSuperpositionBos();
 };
 
 /**
@@ -433,6 +456,40 @@ nsVmap.nsToolsManager.Insert.prototype.inserttoolController.prototype.selectCurr
     this.checkEditionScale();
 };
 
+
+/**
+ * Load this.aAvoidSuperpositionsBOs
+ *
+ */
+nsVmap.nsToolsManager.Insert.prototype.inserttoolController.prototype.loadAvoidSuperpositionBos = function () {
+    oVmap.log('nsVmap.nsToolsManager.Insert.inserttoolController.loadAvoidSuperpositionBos');
+
+    var this_ = this;
+
+    // Types de géométries pour le calcul des jointures
+    var aActiveGeomTypes = ['POLYGON', 'MULTIPOLYGON', 'GEOMETRY', 'GEOMETRYCOLLECTION'];
+
+    // Objets métiers actifs pour la calcul des jointures
+    this.$scope_['aAvoidSuperpositionsBOs'] = [];
+
+    if (goog.isDefAndNotNull(this.$scope_['oInsertObject']['sGeomType'])) {
+
+        // Si la couche en cours d'insertion est dans aActiveGeomTypes
+        if (aActiveGeomTypes.indexOf(this.$scope_['oInsertObject']['sGeomType']) !== -1) {
+            for (var i = 0; i < this_.$scope_['aQueryableBOs'].length; i++) {
+
+                // Si la couche cible est dans aActiveGeomTypes
+                if (goog.isDefAndNotNull(this_.$scope_['aQueryableBOs'][i]['bo_geom_type'])) {
+                    if(aActiveGeomTypes.indexOf(this_.$scope_['aQueryableBOs'][i]['bo_geom_type']) !== -1){
+
+                        this.$scope_['aAvoidSuperpositionsBOs'].push(this_.$scope_['aQueryableBOs'][i]);
+                    }
+                }
+            }
+        }
+    }
+}
+
 /**
  * Vérifie que l'échelle en cours respecte les spécification de l'objet métier
  */
@@ -1068,9 +1125,11 @@ nsVmap.nsToolsManager.Insert.prototype.inserttoolController.prototype.startDrawi
     var this_ = this;
     this.draw_.on('drawend',
             function (evt) {
-                // Si la géométrie est un cercle, alors elle est remplacée par un polygone à 32 côtés
                 var feature = evt.feature;
+                // Si la géométrie est un cercle, alors elle est remplacée par un polygone à 32 côtés
                 feature = this_.updateCircleGeoms(feature);
+                // Évite les superpositions avec les autres couches si besoin
+                this_.avoidSuperpositions(feature);
             }, this);
 
 
@@ -1141,6 +1200,118 @@ nsVmap.nsToolsManager.Insert.prototype.inserttoolController.prototype.updateCirc
     return feature;
 };
 
+/**
+ * Edit the given feature to avoid superpositions with layers defined in snapOptions.avoidSuperpositions
+ * @param {ol.Feature} olFeature
+ * @returns {ol.Feature}
+ */
+nsVmap.nsToolsManager.Insert.prototype.inserttoolController.prototype.avoidSuperpositions = function (olFeature) {
+    oVmap.log('nsVmap.nsToolsManager.Insert.inserttoolController.avoidSuperpositions');
+
+    // Objets métiers à intersecter
+    var aSuperpositionBos = [];
+    for (var bo_id in this['snapOptions']['avoidSuperpositions']) {
+        if (this['snapOptions']['avoidSuperpositions'][bo_id] === true) {
+            aSuperpositionBos.push(bo_id);
+        }
+    }
+
+    // Remplace la géométrie par celle calculée
+    if (aSuperpositionBos.length > 0) {
+        this.setDiffGeom_(aSuperpositionBos, olFeature)
+    }
+}
+
+/**
+ * Modify the feature geometry to avoid superpositions with BOs in aSuperpositionBos
+ *
+ * @param  {string} aSuperpositionBos
+ * @param  {ol.Feature} olFeature
+ * @param  {object|undefines} opt_options
+ */
+nsVmap.nsToolsManager.Insert.prototype.inserttoolController.prototype.setDiffGeom_ = function (aSuperpositionBos, olFeature, opt_options) {
+    oVmap.log('nsVmap.nsToolsManager.Insert.inserttoolController.setDiffGeom_');
+
+    if (!goog.isArray(aSuperpositionBos)) {
+        return 0;
+    }
+    if (!goog.isDefAndNotNull(olFeature)) {
+        return 0;
+    }
+    if (!goog.isDefAndNotNull(opt_options)) {
+        opt_options = {
+            bo_index: 0
+        }
+    }
+
+    var this_ = this;
+    var sEWKTGeom = oVmap.getEWKTFromGeom(olFeature.getGeometry());
+
+    this.getDiffGeom_(aSuperpositionBos[opt_options.bo_index], sEWKTGeom).then(function(sNewEWKTGeom){
+
+        // Remplace la géométrie
+        olFeature.setGeometry(oVmap.getGeomFromEWKT(sNewEWKTGeom));
+
+        // Relance la fonction pour les autres objets métiers
+        opt_options.bo_index ++;
+        if (opt_options.bo_index < aSuperpositionBos.length) {
+            this_.setDiffGeom_(aSuperpositionBos, olFeature, opt_options);
+        }
+    }, function(err){
+        console.error('Cannot get the diff geom: ', err);
+    });
+
+}
+
+/**
+ * Get the diff superposition geometry
+ *
+ * @param  {string} sBoId
+ * @param  {string} sEWKTGeom
+ * @return {promise}
+ */
+nsVmap.nsToolsManager.Insert.prototype.inserttoolController.prototype.getDiffGeom_ = function (sBoId, sEWKTGeom) {
+    oVmap.log('nsVmap.nsToolsManager.Insert.inserttoolController.getDiffGeom_');
+
+    var deferred = this.$q_.defer();
+    ajaxRequest({
+        'method': 'POST',
+        'url': oVmap['properties']['api_url'] + '/vmap/querys/' + sBoId + '/diff_geometry',
+        'headers': {
+            'X-HTTP-Method-Override': 'GET',
+            'Accept': 'application/x-vm-json'
+        },
+        'data': {
+            'intersect_geom': sEWKTGeom
+        },
+        'scope': this.$scope_,
+        'success': function (response) {
+
+            if (!goog.isDefAndNotNull(response['data'])) {
+                deferred.reject('response.data not defined');
+                return 0;
+            }
+            if (goog.isDefAndNotNull(response['data']['errorMessage'])) {
+                deferred.reject(response['data']['errorMessage']);
+                return 0;
+            }
+            if (!goog.isDefAndNotNull(response['data'][0])) {
+                deferred.resolve(sEWKTGeom);
+                return 0;
+            }
+            if (!goog.isDefAndNotNull(response['data'][0]['diff_geom'])) {
+                deferred.resolve(sEWKTGeom);
+                return 0;
+            }
+            deferred.resolve(response['data'][0]['diff_geom']);
+        },
+        'error': function (response) {
+            deferred.reject(response);
+        }
+    });
+    return deferred.promise;
+}
+
 /**
  * Update feature for scope.oInsertObject
  */
@@ -1478,7 +1649,17 @@ nsVmap.nsToolsManager.Insert.prototype.inserttoolController.prototype.getMobileB
 nsVmap.nsToolsManager.Insert.prototype.inserttoolController.prototype.showSnappingOptionsModal = function () {
     oVmap.log('nsVmap.nsToolsManager.Insert.prototype.inserttoolController.prototype.showSnappingOptionsModal');
 
+    var this_ = this;
     this['tmpSnapOptions'] = angular.copy(this['snapOptions']);
+
+    this.$scope_.$applyAsync(function(){
+        for (var i = 0; i < this_.$scope_['aQueryableBOs'].length; i++) {
+            if (!goog.isDefAndNotNull(this_['tmpSnapOptions']['avoidSuperpositions'][this_.$scope_['aQueryableBOs'][i]['bo_id']])) {
+                this_['tmpSnapOptions']['avoidSuperpositions'][this_.$scope_['aQueryableBOs'][i]['bo_id']] = false;
+            }
+        }
+    });
+
     $('#vmap-insert-snap-options-modal').modal('show');
 };
 
@@ -1597,6 +1778,10 @@ nsVmap.nsToolsManager.Insert.prototype.inserttoolController.prototype.loadBoVect
                     oBo['bo_snapping_loaded'] = null;
                     return 0;
                 }
+                if (!goog.isDefAndNotNull(response['data'][0])) {
+                    oBo['bo_snapping_loaded'] = null;
+                    return 0;
+                }
                 if (response['data'][0]['count'] > this_['snapOptions']['snappingObjectsLimit']) {
                     oBo['bo_snapping_loaded'] = null;
                     var text = 'Limit de points atteinte pour object ';
@@ -1609,7 +1794,8 @@ nsVmap.nsToolsManager.Insert.prototype.inserttoolController.prototype.loadBoVect
                     if (goog.isDefAndNotNull(response['data'][i]['geom'])) {
                         geom = response['data'][i]['geom'];
                         aFeatures.push(new ol.Feature({
-                            geometry: oVmap.getGeomFromEWKT(geom)
+                            geometry: oVmap.getGeomFromEWKT(geom),
+                            'bo_id': bo_id
                         }));
                     }
                 }
diff --git a/module/javascript/app/vmap/tools/location.js b/module/javascript/app/vmap/tools/location.js
index 4cd96440554191c47a0415289ddde0cb77eb6065..415bd9cb19f286c3fcb11ea2c8818f5b60dc3c30 100644
--- a/module/javascript/app/vmap/tools/location.js
+++ b/module/javascript/app/vmap/tools/location.js
@@ -197,12 +197,25 @@ nsVmap.nsToolsManager.Location.prototype.locationController = function ($scope,
 
 	        fHistoryDelayHandler = $timeout(function () {
 	        	if(this_['iHistoryOffset'] === 0){
-	        		this_["aLocationHistory"].push({
+
+                    var oNewLocation = {
 		        		center: this_.map_.getView().getCenter(),
 		        		zoom: this_.map_.getView().getZoom()
-		    		});
+		    		}
+
+                    var oLastLocation = this_['aLocationHistory'][this_['aLocationHistory'].length - 1];
+
+                    if (this_['aLocationHistory'].length > 0) {
+                        if (oNewLocation.zoom === oLastLocation.zoom &&
+                            oNewLocation.center[0] === oLastLocation.center[0] &&
+                            oNewLocation.center[1] === oLastLocation.center[1]) {
+                            return 0;
+                        }
+                    }
+
+	        		this_["aLocationHistory"].push(oNewLocation);
 	        	} else {
-	        		// splice 
+	        		// splice
 	        		var iHistoryPosition = this_['aLocationHistory'].length - (this_['iHistoryOffset']);
 	        		this_["aLocationHistory"].splice(iHistoryPosition, this_['iHistoryOffset'], {
 		        		center: this_.map_.getView().getCenter(),
diff --git a/module/javascript/app/vmap/tools/print.js b/module/javascript/app/vmap/tools/print.js
index 8c779787a04216d8ac5ca2ec60d40e2b2bd29a12..f2d041ca2bb9172bf72884d8c7ef08051d3080aa 100644
--- a/module/javascript/app/vmap/tools/print.js
+++ b/module/javascript/app/vmap/tools/print.js
@@ -103,6 +103,9 @@ nsVmap.nsToolsManager.Print.prototype.printController = function ($timeout, $com
      */
     $scope['modelIndex'] = 0;
 
+    $scope["managePrintZoneInProgress"] = false;
+    $scope["manageComparePrintZoneInProgress"] = false;
+
     /**
      * @public
      */
@@ -158,11 +161,23 @@ nsVmap.nsToolsManager.Print.prototype.printController = function ($timeout, $com
     this.template_;
 
     /**
-     * Size of the printZone
+     * Size of the map printZone
      * @private
      */
     this.printedMapSize_;
 
+    /**
+     * Size of the compare map printZone
+     * @private
+     */
+    this.printedCompareMapSize_;
+
+    /**
+     * Size of the overview map printZone
+     * @private
+     */
+    this.printedOverviewMapSize_;
+
     /**
      * this.printedMapSize_ resize coeff
      * @private
@@ -173,7 +188,12 @@ nsVmap.nsToolsManager.Print.prototype.printController = function ($timeout, $com
      * The print box object
      * @private
      */
-    this.printBox_ = new nsVmap.nsToolsManager.PrintBox();
+    this.printBox_ = new nsVmap.nsToolsManager.PrintBox({'map_object':oVmap.getMap()});
+    /**
+     * The print box object
+     * @private
+     */
+    this.printBoxCompare_ = new nsVmap.nsToolsManager.PrintBox({'map_object':oVmap.getMapCompare()});
 
     // mise à jour de l'échelle dans le forulaire d'impression lors d'un mouvement sur la carte
     this.listenScaleChanges();
@@ -197,6 +217,9 @@ nsVmap.nsToolsManager.Print.prototype.printController = function ($timeout, $com
     oVmap['scope'].$on('toggleOutTools', function () {
         if (!$('#print-select-btn').hasClass('active')) {
             this_.printBox_.hide();
+            this_.printBoxCompare_.hide();
+            $scope["managePrintZoneInProgress"] = false;
+            $scope["manageComparePrintZoneInProgress"] = false;
         }
     });
 };
@@ -352,7 +375,10 @@ nsVmap.nsToolsManager.Print.prototype.printController.prototype.loadModelParmas2
     oVmap.log('nsVmap.nsToolsManager.Print.printController.loadModelParmas2');
 
     // Récupère la taille de la carte this.printedMapSize_ ainsi que le coefficient this.resizeCoeff_
-    this.setPrintedMapSize(this.template_);
+    this.printedMapSize_ = this.getPrintedMapSize(this.template_, '#map1', '#map_image');
+    this.printedOverviewMapSize_ = this.getPrintedMapSize(this.template_, '#map1', '#map_overview');
+
+    this.resizeCoeff_ = this.printedMapSize_.resizeCoeff;
 
     // Pré-rempli le champ "Résolution"
     this['resolution'] = this.resizeCoeff_;
@@ -361,9 +387,29 @@ nsVmap.nsToolsManager.Print.prototype.printController.prototype.loadModelParmas2
     this['currentScale'] = oVmap.getMap().getPrettyScale(oVmap.getMap().getScale() / this.resizeCoeff_);
 
     // Dessine un carré d'impression à chaque mouvement de la carte
-    this.printBox_.setSize(this.printedMapSize_);
+    this.printBox_.setSize(this.printedMapSize_.printedMapSize);
     this.printBox_.show();
 
+    if(this.$scope_["$root"]["compare_enabled"]){
+        this.printedCompareMapSize_ = this.getPrintedMapSize(this.template_, "#map1Compare", "#map_image_compare");
+
+        if(this.printedCompareMapSize_ !== 0){
+            // Pré-rempli le champ "Résolution"
+            this['resolutionCompare'] = this.printedCompareMapSize_.resizeCoeff;
+
+            // Ajuste l'échelle avec le niveau de détail
+            this['currentScaleCompare'] = oVmap.getMapCompare().getPrettyScale(oVmap.getMapCompare().getScale() / this.printedCompareMapSize_.resizeCoeff);
+
+            // Dessine un carré d'impression à chaque mouvement de la carte
+            this.printBoxCompare_.setSize(this.printedCompareMapSize_.printedMapSize);
+            this.printBoxCompare_.show();
+        } else {
+            this.printBoxCompare_.hide();
+        }
+    }
+
+    // Supprime le template du body de Vmap
+    $(this.template_).remove();
 };
 
 /**
@@ -389,29 +435,45 @@ nsVmap.nsToolsManager.Print.prototype.printController.prototype.setTemplate = fu
         });
     }
 
+    this.$scope_['compare_mode'] = this.$scope_["$root"]["compare_enabled"];
+
     if (goog.isDefAndNotNull(oModel['definition'])) {
         var template = document.createElement("div");
         template.innerHTML = oModel['definition'];
+
+        this.$compile_(template)(this.$scope_);
         this_.template_ = template;
-        callback.call(this, [template]);
+
+        setTimeout(function () {
+            callback.call(this_, [template]);
+        });
     }
 };
 
 /**
- * Set this.printedMapSize_ and this.resizeCoeff_
- * @param {object} template
+ * Get the print map size and resolution coeff
+ *
+ * @param  {type} template
+ * @param  {type} sElementMapId
+ * @param  {type} sPrintId
+ * @return {object}
  */
-nsVmap.nsToolsManager.Print.prototype.printController.prototype.setPrintedMapSize = function (template) {
-    oVmap.log('nsVmap.nsToolsManager.Print.printController.setPrintedMapSize');
+nsVmap.nsToolsManager.Print.prototype.printController.prototype.getPrintedMapSize = function (template, sElementMapId, sPrintId) {
+    oVmap.log('nsVmap.nsToolsManager.Print.printController.getPrintedMapSize');
 
-    var imageDiv = $(template).find('#map_image');
+    sPrintId = (goog.isDefAndNotNull(sPrintId)) ? sPrintId : '#map_image';
+    sElementMapId = (goog.isDefAndNotNull(sElementMapId)) ? sElementMapId : '#map1';
+
+    var imageDiv = $(template).find(sPrintId);
 
     // Vérifie la présence de '#map_image'
     if (!goog.isDef(imageDiv.get(0))) {
-        console.error('Aucune balise #map_image trouvée dans le template');
+        console.error('Aucune balise ' + sPrintId + ' trouvée dans le template');
         return 0;
     }
 
+    oPrintScope = angular.element($(template).find(sPrintId)).scope();
+
     // Ajoute temporairement le template au body de Vmap
     $(template).addClass('print_template');
     $('body').append(template);
@@ -419,20 +481,21 @@ nsVmap.nsToolsManager.Print.prototype.printController.prototype.setPrintedMapSiz
     var mapHeight = imageDiv.height();
     var mapWidth = imageDiv.width();
 
-    // Supprime le template du body de Vmap
-    $(template).remove();
-
     // Vérifie si la taille de la carte est suppérieur à la taille de l'écran
-    this.resizeCoeff_ = 1;
+    var resizeCoeff = 1;
     var tmpWidth = angular.copy(mapWidth);
     var tmpHeight = angular.copy(mapHeight);
-    while (mapWidth > ($('#map1').width()) || mapHeight > ($('#map1').height())) {
-        this.resizeCoeff_++;
-        mapWidth = tmpWidth / this.resizeCoeff_;
-        mapHeight = tmpHeight / this.resizeCoeff_;
+    while (mapWidth > ($(sElementMapId).width()) || mapHeight > ($(sElementMapId).height())) {
+        resizeCoeff++;
+        mapWidth = tmpWidth / resizeCoeff;
+        mapHeight = tmpHeight / resizeCoeff;
     }
 
-    this.printedMapSize_ = [mapWidth, mapHeight];
+    return {
+        printedMapSize: [mapWidth, mapHeight],
+        realSize: [imageDiv.width(), imageDiv.height()],
+        resizeCoeff: resizeCoeff
+    }
 };
 
 /**
@@ -469,13 +532,32 @@ nsVmap.nsToolsManager.Print.prototype.printController.prototype.changeScale = fu
 nsVmap.nsToolsManager.Print.prototype.printController.prototype.managePrintZone = function () {
     oVmap.log('nsVmap.nsToolsManager.Print.prototype.printController.prototype.managePrintZone');
 
-    if (this['currentAction'] === 'print-modifyPrintZone') {
+    if (this['currentAction'] === 'print-modifyPrintZone' && this.$scope_['managePrintZoneInProgress']) {
         this.printBox_.unmanagePrintBox();
+        this.$scope_["managePrintZoneInProgress"] = false;
     } else {
+        this.$scope_["managePrintZoneInProgress"] = true;
         this.printBox_.managePrintBox('print-modifyPrintZone');
     }
 };
 
+/**
+ * Detach the printZone from the view and allow to translate it
+ * @export
+ */
+nsVmap.nsToolsManager.Print.prototype.printController.prototype.manageComparePrintZone = function () {
+    oVmap.log('nsVmap.nsToolsManager.Print.prototype.printController.prototype.manageComparePrintZone');
+
+    if (this['currentAction'] === 'print-modifyPrintZone' && this.$scope_["manageComparePrintZoneInProgress"]) {
+        this.printBoxCompare_.unmanagePrintBox();
+        this.$scope_["manageComparePrintZoneInProgress"] = false;
+    } else {
+        //this.printBox_.unmanagePrintBox();
+        this.$scope_["manageComparePrintZoneInProgress"] = true;
+        this.printBoxCompare_.managePrintBox('print-modifyPrintZone');
+    }
+};
+
 /**
  * Prepare the print params and launch it
  * @returns {undefined}
@@ -504,15 +586,28 @@ nsVmap.nsToolsManager.Print.prototype.printController.prototype.prepareAndLaunch
     var aPopupOverlayFeatures = oVmap.getMap().getPopupOverlayFeatures().getArray();
     var aSelectionOverlayFeatures = oVmap.getMap().getSelectionOverlayFeatures().getArray();
 
-    // Lance l'impression
-    var returnPrint = this.print({
+    var oPrintOptions = {
         scope: scope,
         extent: extent,
         templateId: templateId,
         printStyleId: this.$scope_['selectedPrintstyleId'],
         resolutionCoeff: this['dpi'],
         features: goog.array.concat(aLocationOverlayFeatures, aPopupOverlayFeatures, aSelectionOverlayFeatures)
-    });
+    };
+
+    // récupération des infos pour la carte de comparaison si le mode comparaison est actif
+    if(this.$scope_['$root']["compare_enabled"]){
+        if(this.printedCompareMapSize_ !== 0){
+            // Enregistre l'échelle actuelle
+            this.currentScaleCompare_ = oVmap.getMapCompare().getScale({
+                'pretty': true
+            });
+            oPrintOptions.extentCompare = this.printBoxCompare_.getExtent();
+        }
+    }
+
+    // Lance l'impression
+    var returnPrint = this.print(oPrintOptions);
 
     if (returnPrint === 1) {
         // Ferme l'outil d'impression
@@ -562,14 +657,22 @@ nsVmap.nsToolsManager.Print.prototype.printController.prototype.print = function
     var printStyleId = opt_options.printStyleId;
 
     // Set includesJSON
-    var includesJson = JSON.stringify([{
+    var aIncludes = [{
             'target': '#map_legend',
-            'html': this_.getLegendTemplate()
-        }]);
+            'html': this_.getLegendTemplate('#maplegend')
+        }];
+    if(this.$scope_["$root"]["compare_enabled"]){
+        aIncludes.push({
+            'target': '#map_legend_compare',
+            'html': this_.getLegendTemplate('#compare_maplegend')
+        });
+    }
+    var includesJson = JSON.stringify(aIncludes);
 
     // Set scope
     var oPrintScope = goog.isDefAndNotNull(opt_options.scope) ? opt_options.scope : {};
     oPrintScope['date'] = goog.isDefAndNotNull(oPrintScope['date']) ? oPrintScope['date'] : today;
+    oPrintScope['compare_mode'] = this.$scope_["$root"]["compare_enabled"] === true ? true : false;
     var sScope = JSON.stringify(oPrintScope);
 
     // Ouvre la fenêtre d'impression
@@ -614,13 +717,11 @@ nsVmap.nsToolsManager.Print.prototype.printController.prototype.print = function
             var sFormat = response['data']['data'][0]['rt_format_id'];
             var sOrientation = response['data']['data'][0]['rt_orientation_id'];
 
-            var template = document.createElement("div");
-            template.innerHTML = response['data']['data'][0]['definition'];
-
-            var mapImageSize = this_.getTemplateTargetSize(template, '#map_image');
-            var overviewSize = this_.getTemplateTargetSize(template, '#map_overview');
+            var mapImageSize = this_.printedMapSize_.realSize;
+            var mapImageSizeCompare = this_.printedCompareMapSize_.realSize;
+            var overviewSize = this_.printedOverviewMapSize_.realSize;
 
-            var mapsJson = this_.getMapsJsonDef({
+            var oJsonDefOptions = {
                 mapId: opt_options.mapId,
                 resolutionCoeff: opt_options.resolutionCoeff,
                 extent: opt_options.extent,
@@ -628,7 +729,15 @@ nsVmap.nsToolsManager.Print.prototype.printController.prototype.print = function
                 featuresZoom: opt_options.featuresZoom,
                 mapImageSize: mapImageSize,
                 overviewSize: overviewSize
-            })
+            }
+
+            if(goog.isDefAndNotNull(opt_options.extentCompare)){
+              oJsonDefOptions.extentCompare = opt_options.extentCompare;
+              oJsonDefOptions.mapIdCompare = opt_options.mapIdCompare;
+              oJsonDefOptions.mapImageSizeCompare = mapImageSizeCompare;
+            }
+
+            var mapsJson = this_.getMapsJsonDef(oJsonDefOptions);
 
             // Récupère les infos de l'utilisateur
             this_.getUserInfos_().then(function (oUserInfos) {
@@ -698,6 +807,10 @@ nsVmap.nsToolsManager.Print.prototype.printController.prototype.print = function
     return 1;
 };
 
+/**
+ * Get the maps JSON defs
+ * @param  {object} opt_options
+ */
 nsVmap.nsToolsManager.Print.prototype.printController.prototype.getMapsJsonDef = function (opt_options) {
     oVmap.log('nsVmap.nsToolsManager.Print.prototype.printController.prototype.getMapsJsonDef');
 
@@ -707,11 +820,18 @@ nsVmap.nsToolsManager.Print.prototype.printController.prototype.getMapsJsonDef =
     // mapId/mapJson
     var sMapId;
     var sMapJSON;
+    var sMapIdCompare;
+    var sMapJSONCompare;
     if (goog.isDefAndNotNull(opt_options.mapId)) {
         sMapId = opt_options.mapId;
     } else {
         sMapJSON = oVmap.getMapManager().getJSONLayersTree();
     }
+    if (goog.isDefAndNotNull(opt_options.mapIdCompare)) {
+        sMapIdCompare = opt_options.mapIdCompare;
+    } else if (this.$scope_['$root']["compare_enabled"]) {
+        sMapJSONCompare = oVmap.getMapManager().getJSONLayersTree(true);
+    }
 
     // Extent
     var aExtent = goog.isDefAndNotNull(opt_options.extent) ? opt_options.extent : [];
@@ -723,13 +843,16 @@ nsVmap.nsToolsManager.Print.prototype.printController.prototype.getMapsJsonDef =
         aExtent[3] + (aExtent[3] - aExtent[1])
     ];
     var sOverviewExtent = '';
+    var sCompareExtent = '';
     for (var i = 0; i < aExtent.length; i++) {
         if (i > 0) {
             sExtent += '|';
             sOverviewExtent += '|';
+            sCompareExtent += (goog.isDefAndNotNull(opt_options.extentCompare)) ? '|' : '';
         }
         sExtent += aExtent[i];
         sOverviewExtent += aOverviewExtent[i];
+        sCompareExtent += (goog.isDefAndNotNull(opt_options.extentCompare)) ? opt_options.extentCompare[i] : '';
     }
 
     // Features
@@ -771,6 +894,15 @@ nsVmap.nsToolsManager.Print.prototype.printController.prototype.getMapsJsonDef =
             'features_zoom': 400
         };
     }
+    if (goog.isDefAndNotNull(opt_options.mapImageSizeCompare) && this.$scope_.$root["compare_enabled"]) {
+        var oCompareDef = {
+            'map_id': sMapIdCompare,
+            'map_json': sMapJSONCompare,
+            'image_size': (opt_options.mapImageSizeCompare[0] * resolutionCoeff) + '|' + (opt_options.mapImageSizeCompare[1] * resolutionCoeff),
+            'resolution_coeff': resolutionCoeff,
+            'extent': sCompareExtent
+        };
+    }
 
     var oMapsJson = [];
     if (goog.isDefAndNotNull(oMapDef)) {
@@ -786,45 +918,26 @@ nsVmap.nsToolsManager.Print.prototype.printController.prototype.getMapsJsonDef =
         });
     }
 
+    if (goog.isDefAndNotNull(oCompareDef)) {
+        oMapsJson.push({
+            'target': '#map_image_compare',
+            'map_definition': oCompareDef
+        });
+    }
+
     var mapsJson = JSON.stringify(oMapsJson);
 
     return mapsJson;
 }
 
-/**
- * Get the size of a target in a template
- * @param {string} template
- * @param {string} target
- * @returns {Array<Number>|undefined}
- */
-nsVmap.nsToolsManager.Print.prototype.printController.prototype.getTemplateTargetSize = function (template, target) {
-
-    var targetDiv = $(template).find(target);
-
-    // Vérifie la présence de '#map_image'
-    if (!goog.isDef(targetDiv.get(0))) {
-        oVmap.log('Aucune balise ' + target + ' trouvée dans le template');
-        return undefined;
-    }
-
-    $('body').append(template);
-
-    var targetHeight = targetDiv.height();
-    var targetWidth = targetDiv.width();
-
-    // Supprime le template du body de Vmap
-    $(template).remove();
-
-    return [targetWidth, targetHeight];
-};
-
 /**
  * Get the html definition of the template with base64 images
+ * @param  {string} sTarget
  * @returns {String}
  */
-nsVmap.nsToolsManager.Print.prototype.printController.prototype.getLegendTemplate = function () {
+nsVmap.nsToolsManager.Print.prototype.printController.prototype.getLegendTemplate = function (sTarget) {
 
-    var template = $('#maplegend').clone();
+    var template = $(sTarget).clone();
 
     // Transforme les images en base64
     template.find('img').each(function (index) {
diff --git a/module/javascript/app/vmap/tools/printBox.js b/module/javascript/app/vmap/tools/printBox.js
index b359736577fd4fc861e58c471cf2f0aad568d5ae..d25f47f7a8ca5d9588d23e08f23767f1ad9d6c16 100755
--- a/module/javascript/app/vmap/tools/printBox.js
+++ b/module/javascript/app/vmap/tools/printBox.js
@@ -18,11 +18,13 @@ goog.require('ol.interaction.Translate');
 nsVmap.nsToolsManager.PrintBox = function (opt_options) {
     oVmap.log('nsVmap.nsToolsManager.PrintBox');
 
-    this.map_ = oVmap.getMap().getOLMap();
-
     // Valeurs par défaut
     opt_options = goog.isDefAndNotNull(opt_options) ? opt_options : {};
 
+    this.oMap_ = (goog.isDefAndNotNull(opt_options["map_object"])? opt_options["map_object"]: oVmap.getMap());
+
+    this.map_ = this.oMap_.getOLMap();
+
     /**
      * The print box feature
      * @private
@@ -45,7 +47,7 @@ nsVmap.nsToolsManager.PrintBox = function (opt_options) {
      * @type {ol.layer.Vector}
      * @private
      */
-    this.oOpenLayersOverlay_ = oVmap.getMap().addVectorLayer();
+    this.oOpenLayersOverlay_ = this.oMap_.addVectorLayer();
 
     /**
      * @type {ol.Collection}
@@ -110,7 +112,7 @@ nsVmap.nsToolsManager.PrintBox.prototype.managePrintBox = function (sInteraction
     this.unlistenMapMovements();
 
     // Ajoute l'interaction de déplacement de la printBox
-    oVmap.getMap().setInteraction(this.translateInteraction_, sInteractionName);
+    this.oMap_.setInteraction(this.translateInteraction_, sInteractionName);
 
 };
 
@@ -122,12 +124,23 @@ nsVmap.nsToolsManager.PrintBox.prototype.unmanagePrintBox = function () {
     oVmap.log('nsVmap.nsToolsManager.PrintBox.unmanagePrintBox');
 
     // remove l'action de modification
-    oVmap.getMap().removeActionsAndTooltips();
+    this.oMap_.removeActionsAndTooltips();
 
     this.drawPrintBox();
     this.listenMapMovements();
 };
 
+/**
+ * Cancel the printZone manage interaction and adapt the view on it
+ * @export
+ */
+nsVmap.nsToolsManager.PrintBox.prototype.unmanagePrintBoxAndLock = function () {
+    oVmap.log('nsVmap.nsToolsManager.PrintBox.unmanagePrintBox');
+
+    // remove l'action de modification
+    this.oMap_.removeActionsAndTooltips();
+};
+
 /**
  * Get the print box scale
  * @returns {Number|String}
@@ -149,7 +162,7 @@ nsVmap.nsToolsManager.PrintBox.prototype.getScale = function () {
         nearest: true
     });
 
-    var scale = oVmap.getMap().getScale();
+    var scale = this.oMap_.getScale();
 
     setTimeout(function () {
         // Retrouve la position initiale
@@ -166,13 +179,13 @@ nsVmap.nsToolsManager.PrintBox.prototype.getScale = function () {
  * @export
  */
 nsVmap.nsToolsManager.PrintBox.prototype.setScale = function (newScale) {
-    
+
     // Échelle courante
     var currentScale = this.getScale();
 
     // Calcul du delta entre l'échelle courrante et l'échelle voulue
     var deltaScale = newScale / currentScale;
-    
+
     // Mise sous forme de variables pour une meilleure compréhension
     var currentExtent = this.getExtent();
     var xmin = currentExtent[0];
@@ -185,7 +198,7 @@ nsVmap.nsToolsManager.PrintBox.prototype.setScale = function (newScale) {
     // Calcul de la nouvelle hauteur/largeur de la printBox
     var newLength = length * deltaScale;
     var newHeight = height * deltaScale;
-    
+
     // Calcul des nouvelles coordonnées en fonction du centre et des nouvelles hauteur/largeur
     var center = this.printBoxFeature_.getGeometry().getInteriorPoint().getCoordinates();
     var newXmin = center[0] - newLength / 2;
@@ -198,10 +211,10 @@ nsVmap.nsToolsManager.PrintBox.prototype.setScale = function (newScale) {
     this.printBoxFeature_ = new ol.Feature({
         geometry: box
     });
-    
+
     // Supprime l'ancienne feature
     this.oOpenLayersOverlayFeatures_.clear();
-    
+
     // Ajoute la nouvelle feature
     this.oOpenLayersOverlay_.getSource().addFeature(this.printBoxFeature_);
 };
@@ -239,7 +252,7 @@ nsVmap.nsToolsManager.PrintBox.prototype.getExtent = function () {
  */
 nsVmap.nsToolsManager.PrintBox.prototype.listenMapMovements = function () {
 
-    this.printBoxEvent_ = oVmap.getMap().setEventOnMap('precompose', this.drawPrintBox, this);
+    this.printBoxEvent_ = this.oMap_.setEventOnMap('precompose', this.drawPrintBox, this);
 };
 
 /**
@@ -286,10 +299,12 @@ nsVmap.nsToolsManager.PrintBox.prototype.createPrintBox = function (printBoxSize
     var boxWidth = printBoxSize[0];
     var boxHeight = printBoxSize[1];
 
-    var x1 = $('#map1').width() / 2 - boxWidth / 2;
-    var x2 = $('#map1').width() / 2 + boxWidth / 2;
-    var y1 = $('#map1').height() / 2 - boxHeight / 2;
-    var y2 = $('#map1').height() / 2 + boxHeight / 2;
+    var sMapComponentId = this.map_.getViewport().getAttribute('id');
+
+    var x1 = $('#' + sMapComponentId).width() / 2 - boxWidth / 2;
+    var x2 = $('#' + sMapComponentId).width() / 2 + boxWidth / 2;
+    var y1 = $('#' + sMapComponentId).height() / 2 - boxHeight / 2;
+    var y2 = $('#' + sMapComponentId).height() / 2 + boxHeight / 2;
 
     var point1 = [x1, y2];
     var point3 = [x2, y1];
@@ -306,4 +321,4 @@ nsVmap.nsToolsManager.PrintBox.prototype.createPrintBox = function (printBoxSize
     boxFeature.set('pixelExtent', [x1, y1, x2, y2]);
 
     return boxFeature;
-};
\ No newline at end of file
+};
diff --git a/module/javascript/app/vmap/tools/select/basicselect.js b/module/javascript/app/vmap/tools/select/basicselect.js
index f8d0af3ccdbafe8cc7ba4a165cb54767d5d7e001..200baf000377bef18fafd189872aea028fddca67 100755
--- a/module/javascript/app/vmap/tools/select/basicselect.js
+++ b/module/javascript/app/vmap/tools/select/basicselect.js
@@ -542,6 +542,7 @@ nsVmap.nsToolsManager.BasicSelect.prototype.basicSelectController.prototype.repl
 nsVmap.nsToolsManager.BasicSelect.prototype.basicSelectController.prototype.displaySelectionPopup = function (aSelection, olPoint) {
     oVmap.log('nsVmap.nsToolsManager.BasicSelect.prototype.basicSelectController.prototype.displaySelectionPopup');
 
+    var this_ = this;
     var scope = this.$scope_;
 
     for (var i = 0; i < aSelection.length; i++) {
@@ -659,6 +660,51 @@ nsVmap.nsToolsManager.BasicSelect.prototype.basicSelectController.prototype.disp
                 }
             });
         }
+
+        aSelection[i]['mapPopup'].addAction({
+            'content': '<span class="icon-link_url"></span> Lien vers cet objet' ,
+            'event': angular.bind(this, function(i){
+                scope.$apply(function () {
+                    // generate url for this object;
+                    var sUrl = this_['properties']['web_server_name'] + "/" + this_['properties']['application'];
+
+                    if (goog.isDefAndNotNull(this_['properties']['environment'])){
+                        if (this_['properties']['environment'] != ""){
+                            sUrl += "_" + this_['properties']['environment'];
+                        }
+                    }
+
+                    sUrl += "?mode_id=vmap&";
+
+                    var oMapCatalog = oVmap.getMapManager().getMapCatalog();
+                    var iMapId = oMapCatalog["maps"][oMapCatalog["usedMap"]]["map_id"];
+
+                    sUrl += "map_id=" + iMapId + "&";
+                    sUrl += "bo_id=" + aSelection[i]["bo_type"] + "&";
+                    sUrl += "ids=" + aSelection[i]["bo_id_value"];
+
+                    //copy url to clipboard
+                    var textArea = document.createElement("textarea");
+                    textArea.value = sUrl;
+                    document.body.appendChild(textArea);
+                    textArea.focus();
+                    textArea.select();
+
+                    try {
+                        var successful = document.execCommand('copy');
+                        if (successful){
+                            $.notify('L\'URL d\'accés à cette objet a été copié dans votre presse-papier : \n' + sUrl, 'success');
+                        } else {
+                            $.notify('L\'URL d\'accés à cette objet n\'a pas pu être copié dans votre presse-papier : \n' + sUrl, 'error');
+                        }
+                    } catch (err) {
+                        $.notify('L\'URL d\'accés à cette objet n\'a pas pu être copié dans votre presse-papier : \n' + sUrl, 'error');
+                        console.error('Fallback: Oops, unable to copy', err);
+                    }
+                    document.body.removeChild(textArea);
+                });
+            }, i)
+        });
     }
 
     // Ajoute les résultats
diff --git a/module/javascript/app/vmap/tools/select/select.js b/module/javascript/app/vmap/tools/select/select.js
index 6a7eddf0e1b15822a8732b90e569e4e05093d0fd..0944cee5c36c0157e090e853d22cadfe027a9f6e 100755
--- a/module/javascript/app/vmap/tools/select/select.js
+++ b/module/javascript/app/vmap/tools/select/select.js
@@ -366,6 +366,7 @@ nsVmap.nsToolsManager.Select.prototype.selectController = function ($scope, $tim
         this['snapOptions']['mode'] = oVmap['properties']['snapping']['defaut_snapp_mode'];
         this['snapOptions']['limit'] = oVmap['properties']['snapping']['defaut_limit'];
         this['snapOptions']['visible'] = oVmap['properties']['snapping']['defaut_visibility'];
+        this['snapOptions']['avoidSuperpositions'] = {};
     }
 
     /**
@@ -373,6 +374,16 @@ nsVmap.nsToolsManager.Select.prototype.selectController = function ($scope, $tim
      */
     this['tmpSnapOptions'] = angular.copy(this['snapOptions']);
 
+    /**
+     * Queryable Business Objects
+     */
+    this['aQueryableBOs'] = [];
+
+    /**
+    * Business objects avaliable for avoiding superpositions
+    */
+    $scope['aAvoidSuperpositionsBOs'] = [];
+
     /**
      * Tree resulting the various GetFeatureInfo requests
      */
@@ -523,10 +534,33 @@ nsVmap.nsToolsManager.Select.prototype.selectController = function ($scope, $tim
         features: this.oOverlayFeatures_
     });
 
-    this.modify_.on('modifyend', function () {
+    this.modify_.on('modifyend', function (evt) {
+
+        // Récupère la feature ajoutée
+        var aFeatures = evt.features.getArray();
+
+        var j = 0;
+        for (var i = 0; i < aFeatures.length; i++) {
+            // Évite les superpositions avec les autres couches si besoin
+            this_.avoidSuperpositions(aFeatures[i]).then(function(){
+                j++;
+                if (!j < aFeatures.length) {
+                    setTimeout(function () {
+                        // Enregistre les changements
+                        this_.putFeaturesOnTheElement(this_.oOverlayFeatures_.getArray());
+                    });
+                }
+            });
+        }
+
+        // Cas où avoidSuperpositions n'ait pas effectué de callback
         setTimeout(function () {
-            this_.putFeaturesOnTheElement(this_.oOverlayFeatures_.getArray());
-        });
+            if (j === 0) {
+                console.error('avoidSuperpositions never sents callback');
+                // Enregistre les changements
+                this_.putFeaturesOnTheElement(this_.oOverlayFeatures_.getArray());
+            }
+        }, 3000);
     });
 
     /**
@@ -685,6 +719,39 @@ nsVmap.nsToolsManager.Select.prototype.selectController.prototype.loadQueryableB
     });
 };
 
+/**
+ * Load this.aAvoidSuperpositionsBOs
+ *
+ */
+nsVmap.nsToolsManager.Select.prototype.selectController.prototype.loadAvoidSuperpositionBos = function () {
+    oVmap.log('nsVmap.nsToolsManager.Select.selectController.loadAvoidSuperpositionBos');
+
+    var this_ = this;
+
+    // Types de géométries pour le calcul des jointures
+    var aActiveGeomTypes = ['POLYGON', 'MULTIPOLYGON', 'GEOMETRY', 'GEOMETRYCOLLECTION'];
+
+    // Objets métiers actifs pour la calcul des jointures
+    this.$scope_['aAvoidSuperpositionsBOs'] = [];
+
+    if (goog.isDefAndNotNull(this['editableFeatureType'])) {
+
+        // Si la couche en cours d'insertion est dans aActiveGeomTypes
+        if (aActiveGeomTypes.indexOf(this['editableFeatureType']) !== -1) {
+            for (var i = 0; i < this['aQueryableBOs'].length; i++) {
+
+                // Si la couche cible est dans aActiveGeomTypes
+                if (goog.isDefAndNotNull(this['aQueryableBOs'][i]['bo_geom_type'])) {
+                    if(aActiveGeomTypes.indexOf(this['aQueryableBOs'][i]['bo_geom_type']) !== -1){
+
+                        this.$scope_['aAvoidSuperpositionsBOs'].push(this['aQueryableBOs'][i]);
+                    }
+                }
+            }
+        }
+    }
+}
+
 /**
  * Vérifie que l'échelle en cours respecte les spécification de l'objet métier
  */
@@ -1880,6 +1947,9 @@ nsVmap.nsToolsManager.Select.prototype.selectController.prototype.editFeature =
         // Affiche la palette de modification
         $('#basictools-select-modify-palette').show();
 
+        // Chage le liste des BO intersectables par calcul de polygones jointifs
+        this_.loadAvoidSuperpositionBos();
+
         // Timeout car lors du toggleOutTools, clearOverlays est lancé
         setTimeout(function () {
             // Ajoute la/les feature(s)
@@ -2126,12 +2196,160 @@ nsVmap.nsToolsManager.Select.prototype.selectController.prototype.startDrawing =
                 this_.oOverlayLayer_.getSource().addFeature(feature);
             }
 
+            // Évite les superpositions avec les autres couches si besoin
+            this_.avoidSuperpositions(feature);
+
             // Ajoute les géométries en mode multi ou simple à editableSelection.olFeature
             this_.putFeaturesOnTheElement(this_.oOverlayFeatures_.getArray());
         });
     }, this);
 };
 
+/**
+ * Edit the given feature to avoid superpositions with layers defined in snapOptions.avoidSuperpositions
+ * @param {ol.Feature} olFeature
+ * @returns {ol.Feature}
+ */
+nsVmap.nsToolsManager.Select.prototype.selectController.prototype.avoidSuperpositions = function (olFeature) {
+    oVmap.log('nsVmap.nsToolsManager.Select.selectController.avoidSuperpositions');
+
+    var deferred = this.$q_.defer();
+
+    // Objets métiers à intersecter
+    var aSuperpositionBos = [];
+    for (var bo_id in this['snapOptions']['avoidSuperpositions']) {
+        if (this['snapOptions']['avoidSuperpositions'][bo_id] === true) {
+            aSuperpositionBos.push(bo_id);
+        }
+    }
+
+    // Remplace la géométrie par celle calculée
+    if (aSuperpositionBos.length > 0) {
+        this.setDiffGeom_(aSuperpositionBos, olFeature).then(function(olFeature){
+            deferred.resolve(olFeature);
+        });
+    } else {
+        deferred.resolve(olFeature);
+    }
+
+    return deferred.promise;
+}
+
+/**
+ * Modify the feature geometry to avoid superpositions with BOs in aSuperpositionBos
+ *
+ * @param  {string} aSuperpositionBos
+ * @param  {ol.Feature} olFeature
+ * @param  {object|undefines} opt_options
+ */
+nsVmap.nsToolsManager.Select.prototype.selectController.prototype.setDiffGeom_ = function (aSuperpositionBos, olFeature, opt_options) {
+    oVmap.log('nsVmap.nsToolsManager.Select.selectController.setDiffGeom_');
+
+    if (!goog.isArray(aSuperpositionBos)) {
+        return 0;
+    }
+    if (!goog.isDefAndNotNull(olFeature)) {
+        return 0;
+    }
+    if (!goog.isDefAndNotNull(opt_options)) {
+        opt_options = {
+            bo_index: 0
+        }
+    }
+
+    var this_ = this;
+    var deferred = this.$q_.defer();
+    var sEWKTGeom = oVmap.getEWKTFromGeom(olFeature.getGeometry());
+
+    this.getDiffGeom_(aSuperpositionBos[opt_options.bo_index], sEWKTGeom).then(function(sNewEWKTGeom){
+
+        // Remplace la géométrie
+        olFeature.setGeometry(oVmap.getGeomFromEWKT(sNewEWKTGeom));
+
+        // Relance la fonction pour les autres objets métiers
+        opt_options.bo_index ++;
+        if (opt_options.bo_index < aSuperpositionBos.length) {
+            this_.setDiffGeom_(aSuperpositionBos, olFeature, opt_options).then(function(){
+                deferred.resolve(olFeature);
+            }, function(error){
+                console.error(error);
+            });
+        } else {
+            deferred.resolve(olFeature);
+        }
+    }, function(err){
+        console.error('Cannot get the diff geom: ', err)
+    });
+
+    return deferred.promise;
+}
+
+/**
+ * Get the diff superposition geometry
+ *
+ * @param  {string} sBoId
+ * @param  {string} sEWKTGeom
+ * @return {promise}
+ */
+nsVmap.nsToolsManager.Select.prototype.selectController.prototype.getDiffGeom_ = function (sBoId, sEWKTGeom) {
+    oVmap.log('nsVmap.nsToolsManager.Select.selectController.getDiffGeom_');
+
+    var oParams = {
+        'intersect_geom': sEWKTGeom
+    };
+
+    // Filtre pour ne pas s'éviter lui même
+    if (goog.isDefAndNotNull(this['editableSelection'])) {
+        if (this['editableSelection']['bo_type'] === sBoId) {
+            if (goog.isDefAndNotNull(this['editableSelection']['bo_id_field']) &&
+                goog.isDefAndNotNull(this['editableSelection']['bo_id_value'])) {
+
+                oParams['filter'] = {
+                    'column': this['editableSelection']['bo_id_field'],
+                    'compare_operator': '!=',
+                    'value': this['editableSelection']['bo_id_value']
+                }
+            }
+        }
+    }
+
+    var deferred = this.$q_.defer();
+    ajaxRequest({
+        'method': 'POST',
+        'url': oVmap['properties']['api_url'] + '/vmap/querys/' + sBoId + '/diff_geometry',
+        'headers': {
+            'X-HTTP-Method-Override': 'GET',
+            'Accept': 'application/x-vm-json'
+        },
+        'data': oParams,
+        'scope': this.$scope_,
+        'success': function (response) {
+
+            if (!goog.isDefAndNotNull(response['data'])) {
+                deferred.reject('response.data not defined');
+                return 0;
+            }
+            if (goog.isDefAndNotNull(response['data']['errorMessage'])) {
+                deferred.reject(response['data']['errorMessage']);
+                return 0;
+            }
+            if (!goog.isDefAndNotNull(response['data'][0])) {
+                deferred.resolve(sEWKTGeom);
+                return 0;
+            }
+            if (!goog.isDefAndNotNull(response['data'][0]['diff_geom'])) {
+                deferred.resolve(sEWKTGeom);
+                return 0;
+            }
+            deferred.resolve(response['data'][0]['diff_geom']);
+        },
+        'error': function (response) {
+            deferred.reject(response);
+        }
+    });
+    return deferred.promise;
+}
+
 /**
  * Put the array of features passed on aFeatures on editableSelection.olFeature with MULTI... form
  * @param {array} aFeatures
@@ -2363,7 +2581,17 @@ nsVmap.nsToolsManager.Select.prototype.selectController.prototype.finishEdition
 nsVmap.nsToolsManager.Select.prototype.selectController.prototype.showSnappingOptionsModal = function () {
     oVmap.log('nsVmap.nsToolsManager.Select.prototype.selectController.prototype.showSnappingOptionsModal');
 
+    var this_ = this;
     this['tmpSnapOptions'] = angular.copy(this['snapOptions']);
+
+    this.$scope_.$applyAsync(function(){
+        for (var i = 0; i < this_['aQueryableBOs'].length; i++) {
+            if (!goog.isDefAndNotNull(this_['tmpSnapOptions']['avoidSuperpositions'][this_['aQueryableBOs'][i]['bo_id']])) {
+                this_['tmpSnapOptions']['avoidSuperpositions'][this_['aQueryableBOs'][i]['bo_id']] = false;
+            }
+        }
+    });
+
     $('#vmap-select-snap-options-modal').modal('show');
 };
 
@@ -2477,6 +2705,10 @@ nsVmap.nsToolsManager.Select.prototype.selectController.prototype.loadBoVectorSn
                     oBo['bo_snapping_loaded'] = null;
                     return 0;
                 }
+                if (!goog.isDefAndNotNull(response['data'][0])) {
+                    oBo['bo_snapping_loaded'] = null;
+                    return 0;
+                }
                 if (response['data'][0]['count'] > this_['snapOptions']['snappingObjectsLimit']) {
                     oBo['bo_snapping_loaded'] = null;
                     var text = 'Limit de points atteinte pour object ';
@@ -2489,7 +2721,8 @@ nsVmap.nsToolsManager.Select.prototype.selectController.prototype.loadBoVectorSn
                     if (goog.isDefAndNotNull(response['data'][i]['geom'])) {
                         geom = response['data'][i]['geom'];
                         aFeatures.push(new ol.Feature({
-                            geometry: oVmap.getGeomFromEWKT(geom)
+                            geometry: oVmap.getGeomFromEWKT(geom),
+                            'bo_id': bo_id
                         }));
                     }
                 }
diff --git a/module/javascript/app/vmap/tools/toolsmanager.js b/module/javascript/app/vmap/tools/toolsmanager.js
index ba4c644aea4d99f191adc967b8a5f8d78f45a29a..1b6a247c6b746f13abf5c4fa6ff32e759973f169 100755
--- a/module/javascript/app/vmap/tools/toolsmanager.js
+++ b/module/javascript/app/vmap/tools/toolsmanager.js
@@ -143,13 +143,18 @@ nsVmap.nsToolsManager.ToolsManager.prototype.vmapToolsContainerDirective = funct
 
 /**
  * Basic tools Controller
+ * @param {object} $scope
  * @export
+ * @ngInject
  * @constructor
  */
-nsVmap.nsToolsManager.ToolsManager.prototype.vmapToolsController = function () {
+nsVmap.nsToolsManager.ToolsManager.prototype.vmapToolsController = function ($scope) {
     oVmap.log("nsVmap.nsToolsManager.BasicTools.prototype.vmapToolsController");
 
     this['oToolsTree'] = oVmap.getToolsManager().getToolsTree();
+
+    $scope.$root["bLoadVmapModule"] = goog.isDefAndNotNull(this['oToolsTree']);
+
     this['openedTool'] = '_';
 };
 
@@ -176,7 +181,7 @@ nsVmap.nsToolsManager.ToolsManager.prototype.loadSyncToolsTree = function () {
             oToolsTree = data['usermodules'];
         }
     });
-    
+
     return oToolsTree;
 };
 
@@ -225,4 +230,4 @@ nsVmap.nsToolsManager.ToolsManager.prototype.getTool = function (tool) {
 // Définit la directive et le controller
 oVmap.module.directive('appVmaptools', nsVmap.nsToolsManager.ToolsManager.prototype.vmapToolsDirective);
 oVmap.module.directive('toolsContainer', nsVmap.nsToolsManager.ToolsManager.prototype.vmapToolsContainerDirective);
-oVmap.module.controller('AppVmaptoolsController', nsVmap.nsToolsManager.ToolsManager.prototype.vmapToolsController);
\ No newline at end of file
+oVmap.module.controller('AppVmaptoolsController', nsVmap.nsToolsManager.ToolsManager.prototype.vmapToolsController);
diff --git a/module/javascript/app/vmap/tools/urlexporter.js b/module/javascript/app/vmap/tools/urlexporter.js
index 85e757f8f70c2bac1538b099482fd06940cec290..d531827eddb069217fffec94531c0200d183ca03 100644
--- a/module/javascript/app/vmap/tools/urlexporter.js
+++ b/module/javascript/app/vmap/tools/urlexporter.js
@@ -68,45 +68,38 @@ nsVmap.nsToolsManager.Urlexporter.prototype.urlExporterController = function ($s
     /**
      * @type {string}
      */
-    this["urlToExport"] = "";
+    this["privateExportUrl"] = "";
+
     /**
-     * @type {boolean}
+     * @type {string}
      */
-    this["usePublicToken"] = false;
-
-    this["urlConstructor"]();
-
-    // Affiche les modales en plein écran pour la version mobile
-    //if (oVmap['properties']['is_mobile']) {
-    //    $element.find('.modal').on('shown.bs.modal', function () {
-    //        $('.modal-backdrop.fade.in').hide();
-    //        $('.modal.fade.in').find('.modal-dialog').addClass('mobile-full-modal');
-    //    });
-    //}
-
-    console.log(this['properties']);
+    this["publicExportUrl"] = "";
 
     // recalcule l'url quand on change de carte
     oVmap['scope'].$on('mapChanged', function () {
-        this_["urlConstructor"]();
+        this_["privateExportUrl"] = this_.getExportUrl();
+        this_["publicExportUrl"] = this_.getExportUrl(true);
     });
 
-    $scope.$watch("ctrl.usePublicToken", function(){
-        this_["urlConstructor"]();
-    })
-
+    // recalcule l'url quand on bouge la  carte
     oVmap.getMap().getOLMap().on("moveend", function(event){
-        this_["urlConstructor"]();
+        this_["privateExportUrl"] = this_.getExportUrl();
+        this_["publicExportUrl"] = this_.getExportUrl(true);
     });
+
+    // Recalcule l'URL
+    this_["privateExportUrl"] = this_.getExportUrl();
+    this_["publicExportUrl"] = this_.getExportUrl(true);
 };
 
 /**
- * Display the user form in display mode
- * @returns {undefined}
+ * Generates and return the export URL
+ * @param  {boolean} bPublic
+ * @return {string}
  * @export
  */
-nsVmap.nsToolsManager.Urlexporter.prototype.urlExporterController.prototype.urlConstructor = function () {
-    oVmap.log("nsVmap.nsToolsManager.Urlexporter.urlExporterController.urlConstructor");
+nsVmap.nsToolsManager.Urlexporter.prototype.urlExporterController.prototype.getExportUrl = function (bPublic) {
+    oVmap.log("nsVmap.nsToolsManager.Urlexporter.urlExporterController.getExportUrl");
 
     var sUrl = this['properties']['web_server_name'] + "/" + this['properties']['application'];
 
@@ -116,7 +109,7 @@ nsVmap.nsToolsManager.Urlexporter.prototype.urlExporterController.prototype.urlC
         }
     }
 
-    sUrl += "?";
+    sUrl += "?mode_id=vmap&";
 
     var oMapCatalog = oVmap.getMapManager().getMapCatalog();
     var iMapId = oMapCatalog["maps"][oMapCatalog["usedMap"]]["map_id"];
@@ -124,7 +117,7 @@ nsVmap.nsToolsManager.Urlexporter.prototype.urlExporterController.prototype.urlC
     sUrl += "map_id=" + iMapId;
 
     // si public add token
-    if (this["usePublicToken"]){
+    if (bPublic === true){
         sUrl += "&token=" + this['properties']['public_token'];
     }
 
@@ -132,9 +125,33 @@ nsVmap.nsToolsManager.Urlexporter.prototype.urlExporterController.prototype.urlC
     var sExtent = oVmap.getMap().getOLMap().getView().calculateExtent(oVmap.getMap().getOLMap().getSize()).join("|");
     sUrl += "&extent=" + encodeURI(sExtent);
 
-    this["urlToExport"] = sUrl;
+    return sUrl;
 };
 
+/**
+ * Copy the generated URL on the clipboard
+ * @param  {boolean} bPublic
+ * @export
+ */
+nsVmap.nsToolsManager.Urlexporter.prototype.urlExporterController.prototype.copyUrl = function (bPublic) {
+    oVmap.log("nsVmap.nsToolsManager.Urlexporter.urlExporterController.copyUrl");
+
+    /* Get the text field */
+    if (bPublic === true) {
+        var copyText = document.getElementById("publicExportUrlField");
+    } else {
+        var copyText = document.getElementById("privateExportUrlField");
+    }
+
+    /* Select the text field */
+    copyText.select();
+
+    /* Copy the text inside the text field */
+    document.execCommand("copy");
+
+    $.notify('Copié', 'success');
+}
+
 // Définit la directive et le controller
 oVmap.module.directive('appUrlExporter', nsVmap.nsToolsManager.Urlexporter.prototype.urlExporterDirective);
-oVmap.module.controller('AppUrlExporterController', nsVmap.nsToolsManager.Urlexporter.prototype.urlExporterController);
\ No newline at end of file
+oVmap.module.controller('AppUrlExporterController', nsVmap.nsToolsManager.Urlexporter.prototype.urlExporterController);
diff --git a/module/javascript/app/vmap/vmap.js b/module/javascript/app/vmap/vmap.js
index 48dbc1bacdb92c117848b877817f120614ccbc71..f178a8c8318359837bd33d27463450bfe7744ea8 100644
--- a/module/javascript/app/vmap/vmap.js
+++ b/module/javascript/app/vmap/vmap.js
@@ -97,6 +97,13 @@ oVmap.properties = {};
  */
 oVmap.oMap_ = {};
 
+
+/**
+ * Objet which contains the mapComapre
+ * @type {nsVmap.MapCompare}
+ * @private
+ */
+oVmap.oMapCompare_ = {};
 /**
  * Objet which contains the layers tools (on the left band)
  * @type {nsVmap.nsMapManager.MapManager}
@@ -196,6 +203,7 @@ oVmap.init = function () {
 
     // Instenciation des objects Vmap
     oVmap.oMap_ = new nsVmap.Map();
+    oVmap.oMapCompare_ = new nsVmap.MapCompare();
     oVmap.oMapManager_ = new nsVmap.nsMapManager.MapManager();
     oVmap.oToolsManager_ = new nsVmap.nsToolsManager.ToolsManager();
 
@@ -283,6 +291,12 @@ oVmap.vmapController = function ($sanitize) {
      * @api stable
      */
     this.map = this['map'] = oVmap.getMap().getOLMap();
+    /**
+     * The OpenLayers map
+     * @type {ol.Map}
+     * @api stable
+     */
+    this.mapCompare = this['mapCompare'] = oVmap.getMapCompare().getOLMap();
 
     /**
      * The current action on map
@@ -362,6 +376,16 @@ oVmap.getMap = function () {
     return this.oMap_;
 };
 
+/**
+ * nsVmap.oMapCompare_ getter
+ * @return {nsVmap.MapCompare} Map to use to compare
+ * @export
+ * @api experimental
+ */
+oVmap.getMapCompare = function () {
+    return this.oMapCompare_;
+};
+
 /**
  * nsVmap.oMapManager_ getter
  * @return {nsVmap.nsMapManager.MapManager} Tools fo layers
@@ -719,6 +743,8 @@ oVmap.resizeLayerTools = function (animate) {
 
     if (goog.isDef(angular.element($('#olMap')).scope()))
         angular.element($('#olMap')).scope()['ctrl'].startAnimation();
+    if (goog.isDef(angular.element($('#olMapCompare')).scope()))
+        angular.element($('#olMapCompare')).scope()['ctrl'].startAnimation();
 
     var aItems = ["layertree", "layersorder", "maplegendcontainer"];
     var iMarge = 0;
@@ -851,6 +877,7 @@ oVmap.printElem = function (elem) {
  */
 oVmap.maxResizeBottomBar = function () {
     angular.element($('#olMap')).scope()['ctrl'].startAnimation();
+    angular.element($('#olMapCompare')).scope()['ctrl'].startAnimation();
 
     $(".open-more-selection-info").toggleClass("reverse");
 
@@ -869,13 +896,15 @@ oVmap.maxResizeBottomBar = function () {
  */
 oVmap.minResizeBottomBar = function () {
     angular.element($('#olMap')).scope()['ctrl'].startAnimation();
-
+    angular.element($('#olMapCompare')).scope()['ctrl'].startAnimation();
+    
     if ($("#map-container").hasClass("open2")) {
         $("#map-container").removeClass("open2");
         $("#bottombar").removeClass("open2");
         $(".open-more-selection-info").removeClass("reverse");
     } else if ($("#map-container").hasClass("open")) {
         $("#map-container").addClass("minus");
+        $("#map-container-compare").addClass("minus");
     }
 };
 
diff --git a/module/javascript/vitis/script_module.js b/module/javascript/vitis/script_module.js
index 00d7bea38f0f130a3f1f55460702749cb216fc1f..d740803e7e6612533b3c6704dd7e89348b7bad86 100644
--- a/module/javascript/vitis/script_module.js
+++ b/module/javascript/vitis/script_module.js
@@ -3607,4 +3607,22 @@ vitisApp.on('appMainDrtvLoaded', function () {
             "sMessage": "LIST_DELETE_CONFIRM_VMAP_BUSINESS_OBJECT"
         });
     };
+
+    /**
+     * Return true/false if the tool is avaliable for this user
+     * @param  {string} sTool
+     * @return {boolean}
+     */
+    angular.element(vitisApp.appMainDrtv).scope()["isVmapToolActive"] = function (sTool) {
+
+        var aTools;
+
+        if (propertiesSrvc['public_user']) {
+            aTools = propertiesSrvc['controls']['public_active_tools'].split('|');
+        } else {
+            aTools = propertiesSrvc['controls']['active_tools'].split('|');
+        }
+
+        return aTools.indexOf(sTool) !== -1 ? true : false;
+    }
 });
diff --git a/module/lang/lang-en.json b/module/lang/lang-en.json
index fc1484e29b1d7924daf36b156634486aca812d54..dfca19f973cb24a29baabc9d4d03dbef574b89c8 100644
--- a/module/lang/lang-en.json
+++ b/module/lang/lang-en.json
@@ -251,19 +251,40 @@
     "FORM_PRINTSERVER_ALIAS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Printserver alias",
     "FORM_VEREMAP_API_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Veremap API",
     "FORM_PROXY_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Proxy",
+    "FORM_AVALIABLE_CONTROLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Avaliable controls",
+    "FORM_ACTIVE_CONTROLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Actives controls",
     "FORM_AVALIABLE_TOOLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Avaliable tools",
     "FORM_ACTIVE_TOOLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Active tools",
-    "FORM_TOOLS_ATTRIBUTION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Attribution",
-    "FORM_TOOLS_MOUSE_POSITION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Mouse position",
-    "FORM_TOOLS_CURRENT_PROJECTION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Current projection",
-    "FORM_TOOLS_MAP_NAME_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Map Name",
-    "FORM_TOOLS_SCALE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Numeric scale",
-    "FORM_TOOLS_OVERVIEW_MAP_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Overview map",
-    "FORM_TOOLS_ROTATE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Rotate",
-    "FORM_TOOLS_SCALE_LINE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Scale line",
-    "FORM_TOOLS_ZOOM_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Zoom",
-    "FORM_TOOLS_ZOOM_SLIDER_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Zoom slider",
-    "FORM_TOOLS_REFRESH_SOCKET_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Refresh auto",
+    "FORM_AVALIABLE_PUBLIC_TOOLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Avaliable tools for public user",
+    "FORM_ACTIVE_PUBLIC_TOOLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Active tools for public user",
+    "FORM_CONTROLS_ATTRIBUTION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Attribution",
+    "FORM_CONTROLS_MOUSE_POSITION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Mouse position",
+    "FORM_CONTROLS_CURRENT_PROJECTION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Current projection",
+    "FORM_CONTROLS_MAP_NAME_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Map Name",
+    "FORM_CONTROLS_SCALE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Numeric scale",
+    "FORM_CONTROLS_OVERVIEW_MAP_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Overview map",
+    "FORM_CONTROLS_ROTATE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Rotate",
+    "FORM_CONTROLS_SCALE_LINE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Scale line",
+    "FORM_CONTROLS_ZOOM_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Zoom",
+    "FORM_CONTROLS_ZOOM_SLIDER_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Zoom slider",
+    "FORM_CONTROLS_REFRESH_SOCKET_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Refresh auto",
+    "FORM_TOOLS_MAP_MANAGER_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Gestion des cartes",
+    "FORM_TOOLS_LOCATION_SEARCH_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Localisation recherche",
+    "FORM_TOOLS_LOCATION_HOME_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Position initiale",
+    "FORM_TOOLS_LOCATION_REFRESH_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Rafraichissement carte",
+    "FORM_TOOLS_LOCATION_MAX_EXTENT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Étendue maximale",
+    "FORM_TOOLS_LOCATION_MY_POSITION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Position GPS",
+    "FORM_TOOLS_LOCATION_XY_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Position XY",
+    "FORM_TOOLS_LOCATION_PREC_NEXT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Précédent/suivant",
+    "FORM_TOOLS_URL_GENERATOR_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "URL de la carte en cours",
+    "FORM_TOOLS_MAP_COMPARE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Comparaison de cartes",
+    "FORM_TOOLS_MESURE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Mesures",
+    "FORM_TOOLS_SELECT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Interrogation",
+    "FORM_TOOLS_ADVANCED_SELECT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Interrogation avancée",
+    "FORM_TOOLS_INSERT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Insertion",
+    "FORM_TOOLS_PRINT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Impressions",
+    "FORM_TOOLS_CONFIG_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Configuration contrôles",
+    "FORM_TOOLS_USER_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Utilisateur en cours",
     "TITLE_DISPLAY_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Display",
     "TITLE_TOOLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Tools",
     "TITLE_CONTROLS_KEEPLOADED_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Keep tiles loaded when autorefreshing",
@@ -287,7 +308,12 @@
     "FORM_ENABLE_GETFEATUREINFO_CONFIGURATION_VMAP_CONFIG": "Enable GetFeatureInfo selection",
     "FORM_SELECTION_BUFFER_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Buffer (en mm sur l'écran)",
     "FORM_SELECTION_MAX_SCALE_BUFFER_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Buffer maximum (en mètres sur le terrain)",
-    "TITLE_SNAPPING_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Default snapping options",
+    "TITLE_SNAPPING_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Snapping options",
+    "FORM_SNAPPING_LIMIT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Manimum limit of points per object",
+    "FORM_SNAPPING_TOLERANCE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Snapping tolerance (in pixels)",
+    "FORM_SNAPPING_TYPE_ACC_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Default snapping type",
+    "FORM_SNAPPING_VISIBILITY_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Selected objects visibility",
+    "FORM_SNAPPING_AVOID_SUPERPOSITIONS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Avoid superposition",
     "FORM_SNAPPING_DEFAUT_LIMIT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Manimum limit of points per object",
     "FORM_SNAPPING_DEFAUT_TOLERANCE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Snapping tolerance (in pixels)",
     "FORM_SNAPPING_DEFAUT_TYPE_ACC_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Default snapping type",
diff --git a/module/lang/lang-fr.json b/module/lang/lang-fr.json
index 970eebf515a273666fd84369acf99d6700229a7a..a1b1a7bbd94917d3d4b0021295bd5cac3f109774 100644
--- a/module/lang/lang-fr.json
+++ b/module/lang/lang-fr.json
@@ -251,19 +251,40 @@
     "FORM_PRINTSERVER_ALIAS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Alias pintserver",
     "FORM_VEREMAP_API_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "API Veremap",
     "FORM_PROXY_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Proxy",
+    "FORM_AVALIABLE_CONTROLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Contrôles disponibles",
+    "FORM_ACTIVE_CONTROLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Contrôles actifs",
     "FORM_AVALIABLE_TOOLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Outils disponibles",
-    "FORM_ACTIVE_TOOLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Outils actifs par défaut",
-    "FORM_TOOLS_ATTRIBUTION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Attributions",
-    "FORM_TOOLS_MOUSE_POSITION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Position de la souris",
-    "FORM_TOOLS_CURRENT_PROJECTION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Projection en cours",
-    "FORM_TOOLS_MAP_NAME_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Nom de la carte",
-    "FORM_TOOLS_SCALE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Échelle numérique",
-    "FORM_TOOLS_SCALE_LINE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Échelle graphique",
-    "FORM_TOOLS_OVERVIEW_MAP_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Carte de supervision",
-    "FORM_TOOLS_ROTATE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Rotation",
-    "FORM_TOOLS_ZOOM_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Zoom",
-    "FORM_TOOLS_ZOOM_SLIDER_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Slider de zoom",
-    "FORM_TOOLS_REFRESH_SOCKET_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Rafraichissement auto",
+    "FORM_ACTIVE_TOOLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Outils actifs",
+    "FORM_AVALIABLE_PUBLIC_TOOLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Outils disponibles pour l'utilisateur public",
+    "FORM_ACTIVE_PUBLIC_TOOLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Outils actifs pour l'utilisateur public",
+    "FORM_CONTROLS_ATTRIBUTION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Attributions",
+    "FORM_CONTROLS_MOUSE_POSITION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Position de la souris",
+    "FORM_CONTROLS_CURRENT_PROJECTION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Projection en cours",
+    "FORM_CONTROLS_MAP_NAME_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Nom de la carte",
+    "FORM_CONTROLS_SCALE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Échelle numérique",
+    "FORM_CONTROLS_SCALE_LINE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Échelle graphique",
+    "FORM_CONTROLS_OVERVIEW_MAP_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Carte de supervision",
+    "FORM_CONTROLS_ROTATE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Rotation",
+    "FORM_CONTROLS_ZOOM_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Zoom",
+    "FORM_CONTROLS_ZOOM_SLIDER_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Slider de zoom",
+    "FORM_CONTROLS_REFRESH_SOCKET_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Rafraichissement auto",
+    "FORM_TOOLS_MAP_MANAGER_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Gestion des cartes",
+    "FORM_TOOLS_LOCATION_SEARCH_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Localisation recherche",
+    "FORM_TOOLS_LOCATION_HOME_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Localisation position initiale",
+    "FORM_TOOLS_LOCATION_REFRESH_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Rafraichissement couches",
+    "FORM_TOOLS_LOCATION_MAX_EXTENT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Localisation étendue maximale",
+    "FORM_TOOLS_LOCATION_MY_POSITION_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Localisation GPS",
+    "FORM_TOOLS_LOCATION_XY_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Localisation XY",
+    "FORM_TOOLS_LOCATION_PREC_NEXT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Localisation précédent/suivant",
+    "FORM_TOOLS_URL_GENERATOR_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "URL de la carte en cours",
+    "FORM_TOOLS_MAP_COMPARE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Comparaison de cartes",
+    "FORM_TOOLS_MESURE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Mesures",
+    "FORM_TOOLS_SELECT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Interrogation",
+    "FORM_TOOLS_ADVANCED_SELECT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Interrogation avancée",
+    "FORM_TOOLS_INSERT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Insertion",
+    "FORM_TOOLS_PRINT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Impressions",
+    "FORM_TOOLS_CONFIG_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Configuration contrôles",
+    "FORM_TOOLS_USER_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Utilisateur en cours",
     "TITLE_DISPLAY_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Affichage",
     "TITLE_TOOLS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Outils",
     "TITLE_CONTROLS_KEEPLOADED_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Garder les tuiles lors d'un rafraichissement automatique",
@@ -287,7 +308,12 @@
     "FORM_ENABLE_GETFEATUREINFO_CONFIGURATION_VMAP_CONFIG": "Interrogation par GetFeatureInfo",
     "FORM_SELECTION_BUFFER_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Buffer de sélection (en mm sur l'écran)",
     "FORM_SELECTION_MAX_SCALE_BUFFER_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Buffer maximum (en mètres sur le terrain)",
-    "TITLE_SNAPPING_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Options d'accrochage par défaut",
+    "TITLE_SNAPPING_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Options d'accrochage",
+    "FORM_SNAPPING_LIMIT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Limite de points accrochables",
+    "FORM_SNAPPING_TOLERANCE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Tolérance d'accrochage (pixels)",
+    "FORM_SNAPPING_TYPE_ACC_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Type d'accrochage",
+    "FORM_SNAPPING_VISIBILITY_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Visibilité des zones d'accrochage",
+    "FORM_SNAPPING_AVOID_SUPERPOSITIONS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Eviter les superpositions",
     "FORM_SNAPPING_DEFAUT_LIMIT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Limite de points accrochables",
     "FORM_SNAPPING_DEFAUT_TOLERANCE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Tolérance d'accrochage (pixels)",
     "FORM_SNAPPING_DEFAUT_TYPE_ACC_CONFIGURATION_CONFIGURATION_VMAP_CONFIG": "Type d'accrochage",
diff --git a/module/template/layers/layertree.html b/module/template/layers/layertree.html
index 5002135b16e7963f77a07de5163eee7f95c04f80..3141c44e2381b972cbd1df47df5f2c3cd7f5de90 100644
--- a/module/template/layers/layertree.html
+++ b/module/template/layers/layertree.html
@@ -12,10 +12,20 @@
 </div>
 
 <div id="layertree" class="layers-tool" collapse="{{ctrl.layerstree_collapsed === true ? 'out' : 'in'}}">
+
+    <ul class="nav nav-tabs layerstree-nav left" ng-show="$root.compare_enabled">
+        <li ng-class="{'active' : activeMap == 1}">
+            <a href="#" ng-click="activeMap=1;ctrl.resize()">Carte 1</a>
+        </li>
+        <li ng-class="{'active' : activeMap == 2}">
+            <a href="#" ng-click="activeMap=2;ctrl.resize()">Carte 2</a>
+        </li>
+    </ul>
     <div class="indicators">
         <span class="text-info icon-eye" style="font-size: 18px;line-height: 0" title="Définit si la couche est visible"></span>
     </div>
-    <ul class="tree">
+
+    <ul class="tree" ng-show="activeMap == 1 || !$root.compare_enabled">
         <div ng-repeat="node in tree.children| orderBy : 'name'" ng-if="node.view === undefined">
 
             <!-- Service -->
@@ -140,6 +150,108 @@
             </ul>
         </div>
     </ul>
+
+    <ul class="tree" ng-show="activeMap == 2 && $root.compare_enabled">
+        <div ng-repeat="node in compareTree.children| orderBy : 'name'" ng-if="node.view === undefined">
+
+            <!-- Service -->
+            <div class="layerstree-phather">
+                <div class="tree-father-collapse-btn service-name left" data-toggle="collapse" data-target="#comparetree_element_{{$id}}" onclick="setTimeout(function () {
+                                oVmap.resizeLayerTools(true)
+                            }, 500)" title="{{node.name}}">
+                    {{node.name}}
+                </div>
+                <div class="checkbox checkbox-info inline-checkbox right"
+                     ng-class="{'checkbox_indeterminate': node.visible === null}">
+                    <input id="compare_service_{{$id}}_visible"
+                           ng-init="node.visible = ctrl.isGroupVisible(node)"
+                           ng-model="node.visible"
+                           ng-model-options="{getterSetter: true}"
+                           ng-click="ctrl.setGroupVisible(node)"
+                           type="checkbox"
+                           style="cursor:pointer; position: absolute"
+                           title="Definit si le groupe est visible">
+                    <label for="compare_service_{{$id}}_visible"
+                           style="cursor:pointer"
+                           title="Definit si le groupe est visible"></label>
+                </div>
+            </div>
+
+            <!-- Calque -->
+            <ul id="comparetree_element_{{$id}}" class="collapse layers-tree-ul tree-element" ng-class="{'in': ctrl.layers_collapsed !== true}">
+                <div ng-repeat="layer in node.children">
+                    <li>
+                        <ul class="list-group-item layertree-item auto-height">
+
+                            <!-- Nom du calque -->
+                            <div class="layer-name layer-name-tree" title="{{layer.name}}">{{layer.name}}</div>
+                            <div class="layer-checkboxes">
+                                <button type="button"
+                                        class="btn btn-xs margin-sides-10 hidden"
+                                        ng-click="layer.olLayer.getSource().refreshWithTimestamp()">
+                                    <span class="glyphicon glyphicon-refresh"></span>
+                                </button>
+                                <div type="button" class="btn btn-xs layer-menu-button" ng-click="ctrl.toggleLayerMenu(layer, $event)">
+                                    <span ng-class="{'icon-filter': layer.olLayer.get('is_filtered'), 'icon-format_list_bulleted': !layer.olLayer.get('is_filtered')}"></span>
+                                </div>
+                                <!-- Checkbox visible -->
+                                <div class="checkbox checkbox-info inline-checkbox" style="z-index: 10;">
+                                    <input id="{{layer.$$hashKey}}_compare_visible_order_checkbox"
+                                           type="checkbox"
+                                           style="cursor:pointer; position: absolute"
+                                           title="Definit si le calque est visible"
+                                           ng-checked="layer.olLayer.values.visible === true"
+                                           ng-click="ctrl.setVisible(layer.olLayer, !layer.olLayer.values.visible);node.visible = ctrl.isGroupVisible(node)">
+                                    <label for="{{layer.$$hashKey}}_compare_visible_order_checkbox" style="cursor:pointer" title="Definit si la couche est visible"></label>
+                                </div>
+                            </div>
+                        </ul>
+                    </li>
+                    <div class="dropdown-menu layer-menu" ng-class="{'block': layer.displayedMenu === true}">
+                        <div class="layer-menu-list">
+                            <li ng-if="layer.olLayer.get('is_filtered')" ng-click="ctrl.displayFilterLayerModal(layer.olLayer)">
+                                <a href="#">
+                                    <span class="icon-filter"></span>
+                                    Filtre
+                                </a>
+                            </li>
+                            <li>
+                                <a href="#">
+                                    <div class="row">
+                                        <div class="col-xs-6">
+                                            <span class="icon-star-half"></span>
+                                            Transparence
+                                        </div>
+                                        <div class="col-xs-6">
+                                            <div class="layer-menu-list-slider">
+                                                <input data-app-layer-opacity-slider="" id="compare_slider_layer_form_{{layer.$$hashKey}}" type="text">
+                                            </div>
+                                        </div>
+                                    </div>
+                                </a>
+                            </li>
+                            <li ng-if="layer.olLayer.get('type') === 'imagewms' || layer.olLayer.get('type') === 'tilewms'"
+                                ng-repeat="sublayer in layer.olLayer.get('sublayers')">
+                                <div class="sublayer-checkboxes">
+                                    <!-- Checkbox visible -->
+                                    <div class="checkbox checkbox-info sublayer-checkbox inline-checkbox">
+                                        <input id="{{layer.$$hashKey}}_compare_sublayer_{{sublayer}}_visible_checkbox"
+                                               type="checkbox"
+                                               style="cursor:pointer; position: absolute"
+                                               title="Definit si la couche est visible"
+                                               ng-checked="ctrl.isSublayerActive(layer.olLayer, sublayer)"
+                                               ng-disabled="layer.olLayer.values.visible !== true"
+                                               ng-click="ctrl.toggleSubLayer(layer.olLayer, sublayer, '#' + layer.$$hashKey + '_sublayer_' + sublayer + '_visible_checkbox')">
+                                        <label for="{{layer.$$hashKey}}_compare_sublayer_{{sublayer}}_visible_checkbox" style="cursor:pointer" title="Definit si la couche est visible">{{sublayer}}</label>
+                                    </div>
+                                </div>
+                            </li>
+                        </div>
+                    </div>
+                </div>
+            </ul>
+        </div>
+    </ul>
 </div>
 
 <!--Modale pour le filtrage-->
diff --git a/module/template/layers/maplegend.html b/module/template/layers/maplegend.html
index a82570aa249be47f2f17a50eb48f4238af16d693..4c34eb4904c8941687b5019d7b7c9d20076a7b57 100755
--- a/module/template/layers/maplegend.html
+++ b/module/template/layers/maplegend.html
@@ -1,9 +1,9 @@
 <div class="maplegendtool">
     <div ng-if="!$root.is_mobile" id="maplegendcontainer-button">
-        <div class="list-group-item active pointer maplegend-button-content" 
-             title="Légende de la carte" 
+        <div class="list-group-item active pointer maplegend-button-content"
+             title="Légende de la carte"
              collapse="{{ctrl.legend_collapsed === true ? 'out' : 'in'}}"
-             data-target="#maplegendcontainer" 
+             data-target="#maplegendcontainer"
              onclick="oVmap.getMapManager().collapseElement(this)">
             <span class="icon-info list-group-icon"></span>
             <span>Légende</span>
@@ -12,7 +12,15 @@
         </div>
     </div>
     <div id="maplegendcontainer" class="layers-tool legend" collapse="{{ctrl.legend_collapsed === true ? 'out' : 'in'}}">
-        <div id="maplegend" class="tree legend">
+        <ul class="nav nav-tabs layerstree-nav" ng-show="$root.compare_enabled">
+            <li ng-class="{'active' : activeMap == 1}">
+                <a href="#" ng-click="activeMap=1;ctrl.resize()">Carte 1</a>
+            </li>
+            <li ng-class="{'active' : activeMap == 2}">
+                <a href="#" ng-click="activeMap=2;ctrl.resize()">Carte 2</a>
+            </li>
+        </ul>
+        <div id="maplegend" class="tree legend" ng-show="activeMap == 1 || !$root.compare_enabled">
             <div ng-repeat="(sLayerName, layer) in ctrl.oUrls" class="layer-legend"
                  ng-show="ctrl.areLegendsLoaded(layer)">
                 <div id="legend_father{{$index}}" data-toggle="collapse" data-target="#legend_element_{{$index}}">
@@ -23,7 +31,26 @@
                 <div id="legend_element_{{$index}}" class="collapse in">
                     <ul class="list-group-item auto-height">
                         <div ng-repeat="node in layer"
-                             ng-show="node.legendBlobURL">                            
+                             ng-show="node.legendBlobURL">
+                            <img ng-src="{{node.legendBlobURL}}" class="legend-img" legend-image-node>
+                        </div>
+                    </ul>
+                </div>
+            </div>
+        </div>
+
+        <div id="compare_maplegend" class="tree legend" ng-show="activeMap == 2 && $root.compare_enabled">
+            <div ng-repeat="(sLayerName, layer) in ctrl.oCompareUrls" class="layer-legend"
+                 ng-show="ctrl.areLegendsLoaded(layer)">
+                <div id="compare_legend_father{{$index}}" data-toggle="collapse" data-target="#compere_legend_element_{{$index}}">
+                    <div style="display: inline-block; width:98%">
+                        <div class="legend_father_name" title="{{sLayerName}}">{{sLayerName}}</div>
+                    </div>
+                </div>
+                <div id="compare_legend_element_{{$index}}" class="collapse in">
+                    <ul class="list-group-item auto-height">
+                        <div ng-repeat="node in layer"
+                             ng-show="node.legendBlobURL">
                             <img ng-src="{{node.legendBlobURL}}" class="legend-img" legend-image-node>
                         </div>
                     </ul>
@@ -31,4 +58,4 @@
             </div>
         </div>
     </div>
-</div>
\ No newline at end of file
+</div>
diff --git a/module/template/layers/mapmodal/maplistlitle.html b/module/template/layers/mapmodal/maplistlitle.html
index 2089b99cf5622ae5d17850d76b84c3b77b3102f1..e2ff1e2f60b3b953a96db0e5bdbc0d59d69f50ab 100644
--- a/module/template/layers/mapmodal/maplistlitle.html
+++ b/module/template/layers/mapmodal/maplistlitle.html
@@ -32,6 +32,7 @@
                 <div ng-repeat="map in oTheme.maps| orderBy: 'name'">
                     <div ng-if="($index + 1) % 4 === 0" class="row">
                         <div url="{{map.url}}"
+                             ng-if="!compare"
                              title="{{map.description}}"
                              class="col-md-3 margin-10 pointer opacity-hover underline-hover maplist-map"
                              style="text-align: center; font-size: 12px;"
@@ -43,8 +44,21 @@
                                 <span>{{map.name}}</span>
                             </div>
                         </div>
+                        <div url="{{map.url}}"
+                             ng-if="compare"
+                             title="{{map.description}}"
+                             class="col-md-6 margin-10 pointer opacity-hover underline-hover maplist-map"
+                             style="text-align: center; font-size: 12px;"
+                             onclick="oVmap.getMapManager().loadCompareMap(this)"
+                             data-dismiss="modal">
+
+                            <div onclick="$('#maplistlitle-container').removeClass('open')" ng-class="{'border-black': map.compare === true}" style="overflow:hidden" ng-attr-title="{{map.description}}">
+                                <div class="img-map" style="background-image: url('{{map.thumbnail}}')"></div>
+                                <span>{{map.name}}</span>
+                            </div>
+                        </div>
                     </div>
-                    <div ng-if="($index + 1) % 4 !== 0"
+                    <div ng-if="($index + 1) % 4 !== 0 && !compare"
                          url="{{map.url}}"
                          title="{{map.description}}"
                          class="col-md-3 margin-10 pointer opacity-hover underline-hover maplist-map"
@@ -57,6 +71,19 @@
                             <span>{{map.name}}</span>
                         </div>
                     </div>
+                    <div ng-if="($index + 1) % 4 !== 0 && compare"
+                         url="{{map.url}}"
+                         title="{{map.description}}"
+                         class="col-md-6 margin-10 pointer opacity-hover underline-hover maplist-map"
+                         style="text-align: center; font-size: 12px;"
+                         onclick="oVmap.getMapManager().loadCompareMap(this)"
+                         data-dismiss="modal">
+
+                        <div onclick="$('#maplistlitle-container').removeClass('open')" ng-class="{'border-black': map.compare === true}" style="overflow:hidden" ng-attr-title="{{map.description}}">
+                            <div class="img-map" style="background-image: url('{{map.thumbnail}}')"></div>
+                            <span>{{map.name}}</span>
+                        </div>
+                    </div>
                 </div>
             </div>
         </div>
diff --git a/module/template/tools/basicselect.html b/module/template/tools/basicselect.html
index 1f829c663fd7e9b9eded8c88c38dc379a45fca29..d0ecff8d419dbc2a90adbf8772de3f0f568a4e27 100644
--- a/module/template/tools/basicselect.html
+++ b/module/template/tools/basicselect.html
@@ -1,6 +1,6 @@
 <div id="vmap-basicselect-tool"></div>
 
-<li role="presentation" style="position: inherit" class="basic-tools-dropdown">
+<li role="presentation" style="position: inherit" class="basic-tools-dropdown"  ng-class="{'hidden': !$root.isVmapToolActive('Select')}">
     <a class="basic-tools-element pointer"
        id="basic-tools-dropdown-basicselect-btn"
        ng-show="ctrl.aBusinessObjectsList.length > 0 || (ctrl.properties.selection.enable_getfeatureinfo === true && ctrl.aQueryableLayers.length > 0)"
diff --git a/module/template/tools/basictools.html b/module/template/tools/basictools.html
index e85c74762d60d92d19a6b560d5811b7a178fad98..8d42420c8cb939607f43cac769066030a2b7c227 100644
--- a/module/template/tools/basictools.html
+++ b/module/template/tools/basictools.html
@@ -5,12 +5,12 @@
                 <!-- Outils de localisation -->
                 <div app-location app-lang="ctrl.lang" app-map="ctrl.map"></div>
                 <!-- Outil d'export d'url -->
-                <div>
+                <div ng-class="{'hidden': !$root.isVmapToolActive('URLGenerator')}">
                     <li role="presentation" style="position: inherit" class="basic-tools-dropdown">
                         <a class="basic-tools-element pointer"
-                           title="Générateur d'URL"
+                           title="Lien vers la carte en cours"
                            onclick="oVmap.getToolsManager().getBasicTools().toggleTool(this)">
-                            <span class="icon-at" aria-hidden="true"></span>
+                            <span class="icon-link_url" aria-hidden="true"></span>
                         </a>
                         <div app-url-exporter app-lang="ctrl.lang" app-map="ctrl.map"
                              id="basic-tools-dropdown-urlexporter"
@@ -19,8 +19,24 @@
                         </div>
                     </li>
                 </div>
+                <!-- Outil de comparaison -->
+                <div ng-class="{'hidden': !$root.isVmapToolActive('MapCompare')}">
+                    <li role="presentation" style="position: inherit" class="basic-tools-dropdown">
+                        <a class="basic-tools-element pointer"
+                           id="map-compare-tool-btn"
+                           title="Comparaison de carte"
+                           onclick="oVmap.getToolsManager().getBasicTools().toggleTool(this)"
+                           ng-class="{'active2':$root.compare_enabled}">
+                            <span class="icon-mirror" aria-hidden="true"></span>
+                        </a>
+                        <div app-compare-mode app-lang="ctrl.lang" app-map="ctrl.map"
+                             id="basic-tools-dropdown-comapremode"
+                             class="dropdown-menu basic-tools-dropdown-element no-padding">
+                        </div>
+                    </li>
+                </div>
                 <!-- Login de l'utilisateur -->
-                <div class="right">
+                <div class="right" ng-class="{'hidden': !$root.isVmapToolActive('User')}">
                     <li role="presentation" style="position: inherit" class="basic-tools-dropdown">
                         <a class="basic-tools-element pointer"
                            title="Utilisateur"
@@ -34,7 +50,7 @@
                     </li>
                 </div>
                 <!-- Contrôles -->
-                <div class="right">
+                <div class="right" ng-class="{'hidden': !$root.isVmapToolActive('Config')}">
                     <li role="presentation" style="position: inherit" class="basic-tools-dropdown">
                         <a class="basic-tools-element pointer"
                            title="Outils de contrôle"
@@ -48,7 +64,7 @@
                     </li>
                 </div>
                 <!-- Impression -->
-                <div class="right">
+                <div class="right" ng-class="{'hidden': !$root.isVmapToolActive('Print')}">
                     <li role="presentation" style="position: inherit" class="basic-tools-dropdown">
                         <a id="print-select-btn"
                            class="basic-tools-element pointer"
@@ -58,21 +74,21 @@
                         </a>
                         <div app-print app-lang="ctrl.lang" app-map="ctrl.map" app-action="ctrl.currentAction"
                              id="basic-tools-dropdown-print-content"
-                             class="dropdown-menu basic-tools-dropdown-element basic-tools-dropdown-print-content">		
+                             class="dropdown-menu basic-tools-dropdown-element basic-tools-dropdown-print-content">
                         </div>
                     </li>
                 </div>
                 <!-- Insertion -->
-                <div class="right">
+                <div class="right" ng-class="{'hidden': !$root.isVmapToolActive('Insert')}">
                     <li role="presentation" style="position: inherit" class="basic-tools-dropdown">
                         <a class="basic-tools-element pointer"
-                           id="basic-tools-dropdown-insert-btn" 
+                           id="basic-tools-dropdown-insert-btn"
                            title="Insertion"
                            onclick="oVmap.getToolsManager().getBasicTools().toggleTool(this)">
                             <span class="icon-add-feature" aria-hidden="true"></span>
                         </a>
                         <div app-insert app-lang="ctrl.lang" app-map="ctrl.map" app-action="ctrl.currentAction"
-                             id="basic-tools-dropdown-insert-content" 
+                             id="basic-tools-dropdown-insert-content"
                              class="dropdown-menu basic-tools-dropdown-element basic-tools-dropdown-select-content">
                         </div>
                     </li>
@@ -80,7 +96,7 @@
                 <!--Outils de sélection-->
                 <div app-select app-lang="ctrl.lang" app-map="ctrl.map" app-action="ctrl.currentAction" class="right basic-tools-nav"></div>
                 <!-- Mesure -->
-                <div class="right">
+                <div class="right" ng-class="{'hidden': !$root.isVmapToolActive('Mesure')}">
                     <li style="position: inherit" class="basic-tools-dropdown">
                         <a 	class="basic-tools-element pointer"
                             title="Outils de mesure"
@@ -96,4 +112,4 @@
             </ul>
         </div>
     </div>
-</div>
\ No newline at end of file
+</div>
diff --git a/module/template/tools/comparemapmanager.html b/module/template/tools/comparemapmanager.html
new file mode 100644
index 0000000000000000000000000000000000000000..5400040928382b75fee2971115575455e96f07c6
--- /dev/null
+++ b/module/template/tools/comparemapmanager.html
@@ -0,0 +1,23 @@
+<!--Mode compare-->
+<div class="row margin-sides-0 no-padding">
+    <div class="margin-sides-20">
+        <div>
+            <div class="checkbox checkbox-info checkbox-inline checkbox_margin">
+                <input id="useCompareModeCheckbox"
+                        type="checkbox"
+                        style="cursor:pointer;"
+                        title=">Activer / Désactiver le mode comparaison"
+                        ng-model="ctrl.useCompareMode">
+                <label for="useCompareModeCheckbox"
+                       style="cursor:pointer"
+                       title="Activer / Désactiver le mode comparaison">
+                    Activer / Désactiver le mode comparaison
+                </label>
+            </div>
+        </div>
+    </div>
+    <div ng-show="ctrl.useCompareMode" class="col-md-12"><hr></div>
+    <div ng-show="ctrl.useCompareMode" class="col-md-12 no-padding">
+        <app-maplistlitle app-lang="ctrl.lang" app-maplistlitle-map="ctrl.map" data-compare="true"></app-maplistlitle>
+    </div>
+</div>
diff --git a/module/template/tools/insert.html b/module/template/tools/insert.html
index 8011c69fe13be35cb5aa0684448a4108da9abb2b..b18ed5994bdc1bfbf72020ce20aae6262f22d3be 100644
--- a/module/template/tools/insert.html
+++ b/module/template/tools/insert.html
@@ -242,32 +242,69 @@
                 <h4 class="modal-title" data-translate="TITLE_SNAPPING_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h4>
             </div>
             <div class="modal-body modal-body-big-with-footer-3 font-12">
-                <div class="col-sm-6">
-                    <h5 data-translate="FORM_SNAPPING_DEFAUT_TYPE_ACC_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h5>
-                    <select class="form-control"
-                            ng-model="ctrl.tmpSnapOptions.mode">
-                        <option value="segment_edge_node" data-translate="FORM_SNAPPING_METHOD_SEN_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></option>
-                        <option value="edge_node" data-translate="FORM_SNAPPING_METHOD_EN_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></option>
-                        <option value="node" data-translate="FORM_SNAPPING_METHOD_N_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></option>
-                    </select>
-                </div>
-                <div class="col-sm-6">
-                    <h5 data-translate="FORM_SNAPPING_DEFAUT_TOLERANCE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h5>
-                    <input type="number" class="form-control" ng-model="ctrl.tmpSnapOptions.tolerance">
-                </div>
-                <div class="col-sm-6">
-                    <h5 data-translate="FORM_SNAPPING_DEFAUT_LIMIT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h5>
-                    <input type="number" class="form-control" ng-model="ctrl.tmpSnapOptions.limit">
+                <div class="row">
+                    <div class="col-sm-6">
+                        <h5 data-translate="FORM_SNAPPING_TYPE_ACC_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h5>
+                        <select class="form-control"
+                                ng-model="ctrl.tmpSnapOptions.mode">
+                            <option value="segment_edge_node" data-translate="FORM_SNAPPING_METHOD_SEN_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></option>
+                            <option value="edge_node" data-translate="FORM_SNAPPING_METHOD_EN_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></option>
+                            <option value="node" data-translate="FORM_SNAPPING_METHOD_N_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></option>
+                        </select>
+                    </div>
+                    <div class="col-sm-6">
+                        <h5 data-translate="FORM_SNAPPING_TOLERANCE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h5>
+                        <input type="number" class="form-control" ng-model="ctrl.tmpSnapOptions.tolerance">
+                    </div>
                 </div>
-                <div class="col-sm-6">
-                    <h5 data-translate="FORM_SNAPPING_DEFAUT_VISIBILITY_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h5>
-                    <div class="radio radio-inline">
-                        <input type="radio" name="vmap_insert_snap_visible" id="vmap_insert_snap_visible_1" ng-model="ctrl.tmpSnapOptions.visible" ng-value="true">
-                        <label for="vmap_insert_snap_visible_1">Oui</label>
+                <div class="row">
+                    <div class="col-sm-6">
+                        <h5 data-translate="FORM_SNAPPING_LIMIT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h5>
+                        <input type="number" class="form-control" ng-model="ctrl.tmpSnapOptions.limit">
                     </div>
-                    <div class="radio radio-inline">
-                        <input type="radio" name="vmap_insert_snap_visible" id="vmap_insert_snap_visible_2" ng-model="ctrl.tmpSnapOptions.visible" ng-value="false">
-                        <label for="vmap_insert_snap_visible_2">Non</label>
+                    <div class="col-sm-6">
+                        <h5 data-translate="FORM_SNAPPING_VISIBILITY_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h5>
+                        <div class="radio radio-inline">
+                            <input type="radio" name="vmap_insert_snap_visible" id="vmap_insert_snap_visible_1" ng-model="ctrl.tmpSnapOptions.visible" ng-value="true">
+                            <label for="vmap_insert_snap_visible_1">Oui</label>
+                        </div>
+                        <div class="radio radio-inline">
+                            <input type="radio" name="vmap_insert_snap_visible" id="vmap_insert_snap_visible_2" ng-model="ctrl.tmpSnapOptions.visible" ng-value="false">
+                            <label for="vmap_insert_snap_visible_2">Non</label>
+                        </div>
+                    </div>
+                </div>
+                <div class="row">
+                    <div class="col-sm-6" ng-show="aAvoidSuperpositionsBOs.length > 0">
+                        <div class="row">
+                            <div class="col-sm-12 text-right">
+                                <h5 data-translate="FORM_SNAPPING_AVOID_SUPERPOSITIONS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h5>
+                            </div>
+                        </div>
+                        <div class="row"
+                                ng-repeat="bo in aAvoidSuperpositionsBOs">
+                            <div class="col-sm-5 text-right">
+                                <label>{{bo.bo_title}}</label>
+                            </div>
+                            <div class="col-sm-7 text-right">
+                                <div class="radio radio-inline">
+                                    <input type="radio"
+                                            name="vmap_insert_snap_avoid_superpositions_{{$index}}"
+                                            id="vmap_insert_snap_avoid_superpositions_1_{{$index}}"
+                                            ng-model="ctrl.tmpSnapOptions.avoidSuperpositions[bo.bo_id]"
+                                            ng-value="true">
+                                    <label for="vmap_insert_snap_avoid_superpositions_1_{{$index}}">Oui</label>
+                                </div>
+                                <div class="radio radio-inline">
+                                    <input  type="radio"
+                                            name="vmap_insert_snap_avoid_superpositions_{{$index}}"
+                                            id="vmap_insert_snap_avoid_superpositions_2_{{$index}}"
+                                            ng-model="ctrl.tmpSnapOptions.avoidSuperpositions[bo.bo_id]"
+                                            ng-value="false">
+                                    <label for="vmap_insert_snap_avoid_superpositions_2_{{$index}}">Non</label>
+                                </div>
+                            </div>
+                        </div>
                     </div>
                 </div>
             </div>
diff --git a/module/template/tools/location.html b/module/template/tools/location.html
index a9f3e9bca3288fb5fc5a32a7d83eb4dec5ce8667..62e46ed34e6b7d9853846d9d0845101216ac75a9 100644
--- a/module/template/tools/location.html
+++ b/module/template/tools/location.html
@@ -1,16 +1,16 @@
 <!--location search-->
-<li id="location-search-tool" role="presentation">
+<li id="location-search-tool" role="presentation" ng-class="{'hidden': !$root.isVmapToolActive('LocationSearch')}">
     <form ng-submit="ctrl.searchLocation()" id="location-search-form" class="margin-sides-5 from-control">
         <!--Recherche-->
         <input id="location-search-input"
-               type="text" 
+               type="text"
                placeholder="Localiser.."
                ng-model="ctrl.locationSearch"
                ng-click="ctrl.searchLocation()">
         <!--Sélecteur-->
         <select id="location-search-api-select"
                 ng-model="ctrl.sSelectedLocationService"
-                ng-change="ctrl.searchLocation()">            
+                ng-change="ctrl.searchLocation()">
             <!--Géocodeurs-->
             <option ng-repeat="(key, value) in ctrl.locationServices"
                     value="{{key}}">{{value.title}}</option>
@@ -26,7 +26,7 @@
         <!--Bandeau du haut-->
         <div style="margin: 10px">
             <label>Résultats de la recherche: </label>
-            <span class="glyphicon glyphicon-remove right pointer margin-sides-10" 
+            <span class="glyphicon glyphicon-remove right pointer margin-sides-10"
                   ng-click="ctrl.removeLocation()"></span>
         </div>
 
@@ -65,12 +65,12 @@
 
         <!-- Géocodeur -->
         <div ng-if="locationServiceType === 'geocoder'" class="location-search-dropdown-content">
-            <div class="location-search-dropdown-result" 
+            <div class="location-search-dropdown-result"
                  ng-repeat="node in ctrl.locationResults">
                 <div class="pointer opacity-hover"
                      ng-click="ctrl.locatePlace(node)">
                     <span>{{node.title}}</span>
-                </div>					
+                </div>
 
                 <div class="location-search-dropdown-result-buttons pointer collapsed" data-toggle="collapse" href="#location-search-dropdown-result-infos-{{this['$index']}}">
                     <a>Détails</a>
@@ -78,7 +78,7 @@
                 </div>
 
                 <div class="collapse" id="location-search-dropdown-result-infos-{{this['$index']}}">
-                    <div style="padding-bottom: 10px" ng-if="node.summary">	
+                    <div style="padding-bottom: 10px" ng-if="node.summary">
                         <ul>
                             <li ng-repeat="oSummaryElement in node.summary">{{oSummaryElement.label}}: {{oSummaryElement.value}}</li>
                         </ul>
@@ -91,13 +91,13 @@
         <div style="text-align: center; margin: 10px;">
             <button type="button" class="btn btn-sm btn-primary" ng-click="ctrl.searchLocation(ctrl.locationSearch, 12)">
                 Plus de résultats
-            </button>			
+            </button>
         </div>
     </div>
 </li>
 
 <!--Go home-->
-<li role="presentation">
+<li role="presentation" ng-class="{'hidden': !$root.isVmapToolActive('LocationHome')}">
     <a id="original-position-tool"
        class="basic-tools-element pointer" title="Centrer la carte sur l’emprise par défaut"
        ng-click="ctrl.goHome()">
@@ -106,7 +106,7 @@
 </li>
 
 <!--Refresh map-->
-<li role="presentation">
+<li role="presentation" ng-class="{'hidden': !$root.isVmapToolActive('LocationRefresh')}">
     <a id="original-position-tool"
        class="basic-tools-element pointer" title="Rafraichir les couches de la carte"
        ng-click="ctrl.refreshMap()">
@@ -115,7 +115,7 @@
 </li>
 
 <!--Max extent-->
-<li role="presentation">
+<li role="presentation" ng-class="{'hidden': !$root.isVmapToolActive('LocationMaxExtent')}">
     <a class="basic-tools-element pointer" title="Centrer la carte à l’étendue maximale"
        ng-click="ctrl.maxExtent()">
         <span class="icon-language" aria-hidden="true"></span>
@@ -123,7 +123,7 @@
 </li>
 
 <!--Geolocate me-->
-<li role="presentation">
+<li role="presentation" ng-class="{'hidden': !$root.isVmapToolActive('LocationMyPosition')}">
     <a class="basic-tools-element pointer" title="Centrer la carte sur ma position"
        ng-click="ctrl.geolocateMe()">
         <span class="glyphicon glyphicon-map-marker" aria-hidden="true"></span>
@@ -131,7 +131,7 @@
 </li>
 
 <!--Go to-->
-<li role="presentation" style="position: inherit" class="basic-tools-dropdown">
+<li role="presentation" style="position: inherit" class="basic-tools-dropdown" ng-class="{'hidden': !$root.isVmapToolActive('LocationXY')}">
 
     <a class="basic-tools-element pointer"
        title="Centrer la carte sur une position donnée"
@@ -148,7 +148,7 @@
                 <div class="input-group-sm">
                     <input type="number" class="form-control" placeholder="Y" ng-model="goToY">
                 </div>
-            </div>			
+            </div>
             <div class="col-md-5">
                 <b>Projection:</b>
                 <select class="form-control" ng-model="goToProj">
@@ -169,7 +169,7 @@
 </li>
 
 <!--Previous history-->
-<li role="presentation">
+<li role="presentation" ng-class="{'hidden': !$root.isVmapToolActive('LocationPrecNext')}">
     <a class="basic-tools-element pointer" title="Aller à l'étendue précédente"
        ng-click="ctrl.previousHistoryExtent()" ng-class="{'inactive' : ctrl.iHistoryOffset >= ctrl.aLocationHistory.length - 1}">
         <span class="glyphicon glyphicon-arrow-left" aria-hidden="true"></span>
@@ -177,7 +177,7 @@
 </li>
 
 <!--Next history-->
-<li role="presentation">
+<li role="presentation" ng-class="{'hidden': !$root.isVmapToolActive('LocationPrecNext')}">
     <a class="basic-tools-element pointer" title="Aller à l'étendue suivante"
        ng-click="ctrl.nextHistoryExtent()" ng-class="{'inactive' : ctrl.iHistoryOffset === 0}">
         <span class="glyphicon glyphicon-arrow-right" aria-hidden="true"></span>
diff --git a/module/template/tools/print.html b/module/template/tools/print.html
index 0a1fd62b4dcf92147ce7b543f37d661637c5f70c..330a8b9c2733511e33358d8d02c6e41a6463122a 100644
--- a/module/template/tools/print.html
+++ b/module/template/tools/print.html
@@ -53,10 +53,18 @@
         </select>
 
         <button type="button"
+                title="Modification de la zone d'impression sur la carte"
                 class="btn btn-info btn-sm"
                 style="margin-top: 10px"
-                ng-class="{'active': ctrl.currentAction === 'print-modifyPrintZone'}"
+                ng-class="{'active': managePrintZoneInProgress}"
                 ng-click="ctrl.managePrintZone()"><span class="glyphicon glyphicon-move"></span></button>
+       <button type="button"
+               title="Modification de la zone d'impression sur la carte de comparaison"
+               ng-show="$root.compare_enabled"
+               class="btn btn-info btn-sm"
+               style="margin-top: 10px"
+               ng-class="{'active': manageComparePrintZoneInProgress}"
+               ng-click="ctrl.manageComparePrintZone()"><span class="glyphicon glyphicon-move"></span></button>
 
         <button type="submit"
                 class="btn btn-info btn-sm"
diff --git a/module/template/tools/select.html b/module/template/tools/select.html
index 420c5b37e81360aa9fd3fcd128e1d46bb3f5e001..f801d83e906904ae6028f8e76bd8041af1c7d928 100644
--- a/module/template/tools/select.html
+++ b/module/template/tools/select.html
@@ -2,7 +2,7 @@
 <div id="vmap-select-tool"></div>
 
 <!-- Selection Avancée -->
-<div class="right" ng-if="!$root.is_mobile">
+<div class="right" ng-if="!$root.is_mobile" ng-class="{'hidden': !$root.isVmapToolActive('AdvancedSelect')}">
     <li role="presentation" style="position: inherit" class="basic-tools-dropdown">
         <a class="basic-tools-element pointer"
            id="basic-tools-dropdown-select-btn"
@@ -290,32 +290,69 @@
                 <h4 class="modal-title" data-translate="TITLE_SNAPPING_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h4>
             </div>
             <div class="modal-body modal-body-big-with-footer-3 font-12">
-                <div class="col-sm-6">
-                    <h5 data-translate="FORM_SNAPPING_DEFAUT_TYPE_ACC_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h5>
-                    <select class="form-control"
-                            ng-model="ctrl.tmpSnapOptions.mode">
-                        <option value="segment_edge_node" data-translate="FORM_SNAPPING_METHOD_SEN_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></option>
-                        <option value="edge_node" data-translate="FORM_SNAPPING_METHOD_EN_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></option>
-                        <option value="node" data-translate="FORM_SNAPPING_METHOD_N_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></option>
-                    </select>
-                </div>
-                <div class="col-sm-6">
-                    <h5 data-translate="FORM_SNAPPING_DEFAUT_TOLERANCE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h5>
-                    <input type="number" class="form-control" ng-model="ctrl.tmpSnapOptions.tolerance">
-                </div>
-                <div class="col-sm-6">
-                    <h5 data-translate="FORM_SNAPPING_DEFAUT_LIMIT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h5>
-                    <input type="number" class="form-control" ng-model="ctrl.tmpSnapOptions.limit">
+                <div class="row">
+                    <div class="col-sm-6">
+                        <h5 data-translate="FORM_SNAPPING_TYPE_ACC_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h5>
+                        <select class="form-control"
+                                ng-model="ctrl.tmpSnapOptions.mode">
+                            <option value="segment_edge_node" data-translate="FORM_SNAPPING_METHOD_SEN_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></option>
+                            <option value="edge_node" data-translate="FORM_SNAPPING_METHOD_EN_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></option>
+                            <option value="node" data-translate="FORM_SNAPPING_METHOD_N_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></option>
+                        </select>
+                    </div>
+                    <div class="col-sm-6">
+                        <h5 data-translate="FORM_SNAPPING_TOLERANCE_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h5>
+                        <input type="number" class="form-control" ng-model="ctrl.tmpSnapOptions.tolerance">
+                    </div>
                 </div>
-                <div class="col-sm-6">
-                    <h5 data-translate="FORM_SNAPPING_DEFAUT_VISIBILITY_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h5>
-                    <div class="radio radio-inline">
-                        <input type="radio" name="vmap_select_snap_visible" id="vmap_select_snap_visible_1" ng-model="ctrl.tmpSnapOptions.visible" ng-value="true">
-                        <label for="vmap_select_snap_visible_1">Oui</label>
+                <div class="row">
+                    <div class="col-sm-6">
+                        <h5 data-translate="FORM_SNAPPING_LIMIT_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h5>
+                        <input type="number" class="form-control" ng-model="ctrl.tmpSnapOptions.limit">
                     </div>
-                    <div class="radio radio-inline">
-                        <input type="radio" name="vmap_select_snap_visible" id="vmap_select_snap_visible_2" ng-model="ctrl.tmpSnapOptions.visible" ng-value="false">
-                        <label for="vmap_select_snap_visible_2">Non</label>
+                    <div class="col-sm-6">
+                        <h5 data-translate="FORM_SNAPPING_VISIBILITY_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h5>
+                        <div class="radio radio-inline">
+                            <input type="radio" name="vmap_select_snap_visible" id="vmap_select_snap_visible_1" ng-model="ctrl.tmpSnapOptions.visible" ng-value="true">
+                            <label for="vmap_select_snap_visible_1">Oui</label>
+                        </div>
+                        <div class="radio radio-inline">
+                            <input type="radio" name="vmap_select_snap_visible" id="vmap_select_snap_visible_2" ng-model="ctrl.tmpSnapOptions.visible" ng-value="false">
+                            <label for="vmap_select_snap_visible_2">Non</label>
+                        </div>
+                    </div>
+                </div>
+                <div class="row">
+                    <div class="col-sm-6" ng-show="aAvoidSuperpositionsBOs.length > 0">
+                        <div class="row">
+                            <div class="col-sm-12 text-right">
+                                <h5 data-translate="FORM_SNAPPING_AVOID_SUPERPOSITIONS_CONFIGURATION_CONFIGURATION_VMAP_CONFIG"></h5>
+                            </div>
+                        </div>
+                        <div class="row"
+                                ng-repeat="bo in aAvoidSuperpositionsBOs">
+                            <div class="col-sm-5 text-right">
+                                <label>{{bo.bo_title}}</label>
+                            </div>
+                            <div class="col-sm-7 text-right">
+                                <div class="radio radio-inline">
+                                    <input type="radio"
+                                            name="vmap_select_snap_avoid_superpositions_{{$index}}"
+                                            id="vmap_select_snap_avoid_superpositions_1_{{$index}}"
+                                            ng-model="ctrl.tmpSnapOptions.avoidSuperpositions[bo.bo_id]"
+                                            ng-value="true">
+                                    <label for="vmap_select_snap_avoid_superpositions_1_{{$index}}">Oui</label>
+                                </div>
+                                <div class="radio radio-inline">
+                                    <input  type="radio"
+                                            name="vmap_select_snap_avoid_superpositions_{{$index}}"
+                                            id="vmap_select_snap_avoid_superpositions_2_{{$index}}"
+                                            ng-model="ctrl.tmpSnapOptions.avoidSuperpositions[bo.bo_id]"
+                                            ng-value="false">
+                                    <label for="vmap_select_snap_avoid_superpositions_2_{{$index}}">Non</label>
+                                </div>
+                            </div>
+                        </div>
                     </div>
                 </div>
             </div>
diff --git a/module/template/tools/urlexporter.html b/module/template/tools/urlexporter.html
index 8219c05115135bb301def37dcd88452878d5a06b..a1602e307b52d657096cda53b9c1ee618df0a754 100644
--- a/module/template/tools/urlexporter.html
+++ b/module/template/tools/urlexporter.html
@@ -1,11 +1,30 @@
 <!--UrlExporter-->
 <div class="row margin-sides-0 margin-10">
-    <div class="col-md-3" ng-show="ctrl.properties.allow_public_connection">
-        <input type="checkbox" ng-model="ctrl.usePublicToken" id="publicAccountCheckbox">
-        <label for="publicAccountCheckbox" class="control-label">Public</label>
-    </div>          
-    <div class="" ng-class="{'col-md-9' : ctrl.properties.allow_public_connection, 'col-md-12': !ctrl.properties.allow_public_connection}">
-        <label for="urlExporterField" class="control-label">URL</label>
-        <input type="text" class="form-control" ng-model="ctrl.urlToExport" id="urlExporterField">
+    <div class="col-md-12">
+        <div class="left">
+            <label for="privateExportUrlField" class="control-label">Lien vers la carte en cours</label>
+        </div>
     </div>
-</div>
\ No newline at end of file
+    <div class="col-md-12">
+        <div class="input-group">
+            <span class="input-group-btn">
+                <button type="button" class="btn btn-default" disabled><span class="fa fa-lock"></span></button>
+            </span>
+            <input type="text" class="form-control" ng-model="ctrl.privateExportUrl" id="privateExportUrlField">
+            <span class="input-group-btn">
+                <button type="button" class="btn btn-default" ng-click="ctrl.copyUrl()"><span class="icon-copy"></span></button>
+            </span>
+        </div>
+    </div>
+    <div class="col-md-12 margin-10" ng-if="ctrl.properties.allow_public_connection">
+        <div class="input-group">
+            <span class="input-group-btn">
+                <button type="button" class="btn btn-default" disabled><span class="fa fa-unlock"></span></button>
+            </span>
+            <input type="text" class="form-control" ng-model="ctrl.publicExportUrl" id="publicExportUrlField">
+            <span class="input-group-btn">
+                <button type="button" class="btn btn-default" ng-click="ctrl.copyUrl(true)"><span class="icon-copy"></span></button>
+            </span>
+        </div>
+    </div>
+</div>
diff --git a/module/template/vmap.html b/module/template/vmap.html
index 358cdd8b6ca49e2c506b886d9a79c2683830b5cb..3dfe8e972c9041da49bdcca98ac684467dbcd2c4 100755
--- a/module/template/vmap.html
+++ b/module/template/vmap.html
@@ -4,7 +4,7 @@
     <div ng-if="!$root.is_mobile" id="left-sidebar" ng-class="vmapCtrl.left_open ? 'open' : ''">
         <div id="maplistlitle-container" class="dropdown">
             <!--voir dans maplistlitle.js pour l'evenement de fermeture de la dropdown-->
-            <button id="maplistlitle-button" class="btn btn-success dropdown-toggle btn-map-manager" 
+            <button id="maplistlitle-button" class="btn btn-success dropdown-toggle btn-map-manager"
                     type="button"
                     onclick="$('#maplistlitle-container').toggleClass('open')">
                 <span class="icon-map left" style="font-size: 30px"></span>
@@ -13,19 +13,19 @@
                     <span class="caret"></span>
                 </span>
             </button>
-            
-            
+
+
             <div id="dropdownMenuMaps" class="dropdown-menu map-list-litle-panel">
 
                 <app-maplistlitle app-lang="ctrl.lang" app-maplistlitle-map="ctrl.map"></app-maplistlitle>
 
-                <div id="map-manager-button-container" style="text-align: center">
-                    <button id="map-manager-button" 
-                            type="button" 
+                <div id="map-manager-button-container" style="text-align: center" ng-class="{'hidden': !$root.isVmapToolActive('MapManager')}">
+                    <button id="map-manager-button"
+                            type="button"
                             class="btn btn-success btn-sm btn-modal margin-10"
                             onclick="oVmap.simuleClick('btn-reload-myMap'); $('#mapModalManager').modal('show'); $('#dropdownMenuMaps').dropdown('toggle')">
                         GESTION DES CARTES
-                    </button> 
+                    </button>
                 </div>
             </div>
         </div>
@@ -33,7 +33,7 @@
         <div app-layertree app-map="vmapCtrl.map" app-proj="vmapCtrl.proj" app-lang="vmapCtrl.lang" id="app-layertree"></div>
         <div app-layersorder app-map="vmapCtrl.map" app-proj="vmapCtrl.proj" app-lang="vmapCtrl.lang" id="app-layersorder"></div>
         <div app-maplegend app-map="vmapCtrl.map" app-proj="vmapCtrl.proj" app-lang="vmapCtrl.lang" id="app-maplegend"></div>
-        <div id="LayersDiv"></div> 
+        <div id="LayersDiv"></div>
 
         <!-- Map Modal -->
         <div class="modal fade" id="mapModalManager" role="dialog">
@@ -48,12 +48,19 @@
     <div ng-if="!$root.is_mobile" id="opener-sidebar" ng-click="vmapCtrl.left_open = !vmapCtrl.left_open" onclick="oVmap.resizeLayerTools(false); oVmap.getToolsManager().getBasicTools().toggleOutTools();">
         <div class="layer-tools-btn shadow-hover icon-tree" ng-class="vmapCtrl.left_open ? 'open' : ''" data-original-title="Couches et cartes"></div>
     </div>
-    
+
     <!-- Carte -->
-    <div id="map-container" ng-class="ctrl.bottom_open ? 'open' : ''">
+    <div id="map-container"
+         ng-class="{'open' : ctrl.bottom_open,'half' : compare_enabled, 'right-module-bar-present' : bLoadVmapModule, 'left-map-manager-open' : vmapCtrl.left_open, 'right-module-manager-open' : vmapCtrl.right_open}">
         <app-map app-map="vmapCtrl.map" app-action="vmapCtrl.currentAction"></app-map>
     </div>
 
+    <!-- Carte Compare -->
+    <div  ng-show="compare_enabled" id="map-container-compare"
+          ng-class="{'open' : ctrl.bottom_open,'half' : compare_enabled, 'right-module-bar-present' : bLoadVmapModule, 'left-map-manager-open' : vmapCtrl.left_open, 'right-module-manager-open' : vmapCtrl.right_open}">
+        <app-map-compare app-map="vmapCtrl.mapCompare" app-action="vmapCtrl.currentAction" style="display:block; width:100%; height:100%;"></app-map-compare>
+    </div>
+
     <!-- Bandeau de selection -->
     <div id="opener-bottombar" class="list-group-item active">
         <div id="opener-bottombar-1" class="open-selection-info" ng-click="ctrl.bottom_open = !ctrl.bottom_open" onclick="oVmap.minResizeBottomBar()"></div>
@@ -63,7 +70,3 @@
         <div id="info-container" app-infocontainer app-infocontainer-lang="vmapCtrl.lang" app-infos="vmapCtrl.infos"></div>
     </div>
 </div>
-
-
-
-
diff --git a/web_service/conf/properties.inc b/web_service/conf/properties.inc
index f21d672f35ce9422a3c58ad6d0234300c1e02950..14c81c8910fbc063076e47d22ae07118a19d04c9 100755
--- a/web_service/conf/properties.inc
+++ b/web_service/conf/properties.inc
@@ -10,6 +10,8 @@ $properties["vmap"]["layers_collapsed"] = false;
 $properties["vmap"]["layerstree_collapsed"] = false;
 $properties["vmap"]["layersorder_collapsed"] = true;
 $properties["vmap"]["legend_collapsed"] = false;
+$properties['controls']['active_tools'] = 'LocationMaxExtent|User|Print|Insert|AdvancedSelect|Select|Mesure|URLGenerator|MapManager|LocationSearch|LocationHome|LocationRefresh|LocationXY|MapCompare|LocationMyPosition';
+$properties['controls']['public_active_tools'] = 'User|Insert|AdvancedSelect|LocationXY|MapManager|LocationHome|MapCompare|Select|Print|LocationSearch|LocationMyPosition|Mesure';
 $properties['controls']['active_controls'] = 'Attribution|MousePosition|CurrentProjection|MapName|Scale|ScaleLine|OverviewMap|Zoom|ZoomSlider|RefreshSocket';
 $properties["selection"]["limit_popup"] = 1;
 $properties["selection"]["limit_list"] = 50;
diff --git a/web_service/sql/sqlQueries.xml b/web_service/sql/sqlQueries.xml
index cbe6c7bfb1c8f72f64dc354137eeb98e981f4d00..a7a4ff6699e62b6fb67a7b5637015655befbf6d5 100644
--- a/web_service/sql/sqlQueries.xml
+++ b/web_service/sql/sqlQueries.xml
@@ -18,7 +18,7 @@
 				ALTER TABLE s_vmap.seq_common OWNER TO u_vitis;
 				GRANT ALL ON TABLE s_vmap.seq_common TO vmap_admin;
 				GRANT SELECT ON TABLE s_vmap.seq_common TO vmap_user;
-				CREATE TABLE s_vmap.version(   version character varying(10) NOT NULL,    build integer NOT NULL,    date timestamp with time zone NOT NULL,    active boolean,  CONSTRAINT pk_version PRIMARY KEY (version));
+				CREATE TABLE s_vmap.version(   version character varying(100) NOT NULL,    build integer NOT NULL,    date timestamp with time zone NOT NULL,    active boolean,  CONSTRAINT pk_version PRIMARY KEY (version));
 				ALTER TABLE s_vmap.version  OWNER TO u_vitis;
 				GRANT ALL ON TABLE s_vmap.version TO vmap_admin;
 				GRANT SELECT ON TABLE s_vmap.version TO vmap_user;
diff --git a/web_service/ws/BusinessObjects.class.inc b/web_service/ws/BusinessObjects.class.inc
index 413f93e43ebbc728cbc4600f84d2cc8d85d05249..fa7ca58d1eaf4d159d82c3498a6c75caf20b1d79 100755
--- a/web_service/ws/BusinessObjects.class.inc
+++ b/web_service/ws/BusinessObjects.class.inc
@@ -697,10 +697,6 @@ class BusinessObjects extends Vmap {
             $sFileContents .= $aFileContents[$i] . ' ';
         }
 
-//        // Travail sur chacune des requêtes du fichier
-//        $aFileContents = explode(';', $sFileContents);
-//        $aFileContents = $this->cleanDataModelFileArray($aFileContents);
-
         return $sFileContents;
     }
 
@@ -1318,7 +1314,7 @@ class BusinessObjects extends Vmap {
                         fclose($pFile);
                     }
 
-                    if ($this->aValues["Js"] != "") {
+                    if (isset($this->aValues["Js"])) {
                         $pFileJS = fopen($sDirPath . '/forms/ressources/' . $sFormName . '.js', 'w+');
                         if (fwrite($pFileJS, $this->aValues["Js"]) == FALSE) {
                             writeToErrorLog('ERROR: ' . $sFormName . '.js save failed');
@@ -1326,7 +1322,7 @@ class BusinessObjects extends Vmap {
                         fclose($pFileJS);
                     }
 
-                    if ($this->aValues["Css"] != "") {
+                    if (isset($this->aValues["Css"])) {
                         $pFileCSS = fopen($sDirPath . '/forms/ressources/' . $sFormName . '.css', 'w+');
                         if (fwrite($pFileCSS, $this->aValues["Css"]) == FALSE) {
                             writeToErrorLog('ERROR: ' . $sFormName . '.css save failed');
@@ -1370,6 +1366,26 @@ class BusinessObjects extends Vmap {
                     @unlink($sDirPath . "/forms/default.json");
                     $aFields = explode("|", $this->aValues['field']);
                     $this->generateBusinessObjectForm($sBusinessObjectId, $sFormName, $aFields, $this->aValues['label']);
+                    break;
+                case "Published_Delete":
+
+                    if (file_exists($sDirPath . "/forms/published.json")) {
+                        @unlink($sDirPath . "/forms/published.json");
+                    }
+                    if (file_exists($sDirPath . "/forms/ressources/published.js")) {
+                        @unlink($sDirPath . "/forms/ressources/published.js");
+                    }
+                    if (file_exists($sDirPath . "/forms/ressources/published.css")) {
+                        @unlink($sDirPath . "/forms/ressources/published.css");
+                    }
+
+                    break;
+                case "Delete_JS":
+
+                    if (file_exists($sDirPath . "/forms/ressources/" . $sFormName . ".js")) {
+                        @unlink($sDirPath . "/forms/ressources/" . $sFormName . ".js");
+                    }
+
                     break;
             }
         }
diff --git a/web_service/ws/Querys.class.inc b/web_service/ws/Querys.class.inc
index a5e4b7deed246263e5d67a6856fb62af7d503fa9..3aed39da27e23ba5bbe1615d9fa027c6127d5f48 100644
--- a/web_service/ws/Querys.class.inc
+++ b/web_service/ws/Querys.class.inc
@@ -515,14 +515,54 @@ class Querys extends Vmap {
      *     )
      *  )
      */
+    /**
+     * @SWG\Get(path="/querys/{business_object_id}/diff_geometry",
+     *   tags={"Querys"},
+     *   summary="Get business object form querys",
+     *   description="Get the difference geom between intersect_geom and the BO using st_difference",
+     *   operationId="GET",
+     *   produces={"application/json", "application/x-vm-json"},
+     *  @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="business_object_id",
+     *     in="path",
+     *     description="business object id",
+     *     required=true,
+     *     type="integer"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="intersect_geom",
+     *     in="query",
+     *     description="EWKT intersect geometry",
+     *     required=true,
+     *     type="integer"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/users")
+     *     )
+     *  )
+     */
 
     /**
      * get Querys
      * @return  Querys
      */
     function GET($bOnlyReturnStatus = FALSE) {
-        if (isset($this->aPath[3]) && ($this->aPath[3] == 'geometry')) {
-            return $this->getBoGeomsFromIntersect($this->aPath[2]);
+        if (($this->aPath[3] == 'geometry') || ($this->aPath[3] == 'diff_geometry')) {
+            if (($this->aPath[3] == 'geometry')) {
+                return $this->getBoGeomsFromIntersect($this->aPath[2]);
+            }
+            if (($this->aPath[3] == 'diff_geometry')) {
+                return $this->getBoDiffGeomFromIntersect($this->aPath[2]);
+            }
         } else if (isset($this->aPath[3])) {
             return $this->queryBusinessObject($this->aPath[3]);
         } else {
@@ -597,7 +637,6 @@ class Querys extends Vmap {
 
         // Valeurs par défaut
         $intersect_column = empty($intersect_column) ? $geom_column : $intersect_column;
-//        $intersect_buffer = empty($intersect_buffer) ? 0.01 : $intersect_buffer;
         $geom_field = empty($geom_field) ? $intersect_column : $geom_field;
         $get_geom = empty($geom_field) || empty($get_geom) ? false : $get_geom;
         $use_intersect = empty($intersect_geom) || empty($intersect_column) ? false : true;
@@ -1205,6 +1244,121 @@ class Querys extends Vmap {
         }
     }
 
+    /**
+     * Get the difference geometry with a business object intersecting intersect_geom
+     */
+    function getBoDiffGeomFromIntersect($sBusinessObjectId) {
+
+        if (!empty($this->oConnection->oError)) {
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $this->oConnection->oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            $aReturn = array('sStatus' => $aXmlRacineAttribute['status'], "sMessage" => $sMessage);
+            return $aReturn['sMessage'];
+        }
+        if (empty($sBusinessObjectId) || empty($this->aValues['intersect_geom'])) {
+            $oError = new VitisError(0, 'Parameters business_object_id, intersect_geom required');
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            $aReturn = array('sStatus' => $aXmlRacineAttribute['status'], "sMessage" => $sMessage);
+            return $aReturn['sMessage'];
+        }
+
+        // Objet BusinessObject correspondant
+        $aPath = array('vmap', 'businessobjects', $sBusinessObjectId);
+        $aValues = array(
+            'token' => $this->aValues['token'],
+            'output' => 'application/json',
+            'sEncoding' => 'UTF-8',
+            'sSourceEncoding' => 'UTF-8',
+            'my_vitis_id' => $sBusinessObjectId,
+            'module' => 'vmap',
+        );
+        $oBusinessObject = new BusinessObject($aPath, $aValues, $this->aProperties, $this->oConnection);
+        $oBusinessObject->GET();
+
+        // Vérifie l'éxistance de l'objet métier
+        if (empty($oBusinessObject->aFields['business_object_id'])) {
+            $oError = new VitisError(0, 'Business object ' . $sBusinessObjectId . ' not founded');
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            $aReturn = array('sStatus' => $aXmlRacineAttribute['status'], "sMessage" => $sMessage);
+            return $aReturn['sMessage'];
+        }
+
+        // Paramètres retenus dans l'url
+        $sSchema = $oBusinessObject->aFields['schema'];
+        $sTable = $oBusinessObject->aFields['table'];
+        $sIntersectGeom = $this->aValues['intersect_geom'];
+        $sInputFilter = $this->aValues['filter'];
+
+        // Paramètres retenus dans le business object
+        $sGeomColumn = $oBusinessObject->aFields['geom_column'];
+        $sDatabase = $oBusinessObject->aFields['database'];
+
+        // Base de données
+        if (!empty($sDatabase) && $sDatabase != $this->oConnection->oBd->base) {
+            $this->oConnection->oBd = new Vm($this->oConnection->oBd->login, $this->oConnection->oBd->mdp, $sDatabase, $this->oConnection->oBd->serveur, $this->oConnection->oBd->port, $this->oConnection->oBd->sgbd, $this->oConnection->oBd->sPageEncoding);
+        }
+
+        // Projection de la colonne intersectée
+        $iColumnProj = $this->oConnection->oBd->getColumnSRID($sSchema, $sTable, $sGeomColumn);
+        if (empty($iColumnProj)) {
+            $iColumnProj = '2154';
+        }
+
+        // Paramètres de la requête
+        $aParams = array();
+        $aParams['sSchema'] = array('value' => $sSchema, 'type' => 'schema_name');
+        $aParams['sTable'] = array('value' => $sTable, 'type' => 'table_name');
+        $aParams['sGeomColumn'] = array('value' => $sGeomColumn, 'type' => 'column_name');
+        $aParams['sIntersectGeom'] = array('value' => $sIntersectGeom, 'type' => 'geometry');
+
+        // Filtre
+        $aFilter = array(
+            'column' => $sGeomColumn,
+            'compare_operator' => 'intersect',
+            'compare_operator_options' => array(
+                'source_proj' => $iColumnProj,
+            ),
+            'value' => $sIntersectGeom
+        );
+
+        if (!empty($sInputFilter)) {
+            $aFilter = $this->addFilterOperator($sInputFilter, $aFilter);
+        }
+
+        $aDecodedFilter = $this->decodeJSONFilter($aFilter, $sSchema, $sTable);
+
+        $sSecuredFilter = $aDecodedFilter['request'];
+        foreach ($aDecodedFilter['params'] as $key => $value) {
+            $aParams[$key] = $value;
+        }
+
+        $sSql = '
+            WITH geoms AS (
+                SELECT (ST_Dump(st_difference(
+            				ST_GeomFromEWKT([sIntersectGeom]),
+            				ST_Union([sGeomColumn])
+            			))).geom AS geom
+                FROM [sSchema].[sTable] WHERE ' . $sSecuredFilter . '
+            )
+            SELECT ST_AsEWKT(geom) as diff_geom
+            FROM geoms
+            ORDER BY ST_Area(geom) DESC
+            LIMIT 1
+        ';
+
+        $oResult = $this->oConnection->oBd->executeWithParams($sSql, $aParams);
+        if ($this->oConnection->oBd->enErreur()) {
+            $aXmlRacineAttribute['status'] = 0;
+            writeToErrorLog($this->oConnection->oBd->getBDMessage());
+            return json_encode(array('errorMessage' => 'Error while calculating diff geom'));
+        } else {
+            $aResult = $this->oConnection->oBd->getResultTableAssoc($oResult);
+            return json_encode($aResult);
+        }
+    }
+
     /**
      * @SWG\Put(path="/querys/{business_object_id}",
      *   tags={"Querys"},