How can i get all SKMap location objects so I can filter trough them? - ios

I use SKMap in a offline navigation iOS application and:
I'm trying to search from a UITextField a street/city/district within a preinstalled map and I want to get all objects that matches my search.
How can I get all map location objects so I can filter trough them?
From the sample didn't quite managed to do so.(I get only cities)
Is there other alternative or I must loop trough every city and get streets (Seems ugly)

You have to use SKNearbySearchSettings class and to set
searchObject.searchType = SKAll;
A more detailed example of using this class (should return all streets and POIs containing the "pizza" keyword):
SKNearbySearchSettings *searchObject = [SKNearbySearchSettings nearbySearchSettings];
searchObject.coordinate = CLLocationCoordinate2DMake(52.5233, 13.4127);
searchObject.radius = 40000;
searchObject.searchMode = SKSearchHybrid;
searchObject.searchResultSortType = SKMatchSort;
searchObject.searchType = SKAll;
searchObject.searchTerm = "pizza";
[[SKSearchService sharedInstance]startNearbySearchWithSettings:searchObject];

Related

Avoid coordinates when generating a route using Mapbox Direction API

I have been using Mapbox for my app to generate route and turn-by-turn navigation and it's working well. However I would like to avoid to go through some coordinates of the route but I can't figure it out.
The code to get the route :
Directions.shared.calculate(options) { [unowned self] (waypoints, routes, error) in
// Take first route and customize it in a way to get around some coordinates
}
Here is a scenario :
1- User location is latitude = 37.332331410000002, longitude = -122.0312186
2- The user is going to Santa Clara Unified School located on latitude = 37.354100000000003,longitude = -121.9552
3- The Api generates the following route :
[0] = {
latitude = 37.332329999999999
longitude = -122.03118000000001
}
[1] = {
latitude = 37.332619999999999
longitude = -122.03118000000001
}
[2] = {
latitude = 37.332609999999995
longitude = -122.03097000000001
}
[3] = {
latitude = 37.332609999999995
longitude = -122.03076000000001
}
[4] = {
latitude = 37.332199999999993
longitude = -122.03076000000001
}
[5] = {
latitude = 37.331689999999995
longitude = -122.03076000000001
}
[6] = {
latitude = 37.331689999999995
longitude = -122.03190000000002
}
[7] = {
latitude = 37.331719999999997
longitude = -122.03199000000002
}
[8] = {
latitude = 37.331759999999996
longitude = -122.03205000000003
} ...
4- Suppose the generated route goes through East Homestead Rd, I would like to be able to avoid this road and generate a new route even if it's a longer one.In the screen below avoid the route in red because going through East Homestead Rd and take the next fastest route not going through East Homestead Rd
Any help would be appreciated !
EDIT : Here is the query for finding if a route has points to avoid in it
// $linestring is the array of coordinates from the route in the string format of (lng lat,lng2 lat2,lng3 lat3,lng4 lat4....)
$query = $this->em->createQuery('
SELECT count(i) as counter
FROM HitsBundle:Hit i
WHERE i.datetime BETWEEN :lastMonth AND :now
AND
MBRCovers(
ST_Buffer(
ST_GeomFromText(\'LineString('.$linestring.')\') ,
0.00001
),
i.coordinates
) = 1
GROUP BY i.coordinates
HAVING counter > 1
')
->setParameter('lastMonth', $lastMonth)
->setParameter('now', new \DateTime())
->setMaxResults(1);
EDIT: Related issue on Github
I may be rough-guessing here, but looking through Mapbox API it does not have any options to avoid while generating routes, therefore you need to implement some route-selection logic on client-side.
Basically you need to have an algorithm which gets a set of points to avoid and checks if your Route geometry GeoJSON or Polyline are within some threshold range from given points. If it is - discard the route (or lower route priority).
Of course it may fail to find a route if all routes provided by Mapbox are discarded - Mapbox does not know about your restrictions, therefore using weight for routes could be one option of solving this.
These posts might give you some hints:
Is it possible to determine if a GeoJSON point is inside a GeoJSON polygon using JavasScript
How to check if a Latitude/Longitude point is on the GRoute in Google Maps API
After few months dealing with the MapBox Direction API we've come to the conclusion that it's not reliable for this specific use case. When calculating routes from Point A to Point B using the Direction API, MapBox offers an option includesAlternativeRoutes if set to true it provides alternative routes. However this is not consistent and in most cases it returns only the preferred route.
According to MapBox :
If the value of this property is true, the server attempts to find additional reasonable routes that visit the waypoints. Regardless, multiple routes are only returned if it is possible to visit the waypoints by a different route without significantly increasing the distance or travel time.
So we will switch to Google Maps as this feature is crucial to our business logic.

MapKit Define the desired type of search results (Country, city, region, etc)

For an app i'm building, I want to implement a feature that allows users to specify the geographical origin of wines (country (e.g. France), region (e.g. Bordeaux), subregion (e.g. Paullac)).
I want to make sure that I don't have to add all available countries myself, and that all information that comes into the database is valid. Therefore, I decided to do it as follows:
User adds a new wine and types the name of the country it comes from
While typing, the app searches in the apple maps database
The results from this search get displayed as suggestions, and when the user taps a suggestion, the app creates a Country object with all relevant information. The wine van only be saved when such an object is present
This works fine, except one thing: Apple maps returns anything, like restaurants, shops, etcetera, from anywhere.
My question: How can I specify WHAT I am looking for? I can only specify the region I'm searching in, which is irrelevant in my case. I would like to be able to tell apple maps to ONLY look for countries, regions, cities, whatever. Is this possible in a way? I have exhausted google for this and found no way thus far.
Going off what #Trevor said, I found rejecting results where either the title or subtitle have numbers yields pretty good results if you only want cities and towns.
Swift 4.1 code:
// Store this as a property if you're searching a lot.
let digitsCharacterSet = NSCharacterSet.decimalDigits
let filteredResults = completer.results.filter { result in
if result.title.rangeOfCharacter(from: digitsCharacterSet) != nil {
return false
}
if result.subtitle.rangeOfCharacter(from: digitsCharacterSet) != nil {
return false
}
return true
}
or more compactly:
let filteredResults = completer.results.filter({ $0.title.rangeOfCharacter(from: digitsCharacterSet) == nil && $0.subtitle.rangeOfCharacter(from: digitsCharacterSet) == nil })
The best solution we found was to filter our results using a comma in the result's title. This mostly returned only results that matched a city's format, e.g Detroit, MI, United States. We added this filter to the ones suggested by #Ben Stahl. Ben's solution filtered out edge cases where a comma formed part of the business' name.
This usually returns the correct result within three characters. To answer the OP's question, you could then parse this string by city, state or country to get the desired result.
For better results you could use the Google Places API.
func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
self.searchResults = completer.results.filter { result in
if !result.title.contains(",") {
return false
}
if result.title.rangeOfCharacter(from: CharacterSet.decimalDigits) != nil {
return false
}
if result.subtitle.rangeOfCharacter(from: CharacterSet.decimalDigits) != nil {
return false
}
return true
}
self.searchResultsCollectionView.reloadData()
}
I have worked with MapKit and don't believe you can do autocomplete assistance on user entries as they type the best solution I found is Google Place API autocomplete
iOS right now provides receiving geo-coordinates when sending a well-formatted address , or you can receive an address when sending a pair of coordinates. Or points of interest for locations names or coordinates.
There was a class added to MapKit in iOS 9.3 called MKLocalSearchCompleter which helps with autocompletion. You can filter what is returned by using 'MKSearchCompletionFilterType' but that isn't the most extensive and might not fully help with your situation. It does return cities and countries as results but it also returns businesses when I've used it.
One possible option is to filter the returned results again on the app side and exclude all results that have a numeric character in them.
func setupCompleter() {
self.searchCompleter = MKLocalSearchCompleter()
self.searchCompleter?.delegate = self
self.searchCompleter?.filterType = .locationsOnly
self.searchCompleter?.queryFragment = "Bordeaux"
}
func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
print("Results \(completer.results)")
// Do additional filtering on results here
}
In addition to Allan's answer, I've found that if you filter by the subtitle property of a MkLocalSearchCompletion object, you can remove the business entries.

