Upgrade an overpass layer code to use react-leaflet v2 - leaflet

The question Leaflet plugin only working when geolocation is enabled had a nice wrapping of the OverpassLayer OSM for react-leaflet. Unfortunately, it only works for react-leaflet v1.
import { LayerGroup } from "react-leaflet";
import L from "leaflet";
import OverPassLayer from "leaflet-overpass-layer";
export default class OverpassLayer extends LayerGroup {
componentWillReceiveProps(nextProps) {
console.log(nextProps.key);
console.log("OverpassLayer receiving props");
const query = "("
+ "node[\"amenity\"]({{bbox}});"
+ "way[\"amenity\"]({{bbox}});"
+ "relation[\"amenity\"]({{bbox}});"
+ ");"
+ "out body;"
+ ">;"
+ "out skel qt;";
const opl = new L.OverPassLayer({
"query": query,
"endPoint": "https://overpass-api.de/api/",
});
nextProps.map.addLayer(opl);
}
}
With v2, it doesn't work, ending with the error:
TypeError: Super expression must either be null or a function
Any idea on how to update this code to v2?

As for everything in react-leaflet v2, we need to reimplement the intermediate class (LayerGroup) as well:
// #flow
import LeafletOverPassLayer from "leaflet-overpass-layer";
import { withLeaflet, MapLayer } from "react-leaflet";
import type { MapLayerProps } from "react-leaflet";
type LeafletElement = LeafletOverPassLayer;
type Props = MapLayerProps;
class OverPassLayer extends MapLayer<LeafletElement, Props> {
createLeafletElement(props: Props): LeafletElement {
const el = new LeafletOverPassLayer({
query: "("
+ "node[\"amenity\"]({{bbox}});"
+ "way[\"amenity\"]({{bbox}});"
+ "relation[\"amenity\"]({{bbox}});"
+ ");"
+ "out body;"
+ ">;"
+ "out skel qt;",
endpoint: "https://overpass-api.de/api/",
minZoomIndicatorEnabled: false,
}, this.getOptions(props));
this.contextValue = { ...props.leaflet, layerContainer: el };
return el;
}
}
export default withLeaflet<Props, OverPassLayer>(OverPassLayer);
It's basically copy/paste + adding the overpass information. Here we display all amenities as a red circle.
Removed the zoom indicator as it seems to be missing an onRemove method.

V2 of react-leaflet completely breaks the ability to extend many components. I raised an issue about this a while ago:
https://github.com/PaulLeCam/react-leaflet/issues/506
This is an intentional design choice by the library's author (a choice that I wholeheartedly disagree with but that's a moot point)
Read through that Github thread and if you have further questions just ask :)

Related

Fully-transparent exposure of Eigen::Vector/Matrix types using pybind11

I have a simple class definition:
class State {
private:
Eigen::Vector3f m_data;
public:
State(const Eigen::Vector3f& state) : m_data(state) { }
Eigen::Vector3f get() const { return m_data; }
void set(const Eigen::Vector3f& _state) { m_data = _state; }
std::string repr() const {
return "state data: [x=" + std::to_string(m_data[0]) + ", y=" + std::to_string(m_data[1]) + ", theta=" + std::to_string(m_data[2]) + "]";
}
};
I then expose the above in python with pybind11:
namespace py = pybind11;
PYBIND11_MODULE(bound_state, m) {
m.doc() = "python bindings for State";
py::class_<State>(m, "State")
.def(py::init<Eigen::Vector3f>())
.def("get", &_State::get)
.def("set", &_State::set)
.def("__repr__", &_State::repr);
}
And everything works fine; I am able to import this module into python and construct a State instance with a numpy array. This isn't exactly what I want though. I want to be able to access this object as if it were a numpy array; I want to be able to do something like the following in python:
import bound_state as bs
arr = np.array([1, 2, 3])
a = bs.State(arr)
print(a[0])
(the above throws a TypeError: 'bound_state.State' object does not support indexing)
In the past, I've used boost::python to expose lists by using add_property and this allowed indexing of the underlying data in C++. does pybind11 have something similar that can work with Eigen? Could someone provide an example showing how to expose a State instance that is indexable?
Per the API Docs, this can be done easily with the def_property method.
Turn this bit:
namespace py = pybind11;
PYBIND11_MODULE(bound_state, m) {
m.doc() = "python bindings for State";
py::class_<State>(m, "State")
.def(py::init<Eigen::Vector3f>())
.def("get", &State::get)
.def("set", &State::set)
.def("__repr__", &State::repr);
}
Into this:
namespace py = pybind11;
PYBIND11_MODULE(bound_state, m) {
m.doc() = "python bindings for State";
py::class_<State>(m, "State")
.def(py::init<Eigen::Vector3f>())
.def_property("m_data", &State::get, &State::set)
.def("__repr__", &State::repr);
}
Now, from the python-side, I can do:
import bound_state as bs
arr = np.array([1, 2, 3])
a = bs.State(arr)
print(a.m_data[0])
This is not exactly what I want, but is a step in the right direction.

