Find if given lat-long lies in any of the polygon in MongoDB - mongodb

I want to know if I get a lat-long of a user and want to check if he lies in any of the polygon that is stored in my db (MongoDB). How can this be achieved using mongoDB.
For instance my db will have 10 polygons stored as GeoJson objects. I get a lat-long and want to check if this lat-long lies in any of the 10 polygons in my DB.
Can this be achieved in MongoDB?

I dont think your particular case can be achieved in MongoDB. MongoDB does have polygon calculations with the $polygon operator. However, this operator takes a polygon and confirms if any documents are within it not the other way round.

I wrote this code in javascript it is working fine for me
var polygonData = "43.64486433588385,-79.3791389465332;43.64508171979899,-79.3930435180664;43.63682057801007,-79.38437461853027;43.63946054004705,-79.36819553375244;43.652720712083266,-79.37201499938965;43.65793702655821,-79.39111232757568;43.64927396999741,-79.37222957611084";
var lat='43.64927396999741';
var lng='-79.37222957611084';
polySearch(polygonData,lat,lng);
function polySearch(polygonData,lat,lng){
var lat_long=lat+","+lng;
var longitude_x = lng;
var latitude_y = lat;
var is_in_polygon=false;
var vertices_x=[];
var vertices_y=[];
var arr=polygonData.split(';');
for(var j=0; j<arr.length; j++){
var arr1=arr[j].split(',');
vertices_x.push(arr1[1]);
vertices_y.push(arr1[0]);
}
var points_polygon = vertices_x.length;
var isIn=isInPolygon(points_polygon, vertices_x, vertices_y, longitude_x, latitude_y);
if (isIn==1)
console.log('Which is in polygon');
else
console.log('Which is not in polygon');
function isInPolygon(points_polygon, vertices_x, vertices_y, longitude_x, latitude_y)
{
var i = 0;
var j = 0;
var c = 0;
for (i = 0, j = points_polygon-1 ; i < points_polygon; j = i++) {
var val="((("+vertices_y[i]+" > "+latitude_y+") != ("+vertices_y[j]+" > "+latitude_y+")) && ("+longitude_x+" < ("+vertices_x[j]+" - "+vertices_x[i]+") * ("+latitude_y+" - "+vertices_y[i]+") / ("+vertices_y[j]+" - "+vertices_y[i]+") + "+vertices_x[i]+"))";
if(eval(val))c=!c;
}
return c;
}
}

Sorry to only past two links, but i think these explains what should be done far better then i would:
A SO answer in the same subject
An excellent tutorial how to use mongodb geospatial indexes

Related

What would .shift do in MongoDB?

I am learning mongoDB and the below code will find the descendants of "Programming". However, I did not quite understand what would .shift do here.
var descendants = [];
var stack = [];
var item = db.categories.findOne({_id:"Programming"});
stack.push(item);
while(stack.length>0){
var current = stack.shift();
for(let i=0; i<current.children.length;i++){
var children = db.categories.findOne({_id:current.children[i]});
stack.push(children);
descendants.push(children._id);
}
}
descendants;
Could anyone help me understand this functionality?
the stack.shift() function shift the array stack one time to left. It says that the first element in the array removes from it, and returns to current.

Adding color to Netsuite suitelet's sublist row depending upon the result