many to many in redbeanphp is not full

I've created bean called user
$user = = R::dispense('user');
$user->sharedInstrument = $instruments;
And create an instrument where the owner is a user and many users can view it
$instrument = R::dispense('instrument');
$instrument->sharedUser = $users;
$instrument->owner = $owner;
The problem is when I load an instrument $instrument->sharedUser seems to only consist of the owner. Is there a way to get around this other than using R::related($instrument,'user')?
Found out how to do it use preload with an alias.
R::preload($instrument,array('sharedUser'=>'user'));

How to get/set the bonding box in google map?

How can I get/set the bonding box of a Google map? I know how to create map using center and zoom, but I need a way to save the view of map based on its boxing and the recreate the same view later using the map bonds (NE and SW of map)
Any idea how I can do this?
I am using MVC 3.
You want to use the map.getBounds() function which returns a LatLngBounds object. From this you can then use getNorthEast() and getSouthWest() to get the coordinates you want.
var bounds = map.getBounds();
var NE = bounds.getNorthEast();
var SW = bounds.getSouthWest();
If you need those LatLng objects to then be strings (for inserting to your DB or writing to a cookie or whatever), just use the toString() function on them.
strNE = NE.toString();
strSW = SW.toString();
So let's assume you write these to a cookie or use Ajax to write these to your DB. Once you get them out of the cookie/DB later, you can then just use those for setting the center of the map:
bounds = new google.maps.LatLngBounds(SW, NE);
map.fitBounds(bounds); // or maybe try panToBounds()
All these functions are documented here: https://developers.google.com/maps/documentation/javascript/reference

Audience Targeting in FullTextSqlQuery

I am trying to perform a search for documents within a SharePoint site, but I need to apply audience targeting to the results before they are displayed to the user.
I am however struggling to either (a) retrieve the target audience settings within the original query...
using (SPSite site = new SPSite(SPContext.Current.Site.ID)) {
using (FullTextSqlQuery fullText = new FullTextSqlQuery(site)) {
fullText.QueryText = #"select Title, Path, Description, TargetAudience from scope() where ((""scope"" = 'All Sites'))"
+ #" and IsDocument = 1 and freetext(*, '{0}')";
fullText.QueryText = string.Format(fullText.QueryText, this.documentFilter.AllOfTheseWords);
fullText.ResultTypes = ResultType.RelevantResults;
ResultTableCollection resultTableCollection = fullText.Execute();
allofTheseWords = new DataTable();
if (resultTableCollection.Exists(ResultType.RelevantResults)) {
allofTheseWords.Load(resultTableCollection[ResultType.RelevantResults], LoadOption.OverwriteChanges);
}
}
}
or (b) retrieve the list item id (guid) from within the original query so that I can then tie up each result to the original list item (and therefore apply the audience targeting using the list item.
Any suggestions?
I eventually found a way to retrieve the original list item based upon the URL returned from the full text query and then apply the audience targeting test to the list item.

Resources