how to put verification in pageobject model in protractor

I have a code (credit to #kishanpatel) Traverse-through-each-row-for-a-column-text which will verify whether the value is added in grid or not. i want to put this in my page object. i was thinking to add the elements into page object and the if condition in a different helper file similar to selenium but i am not sure is that the right appraoch. see the details below.
if I call the mo.helper in spec.ts, it says gridcheck.ispresent() is not a function. How to handle this scenario?
code:
it('verify the grid that master obligation is added', function () {
var testvar = "'test_protractor'";
var row_check = element(by.xpath("//div[contains(text()," + testvar + ")]"));
if (row_check.isPresent()) {
row_check.getText().then(function (msg) {
if (row_check.isPresent()) {
console.log("Grid contains========== " + msg);
}
});
}
});
i have the below method in mo.ts(page object page):
this.grid = function (value) {
// var testvar = "'test_protractor'";
var row_check = element(by.xpath("//div[contains(text()," + value + ")]"));
return require('./mohelper.ts')
}
}
mohelper.ts:
require('../page/mo.ts')
var mohelper = function () {
this.gridvaluepresent = function () {
require('../page/mo.ts')
var gridcheck = mo.grid();
if(gridcheck.isPresent()) {
gridcheck.getText().then(function (msg) {
if (gridcheck.isPresent()) {
console.log("Grid contains========== " + msg);
}
})
}
}
}
module.exports = new mohelper();
spec.ts:
it('go to corresponding module and verify whether the master obligation is added ', function () {
browser.sleep(10000);
taxhome.selectmodule;
taxhome.selectmoduledropdown(1);
mo.grid("test_protractor");
mohelper.gridvaluepresent();
});
Couple of things here to be considered -
1) Most of the protractor's api methods are asynchronous i.e. they return promises you have to resolve/reject them to perform actions.
isPresent() also returns a promise, you need to resolve it-
var row_check = element(by.xpath("//div[contains(text()," + value + ")]"));
row_check.isPresent().then(function(present) {
if(present) { // it returns a boolean value
row_check.getText().then(function (msg) {
console.log("Grid contains========== " + msg);
});
}
});
2) Since you are using TypeScript , use its syntax rather than conventional js-
let row_check = element(by.xpath("//div[contains(text()," + value + ")]")); // Block scoped variable using 'let'
row_check.isPresent().then((present) => { // notice the thick arrow
if(present) {
row_check.getText().then((msg) => {
console.log("Grid contains========== " + msg);
});
}
});
3) Maintain Page Objects efficiently and readable-
All the helper methods, elements etc. for a single page should go in a single page object. Write them in separate classes, typescript uses the concept of classes and transpiles them to global functions.
moHelper.ts
import {ElementFinder, element} from 'protractor';
export class MoHelper {
public row_check: ElementFinder; // its of element finder type
gridValueCheck(value : string) {
row_check = element(by.xpath("//div[contains(text()," + value + ")]")); // please use Css selectors instead of Xpath!
row_check.isPresent().then((present) => {
if(present) {
row_check.getText().then((msg) => {
return msg; // here you are returning the msg of the row from your page!
});
}
});
}
}
Your spec.ts should validate that row msg!
import {MoHelper} from './moHelper.ts'
let mo: MoHelper = new MoHelper();
it('go to corresponding module and verify whether the master obligation is added ', () => {
browser.sleep(10000); // please refrain from using sleeps instead use Expected Conditions
taxhome.selectmodule;
taxhome.selectmoduledropdown(1);
expect(mo.gridValueCheck("test_protractor")).toEqual("Your Expected Message");
});
Please find the links for your reference to understand the above in more detail-
isPresent
Getting started with typescript
Using page objects in protractor/style guide
Expected Conditions

