// JavaScript Document /** * Renvoie un élément de la structure HTML, dont l'id est passé en paramètre. * @param id l'id de l'élément recherché * @return element */ function getelement( id ) { // détection du navigateur client var isOpera = ( navigator.userAgent.toLowerCase().indexOf("opera") != -1 );//( typeof(window.opera) != 'undefined' ); var isIE = ( ! isOpera && (navigator.userAgent.indexOf('Internet Explorer') != -1 || navigator.userAgent.indexOf('MSIE') != -1) ); // élément à retourner var lelm_element = null; if( isOpera || isIE ) { var elem = document.getElementById(id); if( elem ) { //verify it is a valid match! if( elem.id == id ) { //valid match! lelm_element = elem; } else { //not a valid match! //the non-standard, document.all array has keys for all name'd, and id'd elements //start at one, because we know the first match, is wrong! for( var i=1; i 'valeur' */ function elements_de_formulaire_vers_tableau( pfrm_formulaire ) { var lsa_champs_valeurs = new Array(); for( li_indice in pfrm_formulaire.elements ) { // Récupération de l'élément var lm_element = pfrm_formulaire.elements[li_indice] // On teste qu'on n'obtient pas null, ce qui peut arriver, au moins sous IE6 if( lm_element ) { var ls_champ = lm_element.name; // On teste la valeur du nom de l'élément, car parmi les éléments récupérés, bcp ne sont pas ceux attendus. // Ces éléments dépendent du navigateur, on peut obtenir dans ls_champ undefined ou 'item' ou autre (constaté sous IE6 et FF3.6.7) // et sous ie8 ls_champ peut valoir null, et le typeof ne gère plus if( ls_champ && (typeof(ls_champ) != 'undefined') && (ls_champ.length > 0) ) { var ls_valeur = lm_element.value; // Test du même type que ci-dessus if( typeof(ls_valeur) != 'undefined' ) { lsa_champs_valeurs[ls_champ] = ls_valeur; } } } } return lsa_champs_valeurs; }/* Copyright (c) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * * Author: Doug Ricket, others * * Marker manager is an interface between the map and the user, designed * to manage adding and removing many points when the viewport changes. * * * Algorithm: The MM places its markers onto a grid, similar to the map tiles. * When the user moves the viewport, the MM computes which grid cells have * entered or left the viewport, and shows or hides all the markers in those * cells. * (If the users scrolls the viewport beyond the markers that are loaded, * no markers will be visible until the EVENT_moveend triggers an update.) * * In practical consequences, this allows 10,000 markers to be distributed over * a large area, and as long as only 100-200 are visible in any given viewport, * the user will see good performance corresponding to the 100 visible markers, * rather than poor performance corresponding to the total 10,000 markers. * * Note that some code is optimized for speed over space, * with the goal of accommodating thousands of markers. * */ /** * Creates a new MarkerManager that will show/hide markers on a map. * * @constructor * @param {Map} map The map to manage. * @param {Object} opt_opts A container for optional arguments: * {Number} maxZoom The maximum zoom level for which to create tiles. * {Number} borderPadding The width in pixels beyond the map border, * where markers should be display. * {Boolean} trackMarkers Whether or not this manager should track marker * movements. */ function MarkerManager(map, opt_opts) { var me = this; me.map_ = map; me.mapZoom_ = map.getZoom(); me.projection_ = map.getCurrentMapType().getProjection(); opt_opts = opt_opts || {}; me.tileSize_ = MarkerManager.DEFAULT_TILE_SIZE_; var maxZoom = MarkerManager.DEFAULT_MAX_ZOOM_; if(opt_opts.maxZoom != undefined) { maxZoom = opt_opts.maxZoom; } me.maxZoom_ = maxZoom; me.trackMarkers_ = opt_opts.trackMarkers; var padding; if (typeof opt_opts.borderPadding == "number") { padding = opt_opts.borderPadding; } else { padding = MarkerManager.DEFAULT_BORDER_PADDING_; } // The padding in pixels beyond the viewport, where we will pre-load markers. me.swPadding_ = new GSize(-padding, padding); me.nePadding_ = new GSize(padding, -padding); me.borderPadding_ = padding; me.gridWidth_ = []; me.grid_ = []; me.grid_[maxZoom] = []; me.numMarkers_ = []; me.numMarkers_[maxZoom] = 0; GEvent.bind(map, "moveend", me, me.onMapMoveEnd_); // NOTE: These two closures provide easy access to the map. // They are used as callbacks, not as methods. me.removeOverlay_ = function(marker) { map.removeOverlay(marker); me.shownMarkers_--; }; me.addOverlay_ = function(marker) { map.addOverlay(marker); me.shownMarkers_++; }; me.resetManager_(); me.shownMarkers_ = 0; me.shownBounds_ = me.getMapGridBounds_(); }; // Static constants: MarkerManager.DEFAULT_TILE_SIZE_ = 1024; MarkerManager.DEFAULT_MAX_ZOOM_ = 17; MarkerManager.DEFAULT_BORDER_PADDING_ = 100; MarkerManager.MERCATOR_ZOOM_LEVEL_ZERO_RANGE = 256; /** * Initializes MarkerManager arrays for all zoom levels * Called by constructor and by clearAllMarkers */ MarkerManager.prototype.resetManager_ = function() { var me = this; var mapWidth = MarkerManager.MERCATOR_ZOOM_LEVEL_ZERO_RANGE; for (var zoom = 0; zoom <= me.maxZoom_; ++zoom) { me.grid_[zoom] = []; me.numMarkers_[zoom] = 0; me.gridWidth_[zoom] = Math.ceil(mapWidth/me.tileSize_); mapWidth <<= 1; } }; /** * Removes all currently displayed markers * and calls resetManager to clear arrays */ MarkerManager.prototype.clearMarkers = function() { var me = this; me.processAll_(me.shownBounds_, me.removeOverlay_); me.resetManager_(); }; /** * Gets the tile coordinate for a given latlng point. * * @param {LatLng} latlng The geographical point. * @param {Number} zoom The zoom level. * @param {GSize} padding The padding used to shift the pixel coordinate. * Used for expanding a bounds to include an extra padding * of pixels surrounding the bounds. * @return {GPoint} The point in tile coordinates. * */ MarkerManager.prototype.getTilePoint_ = function(latlng, zoom, padding) { var pixelPoint = this.projection_.fromLatLngToPixel(latlng, zoom); return new GPoint( Math.floor((pixelPoint.x + padding.width) / this.tileSize_), Math.floor((pixelPoint.y + padding.height) / this.tileSize_)); }; /** * Finds the appropriate place to add the marker to the grid. * Optimized for speed; does not actually add the marker to the map. * Designed for batch-processing thousands of markers. * * @param {Marker} marker The marker to add. * @param {Number} minZoom The minimum zoom for displaying the marker. * @param {Number} maxZoom The maximum zoom for displaying the marker. */ MarkerManager.prototype.addMarkerBatch_ = function(marker, minZoom, maxZoom) { var mPoint = marker.getPoint(); // Tracking markers is expensive, so we do this only if the // user explicitly requested it when creating marker manager. if (this.trackMarkers_) { GEvent.bind(marker, "changed", this, this.onMarkerMoved_); } var gridPoint = this.getTilePoint_(mPoint, maxZoom, GSize.ZERO); for (var zoom = maxZoom; zoom >= minZoom; zoom--) { var cell = this.getGridCellCreate_(gridPoint.x, gridPoint.y, zoom); cell.push(marker); gridPoint.x = gridPoint.x >> 1; gridPoint.y = gridPoint.y >> 1; } }; /** * Returns whether or not the given point is visible in the shown bounds. This * is a helper method that takes care of the corner case, when shownBounds have * negative minX value. * * @param {Point} point a point on a grid. * @return {Boolean} Whether or not the given point is visible in the currently * shown bounds. */ MarkerManager.prototype.isGridPointVisible_ = function(point) { var me = this; var vertical = me.shownBounds_.minY <= point.y && point.y <= me.shownBounds_.maxY; var minX = me.shownBounds_.minX; var horizontal = minX <= point.x && point.x <= me.shownBounds_.maxX; if (!horizontal && minX < 0) { // Shifts the negative part of the rectangle. As point.x is always less // than grid width, only test shifted minX .. 0 part of the shown bounds. var width = me.gridWidth_[me.shownBounds_.z]; horizontal = minX + width <= point.x && point.x <= width - 1; } return vertical && horizontal; } /** * Reacts to a notification from a marker that it has moved to a new location. * It scans the grid all all zoom levels and moves the marker from the old grid * location to a new grid location. * * @param {Marker} marker The marker that moved. * @param {LatLng} oldPoint The old position of the marker. * @param {LatLng} newPoint The new position of the marker. */ MarkerManager.prototype.onMarkerMoved_ = function(marker, oldPoint, newPoint) { // NOTE: We do not know the minimum or maximum zoom the marker was // added at, so we start at the absolute maximum. Whenever we successfully // remove a marker at a given zoom, we add it at the new grid coordinates. var me = this; var zoom = me.maxZoom_; var changed = false; var oldGrid = me.getTilePoint_(oldPoint, zoom, GSize.ZERO); var newGrid = me.getTilePoint_(newPoint, zoom, GSize.ZERO); while (zoom >= 0 && (oldGrid.x != newGrid.x || oldGrid.y != newGrid.y)) { var cell = me.getGridCellNoCreate_(oldGrid.x, oldGrid.y, zoom); if (cell) { if (me.removeFromArray(cell, marker)) { me.getGridCellCreate_(newGrid.x, newGrid.y, zoom).push(marker); } } // For the current zoom we also need to update the map. Markers that no // longer are visible are removed from the map. Markers that moved into // the shown bounds are added to the map. This also lets us keep the count // of visible markers up to date. if (zoom == me.mapZoom_) { if (me.isGridPointVisible_(oldGrid)) { if (!me.isGridPointVisible_(newGrid)) { me.removeOverlay_(marker); changed = true; } } else { if (me.isGridPointVisible_(newGrid)) { me.addOverlay_(marker); changed = true; } } } oldGrid.x = oldGrid.x >> 1; oldGrid.y = oldGrid.y >> 1; newGrid.x = newGrid.x >> 1; newGrid.y = newGrid.y >> 1; --zoom; } if (changed) { me.notifyListeners_(); } }; /** * Searches at every zoom level to find grid cell * that marker would be in, removes from that array if found. * Also removes marker with removeOverlay if visible. * @param {GMarker} marker The marker to delete. */ MarkerManager.prototype.removeMarker = function(marker) { var me = this; var zoom = me.maxZoom_; var changed = false; var point = marker.getPoint(); var grid = me.getTilePoint_(point, zoom, GSize.ZERO); while (zoom >= 0) { var cell = me.getGridCellNoCreate_(grid.x, grid.y, zoom); if (cell) { me.removeFromArray(cell, marker); } // For the current zoom we also need to update the map. Markers that no // longer are visible are removed from the map. This also lets us keep the count // of visible markers up to date. if (zoom == me.mapZoom_) { if (me.isGridPointVisible_(grid)) { me.removeOverlay_(marker); changed = true; } } grid.x = grid.x >> 1; grid.y = grid.y >> 1; --zoom; } if (changed) { me.notifyListeners_(); } }; /** * Add many markers at once. * Does not actually update the map, just the internal grid. * * @param {Array of Marker} markers The markers to add. * @param {Number} minZoom The minimum zoom level to display the markers. * @param {Number} opt_maxZoom The maximum zoom level to display the markers. */ MarkerManager.prototype.addMarkers = function(markers, minZoom, opt_maxZoom) { var maxZoom = this.getOptMaxZoom_(opt_maxZoom); for (var i = markers.length - 1; i >= 0; i--) { this.addMarkerBatch_(markers[i], minZoom, maxZoom); } this.numMarkers_[minZoom] += markers.length; }; /** * Returns the value of the optional maximum zoom. This method is defined so * that we have just one place where optional maximum zoom is calculated. * * @param {Number} opt_maxZoom The optinal maximum zoom. * @return The maximum zoom. */ MarkerManager.prototype.getOptMaxZoom_ = function(opt_maxZoom) { return opt_maxZoom != undefined ? opt_maxZoom : this.maxZoom_; } /** * Calculates the total number of markers potentially visible at a given * zoom level. * * @param {Number} zoom The zoom level to check. */ MarkerManager.prototype.getMarkerCount = function(zoom) { var total = 0; for (var z = 0; z <= zoom; z++) { total += this.numMarkers_[z]; } return total; }; /** * Add a single marker to the map. * * @param {Marker} marker The marker to add. * @param {Number} minZoom The minimum zoom level to display the marker. * @param {Number} opt_maxZoom The maximum zoom level to display the marker. */ MarkerManager.prototype.addMarker = function(marker, minZoom, opt_maxZoom) { var me = this; var maxZoom = this.getOptMaxZoom_(opt_maxZoom); me.addMarkerBatch_(marker, minZoom, maxZoom); var gridPoint = me.getTilePoint_(marker.getPoint(), me.mapZoom_, GSize.ZERO); if(me.isGridPointVisible_(gridPoint) && minZoom <= me.shownBounds_.z && me.shownBounds_.z <= maxZoom ) { me.addOverlay_(marker); me.notifyListeners_(); } this.numMarkers_[minZoom]++; }; /** * Returns true if this bounds (inclusively) contains the given point. * @param {Point} point The point to test. * @return {Boolean} This Bounds contains the given Point. */ GBounds.prototype.containsPoint = function(point) { var outer = this; return (outer.minX <= point.x && outer.maxX >= point.x && outer.minY <= point.y && outer.maxY >= point.y); } /** * Get a cell in the grid, creating it first if necessary. * * Optimization candidate * * @param {Number} x The x coordinate of the cell. * @param {Number} y The y coordinate of the cell. * @param {Number} z The z coordinate of the cell. * @return {Array} The cell in the array. */ MarkerManager.prototype.getGridCellCreate_ = function(x, y, z) { var grid = this.grid_[z]; if (x < 0) { x += this.gridWidth_[z]; } var gridCol = grid[x]; if (!gridCol) { gridCol = grid[x] = []; return gridCol[y] = []; } var gridCell = gridCol[y]; if (!gridCell) { return gridCol[y] = []; } return gridCell; }; /** * Get a cell in the grid, returning undefined if it does not exist. * * NOTE: Optimized for speed -- otherwise could combine with getGridCellCreate_. * * @param {Number} x The x coordinate of the cell. * @param {Number} y The y coordinate of the cell. * @param {Number} z The z coordinate of the cell. * @return {Array} The cell in the array. */ MarkerManager.prototype.getGridCellNoCreate_ = function(x, y, z) { var grid = this.grid_[z]; if (x < 0) { x += this.gridWidth_[z]; } var gridCol = grid[x]; return gridCol ? gridCol[y] : undefined; }; /** * Turns at geographical bounds into a grid-space bounds. * * @param {LatLngBounds} bounds The geographical bounds. * @param {Number} zoom The zoom level of the bounds. * @param {GSize} swPadding The padding in pixels to extend beyond the * given bounds. * @param {GSize} nePadding The padding in pixels to extend beyond the * given bounds. * @return {GBounds} The bounds in grid space. */ MarkerManager.prototype.getGridBounds_ = function(bounds, zoom, swPadding, nePadding) { zoom = Math.min(zoom, this.maxZoom_); var bl = bounds.getSouthWest(); var tr = bounds.getNorthEast(); var sw = this.getTilePoint_(bl, zoom, swPadding); var ne = this.getTilePoint_(tr, zoom, nePadding); var gw = this.gridWidth_[zoom]; // Crossing the prime meridian requires correction of bounds. if (tr.lng() < bl.lng() || ne.x < sw.x) { sw.x -= gw; } if (ne.x - sw.x + 1 >= gw) { // Computed grid bounds are larger than the world; truncate. sw.x = 0; ne.x = gw - 1; } var gridBounds = new GBounds([sw, ne]); gridBounds.z = zoom; return gridBounds; }; /** * Gets the grid-space bounds for the current map viewport. * * @return {Bounds} The bounds in grid space. */ MarkerManager.prototype.getMapGridBounds_ = function() { var me = this; return me.getGridBounds_(me.map_.getBounds(), me.mapZoom_, me.swPadding_, me.nePadding_); }; /** * Event listener for map:movend. * NOTE: Use a timeout so that the user is not blocked * from moving the map. * */ MarkerManager.prototype.onMapMoveEnd_ = function() { var me = this; me.objectSetTimeout_(this, this.updateMarkers_, 0); }; /** * Call a function or evaluate an expression after a specified number of * milliseconds. * * Equivalent to the standard window.setTimeout function, but the given * function executes as a method of this instance. So the function passed to * objectSetTimeout can contain references to this. * objectSetTimeout(this, function() { alert(this.x) }, 1000); * * @param {Object} object The target object. * @param {Function} command The command to run. * @param {Number} milliseconds The delay. * @return {Boolean} Success. */ MarkerManager.prototype.objectSetTimeout_ = function(object, command, milliseconds) { return window.setTimeout(function() { command.call(object); }, milliseconds); }; /** * Refresh forces the marker-manager into a good state. *
    *
  1. If never before initialized, shows all the markers.
  2. *
  3. If previously initialized, removes and re-adds all markers.
  4. *
