How to find if coordinates fall within tile bounds? - javascript

I have a tile map like this .I would like to know the lat and long values (41.850033,-87.6500523) is located inside which tileBounds?
Am getting tile bounds values for every tile. but i dont know how to check if latitude is inside the range of particular tileBound value. how to find?
here is a working copy of my code
http://jsfiddle.net/doktormolle/55Nke/
var div = ownerDocument.createElement('div');
div.innerHTML =
'<pre><strong>tile:\n['+tile.x+','+tile.y+']</strong>\
\nbounds:{\nsw:['+tileBounds.sw.lat+','+tileBounds.sw.lng+'],\
\nne:['+tileBounds.ne.lat+','+tileBounds.ne.lng+']\n}</pre>';
div.style.width = this.tileSize.width + 'px';
div.style.height = this.tileSize.height + 'px';
div.style.fontSize = '10';
div.style.borderStyle = 'solid';
div.style.borderWidth = '1px';
div.style.borderColor = '#AAAAAA';
if(lat === 41.850033 && lng === -87.6500523){ //if latitude and longitude value inside that tile bounds set color as red
div.style.backgroundColor='red';
}
return div;
};
how to check here if my latitude and longitude lies inside tileBounds.sw and tileBounds.ne?
var setTileBackground =
this.mapDataPoints.some(function(el){
return (tileBounds.sw.lat <= el.latitude <= tileBounds.ne.lat && tileBounds.sw.lng <= el.longitude <= tileBounds.ne.lng)
}) // never returns true ...
I solved my problem with this check
var setTileBackground = this.mapDataPoints.some(function(el){
return (el.latitude > tileBounds.sw.lat && el.latitude < tileBounds.ne.lat && el.longitude > tileBounds.sw.lng &&
el.longitude < tileBounds.ne.lng)
});

Related

error with arrays in javascript