Producing 3D tracks in Google Earth kml files

I already have some code to generate 2D kml files, but I am interested in reproducing an image similar to this, with an associated depth profile to each position:
Is there a good reference (or perhaps python library) for doing this? I have not managed to find anything.
Image reference:
Baird, R.W., S.W. Martin, D.L. Webster, and B.L. Southall. 2014. Assessment of Modeled Received Sound Pressure Levels and Movements of Satellite-Tagged Odontocetes Exposed to Mid-Frequency Active Sonar at the Pacific Missile Range Facility: February 2011 Through February 2013. Prepared for U.S. Pacific Fleet, submitted to NAVFAC PAC by HDR Environmental, Operations and Construction, Inc.
You may use other language to generate some kml files like the one in the following link:
https://sites.google.com/site/canadadennischen888/home/kml/3d-tracking
click download the attached file
select "save as" to see the KML content
select "open" to see result in Google Earth
hope this help
If you are using java, I have code to generate kml to display 3D tracking in google earth. (plus, a vertical line from air to ground for each point).
(assumption: Since you had code for 2D, you may already have java pojo code that converted from kml21.xsd.)
(p.s. I can attached you an image if you know any free site for me to upload image.)
Hope this help:
package com.googleearth.util;
import java.util.List;
import javax.xml.bind.JAXBElement;
import com.a.googleearth.entities.GoogleEarthView;
import com.a.googleearth.model.AltitudeModeEnum;
import com.a.googleearth.model.DocumentType;
import com.a.googleearth.model.FolderType;
import com.a.googleearth.model.KmlType;
import com.a.googleearth.model.LineStringType;
import com.a.googleearth.model.LineStyleType;
import com.a.googleearth.model.ObjectFactory;
import com.a.googleearth.model.PlacemarkType;
import com.a.googleearth.model.StyleType;
public class KmlService {
public static final byte[] blue = new byte[]{(byte)0x64,(byte)0xF0,(byte)0x00,(byte)0xFF};
private static ObjectFactory factory = new ObjectFactory();
static final String DEFAULT_REGISTRATION_FOR_EMPTY = "EMPTY";
public static JAXBElement<KmlType> createKml(List<GoogleEarthView> listGoogleEarthDBView) {
KmlType kml = factory.createKmlType();
DocumentType document = factory.createDocumentType();
kml.setFeature(factory.createDocument(document));
{
LineStyleType redLineStyle = factory.createLineStyleType();
// http://www.zonums.com/gmaps/kml_color/
redLineStyle.setColor(new byte[]{(byte)0xFF,(byte)0xF0,(byte)0x00,(byte)0x14});
redLineStyle.setWidth(5f);
StyleType style = factory.createStyleType();
style.setId("blueLine");
style.setLineStyle(redLineStyle);
document.getStyleSelector().add(factory.createStyle(style));
}
FolderType folder = factory.createFolderType();
folder.setName(listGoogleEarthDBView.get(0).getFolderName());
document.getFeature().add(factory.createFolder(folder));
PlacemarkType currentPlacemark = null;
for (GoogleEarthView view : listGoogleEarthDBView) {
if (currentPlacemark == null || currentPlacemark.getName().equalsIgnoreCase("F0001") == false) {
if (currentPlacemark != null) {
JAXBElement<LineStringType> lineString = (JAXBElement<LineStringType>) currentPlacemark.getGeometry();
lineString.getValue().getCoordinates().add(view.getLongitude() + "," + view.getLatitude() + "," + view.getPressureAltitude()+"\n");
}
currentPlacemark = createF0001Placemark();
folder.getFeature().add(factory.createPlacemark(currentPlacemark));
}
JAXBElement<LineStringType> lineString = (JAXBElement<LineStringType>) currentPlacemark.getGeometry();
lineString.getValue().getCoordinates().add(view.getLongitude() + "," + view.getLatitude() + "," + view.getPressureAltitude()+"\n");
}
JAXBElement<KmlType> kmlElement = factory.createKml(kml);
return kmlElement;
}
private static PlacemarkType createF0001Placemark() {
PlacemarkType placeMark = factory.createPlacemarkType();
placeMark.setName("F0001");
placeMark.setStyleUrl("#blueLine");
LineStringType flyhtStreamLineString = factory.createLineStringType();
flyhtStreamLineString.setAltitudeMode(AltitudeModeEnum.ABSOLUTE);
flyhtStreamLineString.setExtrude(Boolean.TRUE);
placeMark.setGeometry(factory.createLineString(flyhtStreamLineString));
return placeMark;
}
}