*/ MarkerManager.prototype.refresh = function() { var me = this; if (me.shownMarkers_ > 0) { me.processAll_(me.shownBounds_, me.removeOverlay_); } me.processAll_(me.shownBounds_, me.addOverlay_); me.notifyListeners_(); }; /** * After the viewport may have changed, add or remove markers as needed. */ MarkerManager.prototype.updateMarkers_ = function() { var me = this; me.mapZoom_ = this.map_.getZoom(); var newBounds = me.getMapGridBounds_(); // If the move does not include new grid sections, // we have no work to do: if (newBounds.equals(me.shownBounds_) && newBounds.z == me.shownBounds_.z) { return; } if (newBounds.z != me.shownBounds_.z) { me.processAll_(me.shownBounds_, me.removeOverlay_); me.processAll_(newBounds, me.addOverlay_); } else { // Remove markers: me.rectangleDiff_(me.shownBounds_, newBounds, me.removeCellMarkers_); // Add markers: me.rectangleDiff_(newBounds, me.shownBounds_, me.addCellMarkers_); } me.shownBounds_ = newBounds; me.notifyListeners_(); }; /** * Notify listeners when the state of what is displayed changes. */ MarkerManager.prototype.notifyListeners_ = function() { GEvent.trigger(this, "changed", this.shownBounds_, this.shownMarkers_); }; /** * Process all markers in the bounds provided, using a callback. * * @param {Bounds} bounds The bounds in grid space. * @param {Function} callback The function to call for each marker. */ MarkerManager.prototype.processAll_ = function(bounds, callback) { for (var x = bounds.minX; x <= bounds.maxX; x++) { for (var y = bounds.minY; y <= bounds.maxY; y++) { this.processCellMarkers_(x, y, bounds.z, callback); } } }; /** * Process all markers in the grid cell, using a callback. * * @param {Number} x The x coordinate of the cell. * @param {Number} y The y coordinate of the cell. * @param {Number} z The z coordinate of the cell. * @param {Function} callback The function to call for each marker. */ MarkerManager.prototype.processCellMarkers_ = function(x, y, z, callback) { var cell = this.getGridCellNoCreate_(x, y, z); if (cell) { for (var i = cell.length - 1; i >= 0; i--) { callback(cell[i]); } } }; /** * Remove all markers in a grid cell. * * @param {Number} x The x coordinate of the cell. * @param {Number} y The y coordinate of the cell. * @param {Number} z The z coordinate of the cell. */ MarkerManager.prototype.removeCellMarkers_ = function(x, y, z) { this.processCellMarkers_(x, y, z, this.removeOverlay_); }; /** * Add all markers in a grid cell. * * @param {Number} x The x coordinate of the cell. * @param {Number} y The y coordinate of the cell. * @param {Number} z The z coordinate of the cell. */ MarkerManager.prototype.addCellMarkers_ = function(x, y, z) { this.processCellMarkers_(x, y, z, this.addOverlay_); }; /** * Use the rectangleDiffCoords function to process all grid cells * that are in bounds1 but not bounds2, using a callback, and using * the current MarkerManager object as the instance. * * Pass the z parameter to the callback in addition to x and y. * * @param {Bounds} bounds1 The bounds of all points we may process. * @param {Bounds} bounds2 The bounds of points to exclude. * @param {Function} callback The callback function to call * for each grid coordinate (x, y, z). */ MarkerManager.prototype.rectangleDiff_ = function(bounds1, bounds2, callback) { var me = this; me.rectangleDiffCoords(bounds1, bounds2, function(x, y) { callback.apply(me, [x, y, bounds1.z]); }); }; /** * Calls the function for all points in bounds1, not in bounds2 * * @param {Bounds} bounds1 The bounds of all points we may process. * @param {Bounds} bounds2 The bounds of points to exclude. * @param {Function} callback The callback function to call * for each grid coordinate. */ MarkerManager.prototype.rectangleDiffCoords = function(bounds1, bounds2, callback) { var minX1 = bounds1.minX; var minY1 = bounds1.minY; var maxX1 = bounds1.maxX; var maxY1 = bounds1.maxY; var minX2 = bounds2.minX; var minY2 = bounds2.minY; var maxX2 = bounds2.maxX; var maxY2 = bounds2.maxY; for (var x = minX1; x <= maxX1; x++) { // All x in R1 // All above: for (var y = minY1; y <= maxY1 && y < minY2; y++) { // y in R1 above R2 callback(x, y); } // All below: for (var y = Math.max(maxY2 + 1, minY1); // y in R1 below R2 y <= maxY1; y++) { callback(x, y); } } for (var y = Math.max(minY1, minY2); y <= Math.min(maxY1, maxY2); y++) { // All y in R2 and in R1 // Strictly left: for (var x = Math.min(maxX1 + 1, minX2) - 1; x >= minX1; x--) { // x in R1 left of R2 callback(x, y); } // Strictly right: for (var x = Math.max(minX1, maxX2 + 1); // x in R1 right of R2 x <= maxX1; x++) { callback(x, y); } } }; /** * Removes value from array. O(N). * * @param {Array} array The array to modify. * @param {any} value The value to remove. * @param {Boolean} opt_notype Flag to disable type checking in equality. * @return {Number} The number of instances of value that were removed. */ MarkerManager.prototype.removeFromArray = function(array, value, opt_notype) { var shift = 0; for (var i = 0; i < array.length; ++i) { if (array[i] === value || (opt_notype && array[i] == value)) { array.splice(i--, 1); shift++; } } return shift; }; var metric = false; var singleClick = false; var queryCenterOptions = new Object(); var queryLineOptions = new Object(); queryCenterOptions.icon = new GIcon(); queryCenterOptions.icon.image = "http://www.sitimmo.com/images/disque_centre.png"; queryCenterOptions.icon.iconSize = new GSize(20,20); queryCenterOptions.icon.shadowSize = new GSize(0, 0); queryCenterOptions.icon.iconAnchor = new GPoint(10, 10); queryCenterOptions.draggable = true; queryCenterOptions.bouncy = false; queryLineOptions.icon = new GIcon(); queryLineOptions.icon.image = "http://www.sitimmo.com/images/disque_resize.png"; queryLineOptions.icon.iconSize = new GSize(25,20); queryLineOptions.icon.shadowSize = new GSize(0, 0); queryLineOptions.icon.iconAnchor = new GPoint(12, 10); queryLineOptions.draggable = true; queryLineOptions.bouncy = false; function destination(orig, hdng, dist) { var R = 6371; // rayon moyen de la terre var oX, oY; var x, y; var d = dist/R; // distance angulaire hdng = hdng * Math.PI / 180; // degrees vers radians oX = orig.x * Math.PI / 180; oY = orig.y * Math.PI / 180; y = Math.asin( Math.sin(oY)*Math.cos(d) + Math.cos(oY)*Math.sin(d)*Math.cos(hdng) ); x = oX + Math.atan2(Math.sin(hdng)*Math.sin(d)*Math.cos(oY), Math.cos(d)-Math.sin(oY)*Math.sin(y)); y = y * 180 / Math.PI; x = x * 180 / Math.PI; return new GLatLng(y, x); } // Clacul la distance entre 2 points function distance(point1, point2) { var R = 6371; // earth's mean radius in km var lon1 = point1.lng()* Math.PI / 180; var lat1 = point1.lat() * Math.PI / 180; var lon2 = point2.lng() * Math.PI / 180; var lat2 = point2.lat() * Math.PI / 180; var deltaLat = lat1 - lat2 var deltaLon = lon1 - lon2 var step1 = Math.pow(Math.sin(deltaLat/2), 2) + Math.cos(lat2) * Math.cos(lat1) * Math.pow(Math.sin(deltaLon/2), 2); var step2 = 2 * Math.atan2(Math.sqrt(step1), Math.sqrt(1 - step1)); return step2 * R; } // Classe qui permet de tracer et gérer un cercle de recherche var SitiGoogleMapDisque = function (pi_rayon, pGM_point, pGM_map) { // Constantes // Type this.is_disque = 'disque'; // Tableau de couleurs this.isa_couleurs = ["#0000ff", "#00ff00", "#ff0000"]; // Attributs // indice de la couleur courante this.ii_couleur_disque = 0; // La google map this.GM_map; // Type de forme this.type; // Rayon du disque this.ii_rayon; // Poignée de redimensionnement this.resizeDisque; // centre du disque this.centreDisque; // Disque courant this.disque; // Couleur courante this.is_couleur ; this.control; //Tableau des points du disque this.points; // Position de la poignée de redimensionnement this.resizeDisquePosition; // Position du centre du disque this.centreDisquePosition; //Initialisation du disque this.initialiser_disque(pi_rayon, pGM_point, pGM_map); } // Initialisation du disque SitiGoogleMapDisque.prototype.initialiser_disque = function(pGM_point, pi_rayon, pGM_map) { // Initialisation des variables d'instance this.type = this.is_disque; this.ii_rayon = pi_rayon; this.GM_map = pGM_map; // Ajout du centre et de la poignée de redimensionnement sur la carte this.resizeDisquePosition = destination(pGM_point, 90, this.ii_rayon/1000); this.resizeDisque = new GMarker(this.resizeDisquePosition, queryLineOptions); this.centreDisquePosition = pGM_point; this.centreDisque = new GMarker(this.centreDisquePosition, queryCenterOptions); this.is_couleur = this.isa_couleurs[this.ii_couleur_disque++ % 3]; pGM_map.addOverlay(this.resizeDisque); pGM_map.addOverlay(this.centreDisque); var iSGMD_disque_courant = this; // Ajout des écouteurs d'évènement pour redissiner le disque et effectuer d'autres actions // A la fin d'un redimensionnement GEvent.addListener ( this.resizeDisque, "dragend", function() { iSGMD_disque_courant.majDisque(1); } ); // Pendant un redimensionnement GEvent.addListener ( this.resizeDisque, "drag", function() { iSGMD_disque_courant.majDisque(1); } ); // A la fin d'un déplacement GEvent.addListener( this.centreDisque, "dragend", function() { iSGMD_disque_courant.majDisque(2); } ); // pendant un déplacement GEvent.addListener( this.centreDisque, "drag", function() { iSGMD_disque_courant.majDisque(2); } ); } // Mise à jour du tracé du disque SitiGoogleMapDisque.prototype.majDisque = function (type) { this.GM_map.removeOverlay(this.disque); if (type==1) { this.resizeDisquePosition = this.resizeDisque.getPoint(); this.ii_rayon = distance(this.centreDisquePosition, this.resizeDisquePosition) * 1000; this.afficher(); } else { this.centreDisquePosition = this.centreDisque.getPoint(); this.afficher(); this.resizeDisque.setPoint(this.getEast()); } } // Affichage du disque SitiGoogleMapDisque.prototype.afficher = function() { if (this.type == this.is_disque) { this.points = []; var distance = this.ii_rayon/1000; for (i = 0; i < 72; i++) { this.points.push(destination(this.centreDisquePosition, i * 360/72, distance) ); } this.points.push(destination(this.centreDisquePosition, 0, distance) ); //this.disque = new GPolyline(this.points, this.color, 6); this.disque = new GPolygon(this.points, this.is_couleur, 1, 1, this.is_couleur, 0.2); this.GM_map.addOverlay(this.disque) } } // Fonction qui permet de savoir si un point passé en paramètre est contenu dans le disque SitiGoogleMapDisque.prototype.contient = function(point) { var j=0; var contient = false; var x = point.lng(); var y = point.lat(); for (var i=0; i < this.disque.getVertexCount(); i++) { j++; if (j == this.disque.getVertexCount()) { j = 0; } if (((this.disque.getVertex(i).lat() < y) && (this.disque.getVertex(j).lat() >= y)) || ((this.disque.getVertex(j).lat() < y) && (this.disque.getVertex(i).lat() >= y))) { if ( this.disque.getVertex(i).lng() + (y - this.disque.getVertex(i).lat()) / (this.disque.getVertex(j).lat()-this.disque.getVertex(i).lat()) * (this.disque.getVertex(j).lng() - this.disque.getVertex(i).lng())" + this.getDistHtml() + ""; } SitiGoogleMapDisque.prototype.getDistHtml = function() { result = "Radius "; if (metric) { if (this._radius < 1000) { result += "in meters : " + this._radius.toFixed(1); } else { result += "in kilometers : " + (this._radius / 1000).toFixed(1); } } else { var radius = this._radius * 3.2808399; if (radius < 5280) { result += "in feet : " + radius.toFixed(1); } else { result += "in miles : " + (radius / 5280).toFixed(1); } } return result; } SitiGoogleMapDisque.prototype.getNorth = function() { return this.points[0]; } SitiGoogleMapDisque.prototype.getSouth = function() { return this.points[(72/2)]; } SitiGoogleMapDisque.prototype.getEast = function() { return this.points[(72/4)]; } SitiGoogleMapDisque.prototype.getWest = function() { return this.points[(72/4*3)]; } // tableau global des SitiGoogleMaps var gSGMa_maps ; var gGMa_marker = new Array(); var SitiGoogleMap = function (ps_adresse, ps_div ) { // ajout dans le tableau global if( !gSGMa_maps ) gSGMa_maps = new Array(); this.ii_id = gSGMa_maps.length; gSGMa_maps.push(this); if( ps_div == "" ) { ps_div = "map"; } this.is_div = ps_div; this.ib_activer_icone_cliquee = false; this.ib_activer_icone_survolee = false; this.is_icone = ""; this.is_icone_cliquee = ""; this.is_icone_survolee = ""; this.is_icone_cdc = ""; this.is_icone_cdc_cliquee = ""; this.is_icone_cdc_survolee = ""; this.is_icone_largeur = 15; this.is_icone_hauteur = 15; this.ic_control = new GSmallZoomControl(); this.is_info_bulle_largeur_max = ""; this.iGC_geocoder = ""; this.charger(); } // Permet d'initialiser la carte SitiGoogleMap.prototype.charger = function() { if( GBrowserIsCompatible() ) { // Nouvelle Map dans la div id="map" this.iGM_map = new GMap2( window.document.getElementById(this.is_div) ); this.iGM_map.setCenter(new GLatLng(0, 0), 15); this.iGM_map.setMapType(G_NORMAL_MAP); this.iGM_map.addControl(this.ic_control); this.iMM_marker_manager = new MarkerManager(this.iGM_map); this.ajouter_evenements_carte(); } } // Permet de limiter le niveau de zoom // - zoom_min = niveau le plus loin ( min 1 ) // - zoom_max = niveau le plus proche ( max 19 ) SitiGoogleMap.prototype.limiter_zoom = function( zoom_min, zoom_max ) { var li_id_map_en_cours = this.ii_id; var lSGM_this = gSGMa_maps[li_id_map_en_cours]; GEvent.clearListeners(lSGM_this.iGM_map , "zoomend"); // Permet de limiter le niveau de zoom GEvent.addListener(lSGM_this.iGM_map , "zoomend", function() { if( zoom_min > lSGM_this.get_zoom() ) { lSGM_this.set_zoom( zoom_min ); } else if( zoom_max < lSGM_this.get_zoom() ) { lSGM_this.set_zoom( zoom_max ); } } ); } // Permet d'ajouter les évènements qui vont bien sur la carte SitiGoogleMap.prototype.ajouter_evenements_carte = function() { var li_id_map_en_cours = this.ii_id; // Permet de rafraichir la carte des que l'on change le niveau de zoom GEvent.addListener(gSGMa_maps[li_id_map_en_cours], "zoomend", function() { gSGMa_maps[li_id_map_en_cours].iMM_marker_manager.refresh(); } ); } // Permet d'effacer tous les points de la carte SitiGoogleMap.prototype.effacer_tout = function() { this.iGM_map.clearOverlays(); } // Permet de centrer sur une adresse en précisant le niveau de zoom SitiGoogleMap.prototype.centrer_adresse = function( ps_adresse, pi_zoom ) { if( pi_zoom ) { this.set_zoom(pi_zoom); } var li_id_map_en_cours = this.ii_id; this.get_geocoder().getLatLng( ps_adresse, function( point ) { if ( !point ) { if( getelement("div_map_debug") ) getelement("div_map_debug").innerHTML += ps_adresse + " n'as pas été trouvé.
"; } else { gSGMa_maps[li_id_map_en_cours].iGM_map.setCenter( point, gSGMa_maps[li_id_map_en_cours].get_zoom() ); } } ); } // Permet de centrer sur une latitude et une longitude en précisant le niveau de zoom SitiGoogleMap.prototype.centrer_coordonnees = function( pi_lat, pi_long, pi_zoom ) { if( pi_zoom ) { this.set_zoom(pi_zoom); } if( pi_lat == "" ) { pi_lat = 0; } if( pi_long == "" ) { pi_long = 0; } this.iGM_map.setCenter( new GLatLng(pi_lat, pi_long)); } // Permet d'ajouter les évènements qui vont bien sur un point SitiGoogleMap.prototype.ajouter_contenu_html_point = function( pGM_point, ps_html, pb_cdc ) { this.ajouter_evenements_point( pGM_point, ps_html, pb_cdc ); } // Permet d'ajouter les évènements qui vont bien sur un point SitiGoogleMap.prototype.ajouter_evenements_point = function( pGM_point, ps_html, pb_cdc ) { var li_id_map_en_cours = this.ii_id; // Affiche une bulle quand on clique sur sitimmo GEvent.addListener(pGM_point, "click", function() { if( this.ib_activer_icone_cliquee ) { pGM_point.setImage( gSGMa_maps[li_id_map_en_cours].get_icone_cliquee( pb_cdc ) ); } if( ps_html != '' ) { if( gSGMa_maps[li_id_map_en_cours].get_info_bulle_largeur_max() ) { var iGIWO_info_bulle_options = { maxWidth : gSGMa_maps[li_id_map_en_cours].get_info_bulle_largeur_max() }; pGM_point.openInfoWindowHtml(ps_html, iGIWO_info_bulle_options); } else { pGM_point.openInfoWindowHtml(ps_html); } } } ); if( this.ib_activer_icone_cliquee ) { // Remet la couleur de l'icone normale apres la fermeture de la bulle GEvent.addListener(pGM_point, "infowindowclose", function() { pGM_point.setImage( gSGMa_maps[li_id_map_en_cours].get_icone( pb_cdc ) ); } ); } if( this.ib_activer_icone_survolee ) { // Change l'icone quand on passe sur le point GEvent.addListener(pGM_point, "mouseover", function() { pGM_point.setImage( gSGMa_maps[li_id_map_en_cours].get_icone_survolee( pb_cdc ) ); } ); // Remet l'icone normale quand on quitte le point GEvent.addListener(pGM_point, "mouseout", function() { pGM_point.setImage( gSGMa_maps[li_id_map_en_cours].get_icone( pb_cdc ) ); } ); } } // Permet de placer un point aux coordonnées précisées // Retourne le marker qui a été placé ou qui existait deja // Prends en parametre : // - la latitude // - la longitude // - un contenu html (optionnel) // - une tableau de donnée d'annonces (optionnel) // - un booleen qui precise si l'annonce est oui ou non un "coup de coeur/programme neuf" (optionnel) SitiGoogleMap.prototype.placer_point_coordonnees = function( pi_lat, pi_long, ps_html, psa_tag, pb_cdc ) { var lGM_marker_existant = null; // On recherche si il existe deja un marker a ces coordonnées if( psa_tag != null ) { lGM_marker_existant = this.rechercher_point_selon_coordonnees(pi_lat, pi_long); } // Si ce marker existe on lui rajoute les données de l'annonce if( lGM_marker_existant != null ) { lGM_marker_existant.tag.push(psa_tag); return lGM_marker_existant; } // Sinon on créé un nouveau marker avec les données de l'annonce associées else { var li_id_map_en_cours = this.ii_id; //Création d´un icone personnalisé. if( gSGMa_maps[li_id_map_en_cours].get_icone( pb_cdc ) != '' ) { var lGI_icone = new GIcon(); lGI_icone.image = gSGMa_maps[li_id_map_en_cours].get_icone( pb_cdc ); lGI_icone.iconSize = new GSize(gSGMa_maps[li_id_map_en_cours].get_icone_largeur(), gSGMa_maps[li_id_map_en_cours].get_icone_hauteur()); lGI_icone.iconAnchor = new GPoint(6, 20); lGI_icone.infoWindowAnchor = new GPoint(5, 1); var lGM_point = new GMarker( new GLatLng(pi_lat, pi_long), lGI_icone); } else { var lGM_point = new GMarker( new GLatLng(pi_lat, pi_long) ); } this.iGM_map.addOverlay(lGM_point); if( ps_html != '' ) { this.ajouter_evenements_point(lGM_point, ps_html, pb_cdc); } lGM_point.tag = new Array(); lGM_point.tag.push(psa_tag); if( psa_tag != null ) { gGMa_marker.push(lGM_point); } return lGM_point; } } // Place un point à l'adresse spécifiée SitiGoogleMap.prototype.placer_point_adresse = function( ps_adresse, ps_html, pb_centrer, ps_adresse_alternative, pb_cdc ) { var li_id_map_en_cours = this.ii_id; this.new_geocoder().getLatLng( ps_adresse, function( point ) { if ( !point ) { if( ps_adresse_alternative ) { gSGMa_maps[li_id_map_en_cours].placer_point_adresse(ps_adresse_alternative, ps_html, pb_centrer); } } else { //Création d'un icone personnalisée. if( gSGMa_maps[li_id_map_en_cours].get_icone( pb_cdc ) != '' ) { var lGI_icone = new GIcon(); lGI_icone.image = gSGMa_maps[li_id_map_en_cours].get_icone( pb_cdc ); lGI_icone.iconSize = new GSize(gSGMa_maps[li_id_map_en_cours].get_icone_largeur(), gSGMa_maps[li_id_map_en_cours].get_icone_hauteur()); lGI_icone.iconAnchor = new GPoint(6, 20); lGI_icone.infoWindowAnchor = new GPoint(5, 1); var lGM_point = new GMarker( point, lGI_icone); } else { var lGM_point = new GMarker( point ); } gSGMa_maps[li_id_map_en_cours].iGM_map.addOverlay(lGM_point); gSGMa_maps[li_id_map_en_cours].ajouter_evenements_point(lGM_point, ps_html, pb_cdc); if( pb_centrer ) gSGMa_maps[li_id_map_en_cours].centrer_coordonnees(point.lat() ,point.lng()); return lGM_point; } } ); } // Permt de retrouver un Gmarker en fonction de ses coordonnees SitiGoogleMap.prototype.rechercher_point_selon_coordonnees = function( pi_lat, pi_long ) { var i = 0; var lb_trouve = false; var lGM_retour; while(i < gGMa_marker.length && !lb_trouve) { var lGM_marker = gGMa_marker[i]; if( lGM_marker.getLatLng().lat() == pi_lat && lGM_marker.getLatLng().lng() == pi_long ) { lb_trouve = true; lGM_retour = lGM_marker; } else { i++; } } return lGM_retour; } // Permet de placer un marker sur une couche associée a un niveau de zoom SitiGoogleMap.prototype.visibilite_selon_zoom = function( pGM_marker, pi_zoom_min, pi_zoom_max ) { if( pi_zoom_max == '') { pi_zoom_max = 17; } if( pi_zoom_min == '') { pi_zoom_min = 1; } this.iMM_marker_manager.addMarker(pGM_marker, pi_zoom_min, pi_zoom_max); } // desactive les bulle html quand on clique sur les points SitiGoogleMap.prototype.desactiver_bulle_html = function( ) { this.iGM_map.disableInfoWindow(); } // Permet de placer un marker sur une couche associée a un niveau de zoom SitiGoogleMap.prototype.rafraichir_carte = function() { this.iMM_marker_manager.refresh(); } // Vide le MarkerManager de ses markers SitiGoogleMap.prototype.vider_manager = function() { for( li=0; li