Is there any way to add colors to a sublist's row depending upon a condition. I have loaded a saved search to show output on a sublist. But now I want to highlight the rows if the difference between todays date and audit date(search output) is more than 100 days.
var search = nlapiLoadSearch('customrecord_cseg_properties', 'customsearch52');
var columns=search.getColumns();
var sublist = form.addSubList('customsublist', 'staticlist', 'List of properties');
for(var i = 0; i< columns.length; i++){
sublist.addField('customcolumn'+i, 'text', columns[i].getLabel());
}
var result= search.runSearch();
var resultIndex = 0,resultStep = 1000,resultSet,resultSets = [];
do {
resultSet = result.getResults(resultIndex, resultIndex + resultStep);
resultSets = resultSets.concat(resultSet);
resultIndex = resultIndex + resultStep;
} while (resultSet.length > 0);
nlapiLogExecution('DEBUG','The Total number of rows is',resultSets.length);
for(var w= 0; w<resultSets.length ;w++){
for(var x=0; x<columns.length; x++){
var temp;
temp=resultSets[w].getText(columns[x]);
if(temp==null || temp==''){
temp=resultSets[w].getValue(columns[x]);
}
sublist.setLineItemValue('customcolumn'+x, Number(w)+1,temp);
}
I couldn't find any functions in UI Builder API for Netsuite for doing this. Please let me know if there is any other way to do this. Above is the code which I have used to display search result in suitelet.
There is no native api for that.
You can do it by mainpulating the DOM on the client script onInit function.
Just keep in mind that DOM manipulation are risky since they can break if NetSuite will chnage the DOM structure.

Not getting frequency values in webaudio-api

I am using this spectrogram.js from github to plot spectrogram and obtain frequency values in real-time.
Github Repo
I have written this extra stopSong function:
function stopSong() {
var analyser = audioContext.createAnalyser();
var ctx = new AudioContext();
var osc = ctx.createOscillator();
osc.connect(ctx.destination);
osc.start(0);
spectro.stop();
var freqData= new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(freqData);
//var f = Math.round(freqData[1]);
// var text = f + ' Hz';
var idx = 0;
for (var j=0; j < analyser.frequencyBinCount; j++) {
if (freqData[j] > freqData[idx]) {
idx = j;
}
}
var frequency = idx * ctx.sampleRate / analyser.fftSize;
console.log(frequency);
//document.getElementById("frec").innerHTML = text;
}
But everytime i am running it it give 0 as output. Can anybody tell whats wrong with my code.
You need to connect the oscillator to the analyser:
oscillator.connect(analyser);
Also you might want to call getByteFrequencyData multiple times, maybe in requestAnimationFrame, or something like setTimeout.

How do I add polyline length to a Bing Maps polygon

I am trying to recreate a tax map within my system using Bing Maps. My problem is in listing the length, in feet, of the sides of the polygons I am creating. I have a good idea of how to get the length of polylines I am creating from the MSSQL 2012 geometry or geography items in my database. I cannot figure out how to present it to the user effectively though. I have two ideas for how I would like to do this.
Place the lengths directly on or adjacent to the polyline in question.
Create an emphasized point on the full polygon and list to the side of the map, the lengths of the sides of the polygon based on a clockwise order.
Either of the 2 options would work as an acceptable solution. I used this tutorial to create my current environment so I would be looking to integrate the solution into it in some way:
How to create a spatial web service that connects a database to Bing Maps using EF5
Note that my implementation only uses the countries part of the code so I do not need to deal with single points like cities that are in that tutorial.
The relevant piece of code that handles drawing on the map that I would need to edit can be found here:
Bing Maps v7 WellKnowTextModule
If you want to get the perimeter of a polygon in SQL2012 you can grab the exterior ring of it. The exterior ring will be a LineString i.e. "#g.STExteriorRing()". Then measure the length along that line. i.e. "#g.STExteriorRing().STLength()". However, countries are usually not just single Polygons, they can be MultiPpolygons, or GeometryCollections. So to calculate these lengths we have to do a bit more work. Here is a helper method you can add to the service to calculate the perimeters of these shapes:
private double CalculateLength(SqlGeometry geom)
{
double length = 0;
if(string.Compare(geom.STGeometryType().Value, "polygon", true) == 0)
{
}
else if (string.Compare(geom.STGeometryType().Value, "multipolygon", true) == 0)
{
int numPolygon = geom.STNumGeometries().Value;
for(int i = 1; i <= numPolygon; i++){
length += geom.STGeometryN(i).STExteriorRing().STLength().Value;
}
}
else if (string.Compare(geom.STGeometryType().Value, "geometrycollection", true) == 0)
{
int numGeom = geom.STNumGeometries().Value;
for (int i = 1; i <= numGeom; i++)
{
length += CalculateLength(geom.STGeometryN(i));
}
}
return length;
}
To get the length info from the server side to the client add a property to the Country or BaseEntity class like this:
[DataMember]
public double Perimeter { get; set; }
From here you can populate this value after the linq query is used to get the response results using a simple loop that calls the helper method from earlier:
for (int i = 0; i < r.Results.Count;i++)
{
var geom = SqlGeometry.STGeomFromText(new System.Data.SqlTypes.SqlChars(r.Results[i].WKT), 4326);
r.Results[i].Perimeter = CalculateLength(geom);
}
As for displaying the information on the map. An easy way to place the information on a polyline is to choose a coordinate along the line, perhaps the middle one, just get the # or coordinates in the line and find the middle index and use that coordinate for a pushpin. You can then create a custom push using either a background image with text, or using custom HTML:
http://www.bingmapsportal.com/ISDK/AjaxV7#Pushpins4
http://www.bingmapsportal.com/ISDK/AjaxV7#Pushpins15
Wanted to add an addendum to the answer I accepted as I feel it changes it a bit.
While working on this I found that I was not actually able to get each line segment's length via entity framework. This is due to the fact that the query required changing the geography I had back to a geometry then parse it to its base line segments and then change those line segments back to geographies. The query, even in SQL, would take minutes so it was not an option to run dynamically in EF.
I ended up creating another table in my database containing the parsed line segments for each side of each polygon I had. Then I could use the centroids of the line segments as faux cities. I then added this logic into the DisplayData javascript function from the tutorial mentioned in the question after the for loop in the method.
if (shape.getLength) {
} else {
var chkPolygon = data.Results[0].WKT.substring(0, data.Results[0].WKT.indexOf('(', 0));
chkPolygon = chkPolygon.replace(/\s/g, '');
switch (chkPolygon.toLowerCase()) {
case 'point':
case 'polygon':
var latlonCheck = map.getCenter();
var setSides = window.location.origin + "/SpatialService.svc/FindNearBy?latitude=" +
latlonCheck.latitude + "&longitude=" + latlonCheck.longitude +
"&radius=" + data.Results[0].ID + "&layerName=" + "city" + "&callback=?";
CallRESTService(setSides, DisplaySides);
default:
break;
}
}
the data.Results[0].ID would find all the line segments in the new table for that specific country. Then the DisplaySides function is used to overlay the html pushpins as "cities" over the appropriate points for each side on the map
function DisplaySides(getSides) {
infobox.setOptions({ visible: false });
if (getSides && getSides.Results != null) {
for (var i = 0; i < getSides.Results.length; i++) {
var sideLenFtShort = Math.round(getSides.Results[i].LengthFeet * 100) / 100;
var htmlLenString = "<div style='font-size:14px;border:thin solid black;background-color:white;font-weight:bold;color:black;'>" + sideLenFtShort.toString(); + "</div>";
var testString = {
pushpinOptions: { width: null, height: null, htmlContent: htmlLenString }
};
var sideCtr = WKTModule.Read(getSides.Results[i].WKT, testString);
dataLayer.push(sideCtr);
}
}
else if (getSides && getSides.Error != null) {
alert("Error: " + getSides.Error);
}
}

Template.templatename.rendered can't return any data from mongodb

I would like to know how can I get the data from mongodb in Template.templatename.rendered function. I tried click event on other template and it's all working fine and return the results i wanted. But what I need is to rendered the chart on load. But I could not get any data from the mongodb.
//poll.js
var drawPollChart = function(){
//returns data on other template methods except for
//Template.templatename.rendered
var dist = getDistinctQuestionId();
alert('dist:'+dist);
var data_x =[];
for(var i=0; i< 1; i++)
{
var count = getDataCount(dist[i]);
var uniq = getDistinctResponseBucket(dist[i]);
for(var j=0; j<uniq.length; j++)
{
//alert('data:' + count[uniq[j]] + ", label:" + uniq[j]);
data_x.push({
data : count[uniq[j]],
label: uniq[j]
});
}
}
Template.pollChart.rendered = function() {
//can't draw a thing cause can't get any data from mongodb
drawPollChart();
};
Help please? Thanks in advance.
Just because the template is rendered doesn't mean the DB is connected.
Use Meteor.status().status to detect the state of the connection. For example you could wait to render the pollChart-template at all until Meteor.status().status === 'connected'.