Is there a way to auto expand objects in Chrome Dev Tools?

EVERY SINGLE TIME I view an object in the console I am going to want to expand it, so it gets tiresome to have to click the arrow to do this EVERY SINGLE TIME :) Is there a shortcut or setting to have this done automatically?
Consider using console.table().
To expand / collapse a node and all its children,
Ctrl + Alt + Click or Opt + Click on arrow icon
(note that although the dev tools doc lists Ctrl + Alt + Click, on Windows all that is needed is Alt + Click).
While the solution mentioning JSON.stringify is pretty great for most of the cases, it has a few limitations
It can not handle items with circular references where as console.log can take care of such objects elegantly.
Also, if you have a large tree, then ability to interactively fold away some nodes can make exploration easier.
Here is a solution that solves both of the above by creatively (ab)using console.group:
function expandedLog(item, maxDepth = 100, depth = 0){
if (depth > maxDepth ) {
console.log(item);
return;
}
if (typeof item === 'object' && item !== null) {
Object.entries(item).forEach(([key, value]) => {
console.group(key + ' : ' +(typeof value));
expandedLog(value, maxDepth, depth + 1);
console.groupEnd();
});
} else {
console.log(item);
}
}
Now running:
expandedLog({
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
})
Will give you something like:
The value of maxDepth can be adjusted to a desired level, and beyond that level of nesting - expanded log will fall back to usual console.log
Try running something like:
x = { a: 10, b: 20 }
x.x = x
expandedLog(x)
Also please note that console.group is non-standard.
Might not be the best answer, but I've been doing this somewhere in my code.
Update:
Use JSON.stringify to expand your object automatically:
> a = [{name: 'Joe', age: 5}, {name: 'John', age: 6}]
> JSON.stringify(a, true, 2)
"[
{
"name": "Joe",
"age": 5
},
{
"name": "John",
"age": 6
}
]"
You can always make a shortcut function if it hurts to type all that out:
j = function(d) {
return JSON.stringify(d, true, 2)
}
j(a)
Previous answer:
pretty = function(d)
{
var s = []
for (var k in d) {
s.push(k + ': ' + d[k])
}
console.log(s.join(', '))
}
then, instead of:
-> a = [{name: 'Joe', age: 5}, {name: 'John', age: 6}]
-> a
<- [Object, Object]
You do:
-> a.forEach(pretty)
<- name: Joe, age: 5
name: John, age: 6
Not the best solution, but works well for my usage. Deeper objects will not work so that's something that can be improved on.
option+Click on a Mac. Just discovered it now myself and have made my week! This has been as annoying as anything
By default the console on Chrome and Safari browsers will output objects which are collapsed, with sorted property keys, and include all inherited prototype chains.
I'm personally not a fan. Most developers need raw output of an object without the prototype chain, and anything else should be opt-in. Collapsed objects waste the developer's time, because they need to expand them, and if they wanted less output they could just log the property keys they need. Auto-sorting the property keys, leaves the developer without a way to check if their own sort works correctly, which could cause bugs. And lastly, the common Javascript developer does not spend much time working on the inherited prototype chain, so that adds noise to the logs.
How to expand objects in Console
Recommended
console.log(JSON.stringify({}, undefined, 2));
Could also use as a function:
console.json = object => console.log(JSON.stringify(object, undefined, 2));
console.json({});
"Option + Click" (Chrome on Mac) and "Alt + Click" (Chrome on Window)
However, it's not supported by all browsers (e.g. Safari), and Console still prints the prototype chains, auto-sorts property keys, etc.
Not Recommended
I would not recommend either of the top answers
console.table() - this is shallow expansion only, and does not expand nested objects
Write a custom underscore.js function - too much overhead for what should be a simple solution
Here is a modified version of lorefnon's answer which does not depend on underscorejs:
var expandedLog = (function(MAX_DEPTH){
return function(item, depth){
depth = depth || 0;
isString = typeof item === 'string';
isDeep = depth > MAX_DEPTH
if (isString || isDeep) {
console.log(item);
return;
}
for(var key in item){
console.group(key + ' : ' +(typeof item[key]));
expandedLog(item[key], depth + 1);
console.groupEnd();
}
}
})(100);
Here is my solution, a function that iterates an all the properties of the object, including arrays.
In this example I iterate over a simple multi-level object:
var point = {
x: 5,
y: 2,
innerobj : { innerVal : 1,innerVal2 : 2 },
$excludedInnerProperties : { test: 1},
includedInnerProperties : { test: 1}
};
You have also the possibility to exclude the iteration if the properties starts with a particular suffix (i.e. $ for angular objects)
discoverProperties = function (obj, level, excludePrefix) {
var indent = "----------------------------------------".substring(0, level * 2);
var str = indent + "level " + level + "\r\n";
if (typeof (obj) == "undefined")
return "";
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
var propVal;
try {
propVal = eval('obj.' + property);
str += indent + property + "(" + propVal.constructor.name + "):" + propVal + "\r\n";
if (typeof (propVal) == 'object' && level < 10 && propVal.constructor.name != "Date" && property.indexOf(excludePrefix) != 0) {
if (propVal.hasOwnProperty('length')) {
for (var i = 0; i < propVal.length; i++) {
if (typeof (propVal) == 'object' && level < 10) {
if (typeof (propVal[i]) != "undefined") {
str += indent + (propVal[i]).constructor.name + "[" + i + "]\r\n";
str += this.discoverProperties(propVal[i], level + 1, excludePrefix);
}
}
else
str += indent + propVal[i].constructor.name + "[" + i + "]:" + propVal[i] + "\r\n";
}
}
else
str += this.discoverProperties(propVal, level + 1, excludePrefix);
}
}
catch (e) {
}
}
}
return str;
};
var point = {
x: 5,
y: 2,
innerobj : { innerVal : 1,innerVal2 : 2 },
$excludedInnerProperties : { test: 1},
includedInnerProperties : { test: 1}
};
document.write("<pre>" + discoverProperties(point,0,'$')+ "</pre>");
Here is the output of the function:
level 0
x(Number):5
y(Number):2
innerobj(Object):[object Object]
--level 1
--innerVal(Number):1
--innerVal2(Number):2
$excludedInnerProperties(Object):[object Object]
includedInnerProperties(Object):[object Object]
--level 1
--test(Number):1
You can also inject this function in any web page and copy and analyze all the properties, try in on the google page using the chrome command:
discoverProperties(google,0,'$')
Also you can copy the output of the command using the chrome command:
copy(discoverProperties(myvariable,0,'$'))
if you have a big object, JSON.stringfy will give error Uncaught TypeError: Converting circular structure to JSON
, here is trick to use modified version of it
JSON.stringifyOnce = function(obj, replacer, indent){
var printedObjects = [];
var printedObjectKeys = [];
function printOnceReplacer(key, value){
if ( printedObjects.length > 2000){ // browsers will not print more than 20K, I don't see the point to allow 2K.. algorithm will not be fast anyway if we have too many objects
return 'object too long';
}
var printedObjIndex = false;
printedObjects.forEach(function(obj, index){
if(obj===value){
printedObjIndex = index;
}
});
if ( key == ''){ //root element
printedObjects.push(obj);
printedObjectKeys.push("root");
return value;
}
else if(printedObjIndex+"" != "false" && typeof(value)=="object"){
if ( printedObjectKeys[printedObjIndex] == "root"){
return "(pointer to root)";
}else{
return "(see " + ((!!value && !!value.constructor) ? value.constructor.name.toLowerCase() : typeof(value)) + " with key " + printedObjectKeys[printedObjIndex] + ")";
}
}else{
var qualifiedKey = key || "(empty key)";
printedObjects.push(value);
printedObjectKeys.push(qualifiedKey);
if(replacer){
return replacer(key, value);
}else{
return value;
}
}
}
return JSON.stringify(obj, printOnceReplacer, indent);
};
now you can use JSON.stringifyOnce(obj)
Its a work around, but it works for me.
I use in the case where a control/widget auto updates depending on user actions. For example, when using twitter's typeahead.js, once you focus out of the window, the dropdown disappears and the suggestions get removed from the DOM.
In dev tools right click on the node you want to expand enable break on... -> subtree modifications, this will then send you to the debugger. Keep hitting F10 or Shift+F11 untill you dom mutates. Once that mutates then you can inspect. Since the debugger is active the UI of Chrome is locked and doesn't close the dropdown and the suggestions are still in the DOM.
Very handy when troubleshooting layout of dynamically inserted nodes that are begin inserted and removed constantly.
Another easier way would be
Use JSON.stringify(jsonObject)
Copy and Paste the result to Visual Studio Code
Use Ctrl+K and Ctrl+F to format the result
You will see formatted expanded object
I have tried this for simple objects.
You can package JSON.stringify into a new function eg
jsonLog = function (msg, d) {
console.log(msg + '\n' + JSON.stringify(d, true, 2))
}
then
jsonLog('root=', root)
FWIW.
Murray
For lazy folks
/**
* _Universal extensive multilevel logger for lazy folks_
* #param {any} value **`Value` you want to log**
* #param {number} tab **Abount of `tab`**
*/
function log(value, tab = 4) {
console.log(JSON.stringify(value, undefined, tab));
}
Usage
log(anything) // [] {} 1 true null
Alt-click will expand all child nodes in the Chrome console.
You could view your element by accessing document.getElementsBy... and then right click and copy of the resulted object. For example:
document.getElementsByTagName('ion-app') gives back javascript object that can be copy pasted to text editor and it does it in full.
Better yet: right click on the resulted element - 'Edit as html' - 'Select all' - 'Copy' - 'Paste'

Newbie problems with Node, Mongo, and Mongoose

I am trying to learn how to use Node, Mongoose, and Mongo by looking at code from GitHub.
What's the purpose of this line:
PostProvider = function(){};
from: https://github.com/cmarin/MongoDB-Node-Express-Blog/blob/master/postprovider.js
To me, it seems like an empty function.
To simulate the "class-concept" in javascript, we have 3 ways. One of this way is to use the prototype feature. Example for a Apple class :
function Apple (type) {
this.type = type;
this.color = "red";
}
Apple.prototype.getInfo = function() {
return this.color + ' ' + this.type + ' apple';
};
In your example, the PostProvider function has no attributes. So, "cmarin" declares an empty function :
PostProvider = function() {};
And add some methods :
PostProvider.prototype.findAll
PostProvider.prototype.findById
etc.