To fully understand this note this; `when the page loads it gets the area of the image (width * height) and creates all the x,y positions for all the positions in the area.
This works fine.
When I have another area from pos x,y and with also an area (width * height) should pop the positions from the first list so it can separate the two areas.
Little bug I noticed is I get little lines that are horizontal to the selected area and they don't extend far from that. I believe the reason is instead of making a clean square inside the image every line is offseted by a pixel or two.
Here's a video of the behaviour https://youtu.be/v1b6dEmfxQw
so since there's already an all positions list this code created a clone of the array and removes the positions.
var drop_boxes = $('.drop-box');
var area_grid = [];
var image_width = $('.img-class')[0].naturalWidth;
var image_height = $('.img-class')[0].naturalHeight;
drop_boxes.each(function() {
var position = $(this).position();
var width = $(this).width();
var height = $(this).height();
var positions_clone = positions.slice(0);
//console.log(positions_clone.length);
var top_offset = parseInt((position['top'] * image_width)/img_width);
var left_offset = parseInt((position['left'] * image_height)/img_height);
position['top'] = top_offset;
position['left'] = left_offset;
var width_offset = parseInt((width * image_width)/img_width);
var height_offset = parseInt((height * image_height)/img_height);
var width_counter = 0;
var height_counter = 0;
var area = width_offset * height_offset;
console.log(position);
console.log(width_offset);
console.log(height_offset);
if (position['top'] < image_height-1 && position['left'] < image_width) {
for (counter = 0; counter < area; counter++) {
var pos = [parseInt(position['left']+width_counter), parseInt(position['top']+height_counter)];
var index = positions.findIndex(function(item) {
// return result of comparing `data` with `item`
// This simple implementation assumes that all `item`s will be Arrays.
return pos.length === item.length && item.every(function(n, i) { return n === pos[i] });
});
//console.log(pos);
if (index > -1) {
positions_clone.splice(index, 1);
}
//area_grid.push(pos);
if (width_counter == width_offset) {
width_counter = 0;
height_counter += 1;
}
if (counter%100 == 0) {
var percentage = Math.round((counter/area)*100, 2);
console.log("Percentage: "+percentage+"%" + " "+counter);
}
width_counter += 1;
}
console.log(positions_clone.length);
console.log(area_grid.length);
areas[area_counter] = {'area': area_grid, 'positions': positions_clone};
parent.find('.area').text(area_counter);
area_counter += 1;
}
any clues in fixing it will be appreciated. I've showed how it behaves after commenting out certain parts of the code in the video.
Change
var index = positions.findIndex(function(item) {
to
var index = positions_clone.findIndex(function(item) {
Because after each splice, the indices of the original positions doesn't change but you are still using those indices to splice the clone.

JavaScript mouseover/mousemove cusor postion without clicking in input text box

I'm attempting to combine a JavaScript mechanism for auto placing the users cursor inside of an input box through the mouseover and mousemove listeners.
I have an almost perfect working example here: http://codepen.io/anon/pen/doxNLm?editors=101
var current_element = document.getElementById("hover");
current_element.onmousemove = function showCoords(evt) {
var form = document.forms.form_coords;
var parent_id = this.id;
form.parentId.value = parent_id;
form.pageXCoords.value = evt.pageX;
form.pageYCoords.value = evt.pageY;
form.layerXCoords.value = evt.layerX;
form.layerYCoords.value = evt.layerY;
function getTextWidth(text, font) {
// re-use canvas object for better performance
var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
var context = canvas.getContext("2d");
context.font = font;
var metrics = context.measureText(text);
return metrics.width;
};
var element_base_browser_styles = window.getDefaultComputedStyle(current_element);
var total_text_pixal_length = getTextWidth(current_element.value, element_base_browser_styles.fontFamily + " " + element_base_browser_styles.fontSize);
var add_char_pixal_lengths = 0;
var myStringArray = current_element.value.split('');
var arrayLength = myStringArray.length;
for (var i = 0; i <= arrayLength; i++) {
var get_char_value = getTextWidth(myStringArray[i], element_base_browser_styles.fontFamily + " " + element_base_browser_styles.fontSize);
add_char_pixal_lengths = add_char_pixal_lengths + (get_char_value) + 1.311111111111; //every char value is added together.
// console.log("Total: " + x);
if ((add_char_pixal_lengths)> (evt.layerX)) {
this.setSelectionRange(i, i);
add_char_pixal_lengths = 0;
break;
}
}
}
current_element.onmouseover = function() {
this.focus()
}
The problem I'm having is like Geosynchronous orbit; the cursor shifts out of place sometimes a few pixels (left or right). My calculation probably sucks, but I'm not sure canvas is really the best way to do the measurement? Is there a better way?
mousemove listener to receive element cursor coordinates from e.pageX
font style using window.getComputedStyles(input_element)
arr.split('') from input_element.text string: x = ['a','b','c']
'for loop' the array, generate a canvas and measure each characters width
add all char widths one by one until the value is greater than e.pageX
set the 'for loop' iterate as the setSelectionRange(i, i)
Any help or suggestions on making this better would be appreciated. Thanks!

Where in the grid the tile belongs

If I created a virtual grid 32x32 as a <div> example:
I want to fill one of the tile with a black box on click I have so far this:
var _proto = {
id:0,
x:0,
y:0
}
var objects = [];
$(".test").on("mousedown", function(e) {
var offset = $(this).offset();
var prex2 = 0, prey2 = 0;
prex2 = _proto.x = e.pageX-offset.left;
prey2 = _proto.y = e.pageY-offset.top;
_proto.id = (_objects.length)?_objects[_objects.length-1].id+1:0;
// Add to grid (not sure how to get proper cordinates)
$("<div style='display:absolute;width:32px;height:32px;background:black'></div>")
.css("top","")
.css("left","")
.appendTo("#maindiv");
});
I have the coordinates as prex2, and prey2 where the user clicked, but how do I know where to put it in the grid? I'm sure there a simple math equation but I can't figure it out.
Here's a snippet from a map editor that I was working on a few months back. It might help you grapple with your own code.
mapBlanket.addEventListener("mousedown", function(e) {
var sideWidth = document.getElementById("mapSide").offsetWidth;
var headHeight = document.getElementById("system").offsetHeight + 32;
var clickX = e.pageX - mapBlanket.offsetLeft - sideWidth + mapBlanket.parentNode.scrollLeft;
var clickY = e.pageY - mapBlanket.offsetTop - headHeight + mapBlanket.parentNode.scrollTop;
var tileX = clickX - (clickX % map.grid);
var tileY = clickY - (clickY % map.grid);
if (paintOn == 5) {
eventThis(tileX, tileY);
} else if (paintOn < 5) {
paintThis(tileX, tileY);
}
...
}
For reference, the map.grid was 32, same as yours. I just had a good bit defined in an object at the top of the file.

how to check whether crop div covers rotated image?

I want to check whether cropping div covers images in it.Everything works fine when image is not rotated but after rotating image crop does not shows error msg...
Here is fiddle : Fiddle
function isCropValid(){
var $selector = $("#resizeDiv"); // cropping Div
var $img = $("#rotateDiv"); // image div
var $selectorW = $selector.width();
var $selectorH = $selector.height();
var $selectorX = $selector.offset().left ;
var $selectorY = $selector.offset().top ;
var $imgW = $img.width();
var $imgH = $img.height();
var $imgX = $img.offset().left;
var $imgY = $img.offset().top;
var diff_X = $selectorX - $imgX;
var diff_Y = $selectorY - $imgY;
if(diff_X+$selectorW > $imgW){
return false;
} else if(diff_Y+$selectorH > $imgH){
return false;
} else if($selectorX<$imgX){
return false;
} else if($selectorY<$imgY){
return false;
}
else {
return true;
}
}
or another function
function isCropValid(){
var el1 = document.getElementById("resizeDiv"); // cropDiv
var el2 = document.getElementById("rotateDiv"); // imageDiv
var cropdiv = el1.getBoundingClientRect();
var imgdiv = el2.getBoundingClientRect();
return (
((imgdiv.top <= cropdiv.top) && (cropdiv.top <= imgdiv.bottom)) &&
((imgdiv.top <= cropdiv.bottom) && (cropdiv.bottom <= imgdiv.bottom)) &&
((imgdiv.left <= cropdiv.left) && (cropdiv.left <= imgdiv.right)) &&
((imgdiv.left <= cropdiv.right) && (cropdiv.right <= imgdiv.right))
);
}
I above code i have one image inside div.if crop div gets out of this div i m showing label bg color red meaning crop is not correct otherwise i m showing label color green means crop is correct..
I think what you'll have to do is to calculate the positions of each of the 4 points of the image top-left top-right bottom-right and bottom-left, then do the same thing for the crop div something like this:
var $topLeftX=$selectorX-($selectorW/2)-($selectorH/2);
var $topLeftY=$selectorY-($selectorH/2)-($selectorW/2);
var $bottomLeftX=$selectorX-($selectorW/2)+($selectorH/2);
var $bottomLeftY=$selectorY+($selectorH/2)-($selectorW/2);
var $topRightX=$selectorX+($selectorW/2)-($selectorH/2);
var $topRightY=$selectorY-($selectorH/2)+($selectorW/2);
var $bottomRightX=$selectorX+($selectorW/2)+($selectorH/2);
var $bottomRightY=$selectorY+($selectorH/2)+($selectorW/2);
Then compare the corner points.
now the issue is with the corners of the image, as after rotation this will need some sine/cosine calculations.
you might want to take a look at this post: Find the coordinates of the corners of a rotated object in fabricjs
I think it will make your life much easier
So this is gonna be a big hack, but hey :-) The idea is to put the cut out behind the image, and then see whether the image overlaps the cut out on all four corners.
function cutoutIsOK() {
// Grab the cutout element and position it behind the image
var cutout = document.querySelector('#resizeDiv');
cutout.style.zIndex = -1;
// Grab the image
var image = document.querySelector('#rotateDiv img');
// Take the four corners of the cutout element
var cutoutRect = cutout.getBoundingClientRect();
var pos = [
[cutoutRect.left, cutoutRect.top],
[cutoutRect.right - 1, cutoutRect.top],
[cutoutRect.left, cutoutRect.bottom - 1],
[cutoutRect.right - 1, cutoutRect.bottom - 1]
];
// And verify that the image overlaps all four corners
var ok = pos.every(function(p) {
return document.elementFromPoint(p[0], p[1]) === image;
});
// Reset the cutout's z-index to make it visible again
cutout.style.zIndex = 0;
return ok;
}

Google maps v3 polyline tooltip

A google maps marker object (google.maps.Marker) has a title property, so when a user moves their mouse over the marker a simple tooltip is displayed.
There isn't a title property on a polyline (google.maps.Polyline). Is there a way I can do this / simulate this in V3? I could do this in V2, and I can't find an example for V3.
I combined #samshull's answer above (duly upvoted!) with info from here to make the InfoWindow appear where the user's cursor mouses over the line:
// Open the InfoWindow on mouseover:
google.maps.event.addListener(line, 'mouseover', function(e) {
infoWindow.setPosition(e.latLng);
infoWindow.setContent("You are at " + e.latLng);
infoWindow.open(map);
});
// Close the InfoWindow on mouseout:
google.maps.event.addListener(line, 'mouseout', function() {
infoWindow.close();
});
Here, line is your PolyLine object; map is your Map object; and infoWindow is your InfoWindow object, which I just create with:
var infoWindow = new google.maps.InfoWindow();
I also follow this advice by re-using the same InfoWindow object for all my polylines rather than creating a new one for each line:
Best practices: For the best user experience, only one info window
should be open on the map at any one time. Multiple info windows make
the map appear cluttered. If you only need one info window at a time,
you can create just one InfoWindow object and open it at different
locations or markers upon map events, such as user clicks. If you do
need more than one info window, you can display multiple InfoWindow
objects at the same time.
Note that infoWindow.setContent() takes a string. So call toString() on a number variable if you want to display a number in the InfoWindow.
I view all of this as an imperfect workaround until Google Maps hopefully one day add a title property to PolylineOptions, just like they've already done for MarkerOptions.
I am not 100% this is the only way, or the best way, but it is a way to create a window over your Polyline
In Google maps V3, you should to create an InfoWindow then set the content using myInfoWindow.setContent("Hello World!")
In order to make it show on mouseover, you will need to do something like:
google.maps.event.addListener(myPolyline, 'mouseover', function() {
myInfoWindow.open(mymap);
// mymap represents the map you created using google.maps.Map
});
// assuming you want the InfoWindow to close on mouseout
google.maps.event.addListener(myPolyline, 'mouseout', function() {
myInfoWindow.close();
});
I found this online that helped me do tooltips on polygons,
from http://philmap.000space.com/gmap-api/poly-hov.html:
var tooltip=function(){
var id = 'tt';
var top = 3;
var left = 3;
var maxw = 200;
var speed = 10;
var timer = 20;
var endalpha = 95;
var alpha = 0;
var tt,t,c,b,h;
var ie = document.all ? true : false;
return{
show:function(v,w){
if(tt == null){
tt = document.createElement('div');
tt.setAttribute('id',id);
t = document.createElement('div');
t.setAttribute('id',id + 'top');
c = document.createElement('div');
c.setAttribute('id',id + 'cont');
b = document.createElement('div');
b.setAttribute('id',id + 'bot');
tt.appendChild(t);
tt.appendChild(c);
tt.appendChild(b);
document.body.appendChild(tt);
tt.style.opacity = 0;
tt.style.filter = 'alpha(opacity=0)';
document.onmousemove = this.pos;
}
tt.style.visibility = 'visible';
tt.style.display = 'block';
c.innerHTML = v;
tt.style.width = w ? w + 'px' : 'auto';
if(!w && ie){
t.style.display = 'none';
b.style.display = 'none';
tt.style.width = tt.offsetWidth;
t.style.display = 'block';
b.style.display = 'block';
}
if(tt.offsetWidth > maxw){tt.style.width = maxw + 'px'}
h = parseInt(tt.offsetHeight) + top;
clearInterval(tt.timer);
tt.timer = setInterval(function(){tooltip.fade(1)},timer);
},
pos:function(e){
var u = ie ? event.clientY + document.documentElement.scrollTop : e.pageY;
var l = ie ? event.clientX + document.documentElement.scrollLeft : e.pageX;
tt.style.top = (u - h) + 'px';
tt.style.left = (l + left) + 'px';
},
fade:function(d){
var a = alpha;
if((a != endalpha && d == 1) || (a != 0 && d == -1)){
var i = speed;
if(endalpha - a < speed && d == 1){
i = endalpha - a;
}else if(alpha < speed && d == -1){
i = a;
}
alpha = a + (i * d);
tt.style.opacity = alpha * .01;
tt.style.filter = 'alpha(opacity=' + alpha + ')';
}else{
clearInterval(tt.timer);
if(d == -1){tt.style.display = 'none'}
}
},
hide:function(){
clearInterval(tt.timer);
tt.timer = setInterval(function(){tooltip.fade(-1)},timer);
}
};
}();
Also, Please see this SO discussion about the same topic:
Tooltip over a Polygon in Google Maps
And,
Google maps rectangle/polygon with title
If i'm not mistaken i don't think it is possible to set the tooltip since as you mentioned there is not a title property in PolygonOptions object.But you can make a div that looks exactly the same as the tooltip and place it let's say in the tip of your mouse during the mousemove event.I tried also to find a solution to place this tooltip somewhere in the center of the polygon but i think it is too much of a trouble that's why i also think the google guys didn't implement it also.
Cheers

Categories

Resources