I have a lot of POIs in my database including location property. How can I add those POIs based on my location on my Map? I found HERE SDK has api like 'Explore Popular Places by Category', but these categories are predefined by HERE. I don't think I can add my POIs to HERE and search by these APIs.
I knew a solution that by adding cluster Marker on Map. but It's difficult and expensive if I retrieve POIs in my database every time. like finding all the POIs which within a circle region(radius is 10 miles). Do you have any better solution for adding custom POIs on HERE map?
Thanks
You may be looking for the Custom Location Extension.
You can add your custom POIs(markers) with custom images using HERE maps, here is the code:
After initialisation map onButtonClick,
SearchRequest searchRequest = new SearchRequest("Water");
searchRequest.execute(discoveryResultPageListener);
then add this method:
private ResultListener<DiscoveryResultPage> discoveryResultPageListener = new ResultListener<DiscoveryResultPage>() {
#Override
public void onCompleted(DiscoveryResultPage discoveryResultPage, ErrorCode errorCode) {
if (errorCode == ErrorCode.NONE) {
List<DiscoveryResult> s_ResultList = discoveryResultPage.getItems();
for (DiscoveryResult item : s_ResultList) {
/*
* Add a marker for each result of PlaceLink type.For best usability, map can be
* also adjusted to display all markers.This can be done by merging the bounding
* box of each result and then zoom the map to the merged one.
*/
if (item.getResultType() == DiscoveryResult.ResultType.PLACE) {
PlaceLink placeLink = (PlaceLink) item;
addMarkerAtPlace(placeLink);
Log.e("nameeee ",""+placeLink.getTitle());
}
}
} else {
Toast.makeText(m_activity,
"ERROR:Discovery search request returned return error code+ " + errorCode,
Toast.LENGTH_SHORT).show();
}
}
};
after this add a method for custom marker,
private void addMarkerAtPlace(PlaceLink placeLink) {
Image img = new Image();
try {
img.setImageResource(R.drawable.camping);
} catch (Exception e) {
e.printStackTrace();
}
MapMarker mapMarker = new MapMarker();
mapMarker.setIcon(img);
mapMarker.setTitle(placeLink.getTitle());
mapMarker.setCoordinate(new GeoCoordinate(placeLink.getPosition()));
m_map.addMapObject(mapMarker);
m_map.setCenter(new GeoCoordinate(placeLink.getPosition()), Map.Animation.NONE);
m_map.setZoomLevel(13);
List<MapObject> m_mapObjectList = new ArrayList<>();
m_mapObjectList.add(mapMarker);
}
Related
I managed to get together a code that allows me to pick a point on a Jfreechart and select the corresponding point on a JavaFX TableView and select one or multiple points. However it's one or the other situation. What I would like is to be able to listen to the CTL key so the user can pick multiple points only when the CLT Key is down in combination with the click. So my question is where and how can I put the key listener.
XYDataset dataset = createXYDataSet(fieldname1,fieldname2);
ChartViewer plotframe = new ChartViewer(createXYChart(dataset, fieldname1,fieldname2));
plotframe.addChartMouseListener(new ChartMouseListenerFX(){
public void chartMouseClicked(ChartMouseEventFX chartmouseevent) {
int datapoint;
selectionmodel.setSelectionMode(SelectionMode.MULTIPLE);
try {
XYItemEntity ce = (XYItemEntity) chartmouseevent.getEntity();
datapoint = ce.getItem();
datatable.requestFocus();
datatable.getSelectionModel().select(datapoint);
datatable.getFocusModel().focus(datapoint);
datatable.scrollTo(datapoint);
}catch (Exception e){
}
}
public void chartMouseMoved(ChartMouseEventFX chartmouseevent) {
}
}
});
Just looking at the docs http://www.jfree.org/jfreechart/api/javadoc_old/org/jfree/chart/fx/interaction/ChartMouseEventFX.html#getTrigger--
I see getTrigger will get you the MouseEvent https://docs.oracle.com/javase/8/javafx/api/javafx/scene/input/MouseEvent.html#isControlDown--
which has isControlDown()
So try boolean isCtrlDown = chartmouseevent.getTrigger().isControlDown();
I am just trying out the SDK Lite API and I am wondering how I can achieve to drag a MapMarker object from one place to another. I suggest, it works somehow with disabling the default onPan gesture, but actually the problem starts with picking an existing object.
Here is my code so far:
public void pickMarker(Point2D p) {
map.getGestures().disableDefaultAction(GestureType.PAN);
map.pickMapItems(p, 20f, pickMapItemsResult -> {
if (pickMapItemsResult != null) {
pickedMarker = pickMapItemsResult.getTopmostMarker();
} else {
map.getGestures().enableDefaultAction(GestureType.PAN);
}
});
}
public void dragMarker(Point2D p) {
if (pickedMarker != null) {
pickedMarker.setCoordinates(map.getCamera().viewToGeoCoordinates(p));
}
}
public boolean releaseMarker(Point2D p) {
map.getGestures().enableDefaultAction(GestureType.PAN);
if (pickedMarker != null) {
GeoCoordinates newCoordinates = map.getCamera().viewToGeoCoordinates(p);
pickedMarker.setCoordinates(newCoordinates);
pickedMarker = null;
return true;
}
return false;
}
while these functions are called on the three states of the onPanListener:
mapView.getGestures().setPanListener((gestureState, point2D, point2DUpdate, v) -> {
if (gestureState.equals(GestureState.BEGIN)) {
mapViewUIEngine.pickMarker(point2D);
}
if (gestureState.equals(GestureState.UPDATE)) {
mapViewUIEngine.dragMarker(point2DUpdate);
}
if (gestureState.equals(GestureState.END)) {
if (mapViewUIEngine.releaseMarker(point2DUpdate)) {
regionController.movePoint(0,
updateNewLocation(point2D, point2DUpdate);
}
}
});
From one of the developer in Github I now know, that the polygon is returned instead of the marker (which is lying on a polygon line, but how can I get the marker instead?
You can use map markers to precisely point to a location on the map.
The following method will add a custom map marker to the map:
MapImage mapImage = MapImageFactory.fromResource(context.getResources(), R.drawable.here_car);
MapMarker mapMarker = new MapMarker(geoCoordinates);
mapMarker.addImage(mapImage, new MapMarkerImageStyle());
mapView.getMapScene().addMapMarker(mapMarker);
For more details, please refer
https://developer.here.com/documentation/android-sdk/dev_guide/topics/map-items.html#add-map-markers
I am trying to find a way to detect (or receive notification) that a Node has been added to a Scene and is visible.
I am creating Node objects off the main JavaFx thread and add them to the Stage and Scene using Platform.runLater(). However I would like the Node object to receive notification that is has been added to the Scene and is visible, for example I wish to trigger an animation to start.
I can't seem to find any property or method to add a listener to capture such an event. Any suggestions?
The third-party JavaFX library ReactFX has a mechanism for this, and this exact use case is cited in the blog. In short, you can do
Val<Boolean> showing = Val.flatMap(node.sceneProperty(), Scene::windowProperty)
.flatMap(Window::showingProperty);
and then of course
showing.addListener((obs, wasShowing, isNowShowing) -> {
if (isNowShowing) {
// node is showing
} else {
// node is not showing
}
});
The standard library has a version of this, but it is very badly written. (It is not typesafe, has no compile-time checking that the properties exist, and also pipes a lot of unnecessary warnings to standard error if any of the properties in the "chain" are null, even though the API docs indicate this is a supported use case.) If you want to do this with the standard JavaFX library, you can do
BooleanBinding showing = Bindings.selectBoolean(node.sceneProperty(), "window", "showing");
and then use the binding the same way as above.
Finally, you could do all this by hand, but it gets a bit ugly to manage the listeners properly:
BooleanProperty showing = new SimpleBooleanProperty();
ChangeListener<Window> windowListener = (obs, oldWindow, newWindow) -> {
showing.unbind();
if (newWindow != null) {
showing.bind(newWindow.showingProperty());
} else {
showing.set(false);
}
};
ChangeListener sceneListener = (obs, oldScene, newScene) -> {
showing.unbind();
if (oldScene != null) {
oldScene.windowProperty().removeListener(windowListener);
}
if (newScene == null) {
showing.set(false);
} else {
newScene.windowProperty().addListener(windowListener);
if (newScene.getWindow() == null) {
showing.set(false);
} else {
showing.bind(newScene.getWindow().showingProperty());
}
}
};
node.sceneProperty().addListener(sceneListener);
if (node.getScene() == null) {
showing.set(false);
} else {
node.getScene().windowProperty().add(windowListener);
if (node.getScene().getWindow() == null) {
showing.set(false);
} else {
showing.bind(node.getScene().getWindow().showingProperty());
}
}
You can add a listener to the children property of container node into which you are adding the new node.
grid.getChildren().addListener((ListChangeListener<? super Node>) change -> {
System.out.println(change.getList().get(0).getTypeSelector());
});
change.getList().get(0) returns the first node that is added to grid object.
After James's comment, I have looked up and yes, it is possible to do it from node's perspective as well. You can listen to parentProeprty's changes on the node. Following snippet shows the way to do it.
Button b = new Button("Test");
b.parentProperty().addListener((observable, oldValue, newValue) -> {
System.out.println("added to a container " + newValue);
});
answerPane.getChildren().add(b);
I'm using android SDK implement the search suggestion, code looks like below:
private void performSearch(CharSequence searchTerm) {
try {
DiscoveryRequest request = new SearchRequest( searchTerm.toString())
.setSearchCenter( mMap.getCenter() )
.setCollectionSize( 10 );
ErrorCode error = request.execute( mSearchRequestListener );
if ( error != ErrorCode.NONE ) {
Log.i( TAG, "Here API place search error: " + error.name() );
mSearchAdapter.notifyDataSetInvalidated();
}
} catch ( IllegalArgumentException ex ) {
Log.i( TAG, "Here API place search exception: " +
ex.getMessage() != null ? ex.getMessage() : "" );
mSearchAdapter.notifyDataSetInvalidated();
}
}
private ResultListener<DiscoveryResultPage> mSearchRequestListener =
new ResultListener<DiscoveryResultPage>() {
#Override
public void onCompleted(DiscoveryResultPage data, ErrorCode error) {
if ( error != ErrorCode.NONE ) {
Log.i( TAG, "Here API place search error: " + error.name() );
mSearchAdapter.notifyDataSetInvalidated();
return;
}
Log.d(TAG, "mSearchRequestListener.onCompleted: count=" + data.getItems().size() );
mResultList = new ArrayList<DiscoveryResult>( data.getItems());
String vicinity = mResultList.get(0).getVicinity();
//String location = ?
mSearchAdapter.notifyDataSetChanged();
}
};
How can I get the Location of a DiscoveryResult after I get DiscoveryResult list? It seems I didn't find this property in DiscoveryResult object. I need to add this location to my RoutePlan to calculate a route.
RoutePlan routePlan = new RoutePlan();
routePlan.addWaypoint(currentGeoCoordinate);
routePlan.addWaypoint(destGeoCoordinate);
routeManager.calculateRoute( routePlan, mRouteManagerListener );
I have a workaround for this in my code. After I get vicinity, I make a request at http://geocoder.cit.api.here.com/6.2/geocode.json?searchtext=" + vicinity + "gen=9"; to get the response. There is a Location property in response of this request. the disadvantage is I need to make a request to get location every time. Any suggestion to get the location without making a request to server?
Thanks in advance.
The data in the DiscoveryResultPage can be of several types, and you should sheck for the right type.
See documentation here:
https://developer.here.com/mobile-sdks/documentation/android-hybrid-plus/topics/places.html
The important part:
Calling DiscoveryResultPage.getItems(), returns a List containing one
of the following types of objects, which are DiscoveryResult
instances. DiscoveryResult is a collection of Link subtypes.
PlaceLink - Represents discovery information about a Place. The
PlaceLink contains a brief summary about a place. Details about a
place are available from the Place that the PlaceLink references.
DiscoveryLink - Represents a discovery-related API link used to
retrieve additional DiscoveryResultPage. This type of Link can be a
result item in an Explore or Here type of search. The DiscoveryLink
references refined discovery requests resulting in more specific
results. For example, the DiscoveryLink may link to a discovery
request to search for 'Eat & Drink', 'Going Out', 'Accommodation', and
so on. Since there may be new types of Link items in the future, it is
recommended that each type of DiscoveryResult be checked before it is
used (as shown in the following code snippet).
That means practically, that you iterate over data and check for the types like this:
// Implement a search result listener
ResultListener<DiscoveryResultPage> searchListener = new ResultListener<DiscoveryResultPage>() {
#Override
public void onCompleted(DiscoveryResultPage results, ErrorCode error) {
if (error == ErrorCode.NONE) {
// The results is a DiscoveryResultPage which represents a
// paginated collection of items.
List<DiscoveryResult> items = results.getItems();
// Iterate through the found place items.
for (DiscoveryResult item : items) {
// A Item can either be a PlaceLink (meta information
// about a Place) or a DiscoveryLink (which is a reference
// to another refined search that is related to the
// original search; for example, a search for
// "Leisure & Outdoor").
if (item.getResultType() == ResultType.PLACE) {
PlaceLink placeLink = (PlaceLink) item;
// PlaceLink should be presented to the user, so the link can be
// selected in order to retrieve additional details about a place
// of interest.
...
} else if (item.getResultType() == ResultType.DISCOVERY) {
DiscoveryLink discoveryLink = (DiscoveryLink) item;
// DiscoveryLink can also be presented to the user.
// When a DiscoveryLink is selected, another search request should be
// performed to retrieve results for a specific category.
...
}
}
} else {
// Handle search request error.
}
}
};
or only get the PlaceLink items directly like that:
public void onCompleted(DiscoveryResultPage data, ErrorCode error) {
List<PlaceLink> results = data.getPlaceLinks(); // we are only interested in PlaceLinks
if (results.size() > 0) {
for (PlaceLink result : results) {
// do something with the PlaceLink item
}
} else {
// handle empty result case
}
The PlaceLink object then has all the methods you would except, also getPosition() or getDistance() that you can use for putting results on the map or calculate a route.
I'm sort of jumping in headfirst to some Flex/AIR stuff. I have a pretty solid background with AS3, but given the inherent hierarchal complexity of Flex (compared to regular Flash), I'm running into an issue.
Let's assume that you have an app where pretty much everything is event driven (common). Accessing elements in the near vicinity of the event target, or the event target itself, is trivial. I'm trying to find, however, the most practical (read: best, most efficient) way to find children that are far removed from the current context.
I know there are functions like getChildAt() and getChildByName(), but that assumes a parent context; what if the element (Flex) you're looking for is several parents up, in a sibling, and then several children down? We take for granted things like jQuery that do this easily, but obviously we don't have that luxury in AS3.
Are any of the following valid? Is there a better way?
Iterate through parents and parents' parents until you find a stop point, find the sibling, and iterate through children and their children until you find your target;
Keep key objects in a global object store (sic) and reference them as necessary (yech)
Use specific dot notation to reach the target, including elements (like skins and their containers - yech again)
Any thoughts would be appreciated.
Edit:
To clarify, let's take an empty Flex 4 AIR app. We have WindowedApplication as the root, obviously, and let's add two SkinnableContainer children with IDs navContainer and mainContainer, respectively. Both have custom skins. Within mainContainer, we have another SkinnableContainer with a vertical layout and ID mainContent, and as one of its children, it has an object (any will do - a spark BorderContainer, maybe) with the ID animatedBox, for example. Within the navContainer, we have a spark Button, which has a listener bound for MouseEvent.CLICK. Within that function, we are going to want to access animatedBox (nativeWindow.mainContainer.mainContent.animatedBox) and animate it to change, say, it's width.
The goal is to access that distant DisplayObject (animatedBox) in a way that is as unobtrusive and efficient as possible, while still conforming to Flex standards that I clearly have yet to possess. :)
in my implementation it is easy to do (however it's in pure AS3):
in display object which handles the click:
private function onClick(e:MouseEvent):void{
Radio.broadcast(new CustomEvent(id, ..params));
}
in animatedBox:
Radio.addListener(id, new Reciever(uid, animate));
private function animate(e:CustomEvent) {
//needed code and access of CustomEvent props you pass
}
upd:
package lazylib.broadcast
{
/**
* ...
* #author www0z0k
*/
public class Reciever
{
private var id: String;
private var toRun: Function;
/*#param nm - unique listener id - required
*#param fn - event handler function - required*/
public function Reciever(nm:String, fn:Function)
{
id = nm;
toRun = fn;
}
public function onEvent(e:* = null):String {
if (e == null) { return id; }
toRun(e);
return id;
}
public function get ID():String { return id; }
}
}
and
package lazylib.broadcast
{
import flash.events.Event;
import flash.events.EventDispatcher;
/**
* ...
* #author www0z0k
*/
public final class Radio extends EventDispatcher
{
private static var listeners: Object = new Object();
private static var archive: Array = new Array();
private static var forSlowpokes: Object = new Object();
public static function get ForSlowpokes():Object { return forSlowpokes; }
public static function addListener(type: String , listener: Reciever):Boolean {
listeners['anchor'] = null;
if (!listeners[type]) {
var o: Object = new Object();
listeners[type] = o;
}
if (!listeners[type][listener.ID]) {
listeners[type][listener.ID] = listener;
return true;
}else {
return false;
}
}
public static function broadcast(evt: * , singleUse:Boolean = false):void {
var type:String = (evt as Event).type;
if (listeners[type]) {
var returned: Array = new Array();
for (var i: String in listeners[type]) {
if(listeners[type][i]){
var fnRetVal: String = listeners[type][i].onEvent(evt);
returned.push(fnRetVal);
}else{
//trace("no listener for id = " + i + ' , type = ' + type);
}
}
}else {
//trace("nobody's interested in : \"" + type + "\"");
}
if (singleUse) {
forSlowpokes[type] = 'you missed it realtime';
delete listeners[type];
}
}
public static function clearDeadFuncs(namez:Object):void {
for (var a:String in namez) {
if (a != 'anchor') {
killListener(a, namez[a]);
}
}
}
public static function killListener(type: String , id: String):Boolean {
if (!listeners[type]) {
//trace("there are no listeners for event : " + "\"" + type + "\"");
return false;
}else {
if (!listeners[type][id]) {
//trace("there is no \"" + id + "\" listener for event : " + "\"" + type + "\"");
return false;
}else {
listeners[type][id] = null;
//trace("removed listener \"" + id + "\" for event : " + "\"" + type + "\"");
var evt2kill: Number = 0;
for (var str: String in listeners[type]) {
if (listeners[type][str]) {
evt2kill++;
}
}
if (evt2kill == 0) {
delete listeners[type];
//trace("no more listeners for event : " + "\"" + type + "\"");
return true;
}
return true;
}
}
}
}
}
delivered as is ;)
We take for granted things like jQuery that do this easily, but obviously we don't have that luxury in AS3.
well there is this: http://tech.nitoyon.com/blog/2008/01/as3query_alpha.html
I asked myself this question also a lot of times. Still haven't figured out an ultimate solution to the problem. Iterating through parents and parents is definately a way but has to be taken with caution, cause relations might change in your application during runtime. I wrote a simple method a few days ago that lets you iterate through all parents of a given object. Definitely not an elegant solution but it works so far. the SWIZ framework also offers good methods to facilitate the communication between objects via code injection and Event mediation. Maybe worth a look...