I succeed to get intersection between line and polygon and display it on map. I had already post this issue here. Now I'm trying to display result for each line on console. When I tried to write console.log(result[i]) I got undefined. What is the right syntax I have to do, I tried many times. Here is my current code:
var lines = [line1, line2, line3, line4];
for (var i = 0; i < lines.length; i++) {
var intersection = [];
var result = [];
intersection = turf.intersect(lines[i], polygon1);
if (intersection) {
result.push(intersection);
L.geoJson(result, {
style: Style
}).addTo(map);
console.log(JSON.stringify(result[i]));
} else {
L.geoJson(lines[i]).addTo(map);
}
result is being defined inside your for loop which operates over lines...so why are you trying to use that loop's internal variable(meant for lines) on result, which only receives input from turf. I would think you just need console.log(result[0]), which would log your intersection.Secondly, I don't see the benefit of calling JSON.stringify for that console.log.
Related
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.
I have figured out how to run a Google App Script project/function on a form submit using the information at https://developers.google.com/apps-script/guides/triggers/events#form-submit_4.
Once I have e I can call e.response to get a FormResponse object and then call getItemResponses() to get an array of all of the responses.
Without iterating through the array and checking each one, is there a way to find the ItemResponse for a specific question?
I see getResponseForItem(item) but it looks like I have to somehow create an Item first?
Can I some how use e.source to get the Form object and then find the Item by question, without iterating through all of them, so I could get the Item object I can use with getResponseForItem(item)?
This is the code I use to pull the current set of answers into a object, so the most current response for the question Your Name becomes form.yourName which I found to be the easiest way to find responses by question:
function objectifyForm() {
//Makes the form info into an object
var myform = FormApp.getActiveForm();
var formResponses = myform.getResponses()
var currentResponse = formResponses[formResponses.length-1];
var responseArray = currentResponse.getItemResponses()
var form = {};
form.user = currentResponse.getRespondentEmail(); //requires collect email addresses to be turned on or is undefined.
form.timestamp = currentResponse.getTimestamp();
form.formName = myform.getTitle();
for (var i = 0; i < responseArray.length; i++){
var response = responseArray[i].getResponse();
var item = responseArray[i].getItem().getTitle();
var item = camelize(item);
form[item] = response;
}
return form;
}
function camelize(str) {
str = str.replace(/[\.,-\/#!$%\^&\*;:{}=\-_`~()#\+\?><\[\]\+]/g, '')
return str.replace(/(?:^\w|[A-Z]|\b\w|\s+)/g, function(match, index) {
if (+match === 0) return ""; // or if (/\s+/.test(match)) for white spaces
return index == 0 ? match.toLowerCase() : match.toUpperCase();
});
}
//Use with installable trigger
function onSubmittedForm() {
var form = objectifyForm();
Logger.log(form);
//Put Code here
}
A couple of important things.
If you change the question on the form, you will need to update your
code
Non required questions may or may not have answers, so check if answer exists before you use it
I only use installable triggers, so I know it works with those. Not sure about with simple triggers
You can see the form object by opening the logs, which is useful for finding the object names
I am using the st_geometry field and try to view the PNU code value.
I tried two ways.
oracle DB query.
select a.pnu from LP_PA_CBND_4600000000 a
where sde.st_contains(a.shape,
sde.st_point(177566.6728471977,160430.12935426735, 4))=1
When an event occurs, click the map object
i got the evt.mapPoint(x,y).
4 is my srid.
this way is took a long time. and query was down...
i used the arcgis api`s IdentifyParameters
my code is follows.
PoiClick : function(map, evt) {
G_evt =evt;
console.log("ClickPoint ==== "+evt.mapPoint);
var targetLayerId = 'LP_PA_CBND';
var url = map.Layers.getLayerInfo(targetLayerId).SVC_URL;
var map = map.getMap();
//파라미터 설정.
var idParams = new krcgis.core.tasks.IdentifyParameters();
G_idparams =idParams;
idParams.geometry = evt.mapPoint;
idParams.mapExtent = map.extent;
idParams.returnGeometry = true;
idParams.tolerance = 3;
idParams.layerOption = krcgis.core.tasks.IdentifyParameters.LAYER_OPTION_ALL;
idParams.width = map.width;
idParams.height = map.height;
krcgis.Function.GetPoiInfo(url, idParams);
return evt.mapPoint;
},
//POI 정보를 가져온다.
GetPoiInfo : function(url, idParams) {
idTask = new krcgis.core.tasks.IdentyfyTask(url);
idTask
.execute(idParams)
.addCallback(function (response) {
G_response = response;
if (response) {
return response;
}
})
.addErrback(function (error) {
console.log('GetPoiInfo result error=', error);
});
}
It could be obtained in this way code pnu.
However, this way is different from the value that gets pnu code depending on the zoom level.
I want to get a single pnu code in a single x, y values.
how to get pnu code?
Database table :
IdentifyTask can be a little tricky, because it takes into account zoom levels, therefor it doesn't always return the same results.
I suggest that you use QueryTask. Just one problem - it doesn't have tolerance parameter, but you can buffer your evt.mapPoint and get 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);
}
}
I'm using getElementsByTagName to return all the select lists on a page - is it possible to then filter these based upon an option value, ie of the first or second item in the list?
The reason is that for reasons I won't go into here there are a block of select lists with number values (1,2,3,4,5 etc) and others which have text values (Blue and Black, Red and Black etc) and I only want the scripting I have to run on the ones with numerical values. I can't add a class to them which would more easily let me do this however I can be certain that the first option value in the list will be "1".
Therefore is there a way to filter the returned list of selects on the page by only those whose first option value is "1"?
I am pretty sure that there is a better solution, but for the moment you can try something like:
var allSelect = document.getElementsByTagName("select");
var result = filterBy(allSelect, 0/*0 == The first option*/, "1"/* 1 == the value of the first option*/);
function filterBy(allSelect, index, theValue) {
var result = [];
for (var i = 0; i < allSelect.length; i++) {
if(allSelect[i].options[index].value == theValue ) {
result.push(allSelect[i]);
}
}
return result;
}
I managed to get this working by wrapping a simple IF statement around the action to be performed (in this case, disabling options) as follows:
inputs = document.getElementsByTagName('select');
for (i = 0; i < inputs.length; i++) {
if (inputs[i].options[1].text == 1) {
// perform action required
}
}
No doubt there is a slicker or more economic way to do this but the main thing is it works for me.