What does MkCoordinateRegion region = {{0,0}, {0,0}}; - latitude-longitude

I am new to xcode, and am trying to create an annotation. The annotation works fine, its just that when the app opens the map is focused on europe! Should I change the coordinates to my latitude and longitude of my annotation location, and how do I do that? Beczuse there are four 0's instead of two! {{0,0},{0,0}} how do i configure latitude and longutude into that?

A MKCoordinateRegion has two fields: 1) center, 2) span.
You should use the MKCoordinateRegionMake macro for this:
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(35, -90); // pick desired values
MKCoordinateSpan span = MKCoordinateSpanMake(100, 100); // pick desired values
MKCoordinateRegion region = MKCoordinateRegionMake(center, span);
The syntax:
MKCoordinateRegion region = { { 0, 0 }, { 0, 0 } };
is a shortcut from C for initializing the struct values. The first pair is for the center field and the second pair is for the span field.

Related

Determine whether a CLLocationCoordinate2D is within a defined region (bounds)?

I am trying to find a simple method to determine whether a CLLocationCoordinate2D lies within the boundaries of an arbitrary shape defined by a series of other CLLocationCoordinate2D's. The shapes may be large enough that great-circle paths need to be considered.
CL used to have a circular region and the containsCoordinate: call to test against, but this has been deprecated in iOS7 and the dox do not contain a hint of what might replace it. I cannot find any other examples, notably one that works on polygons.
There are many similar questions here on SO, but they are not related to iOS specifically, and again, I can't seem to find one that works generally on great-circle polys.
Here's an example (using Algonquin Provincial Park) of an approach that may work for you.
To use CGPathContainsPoint for this purpose, an MKMapView is not required.
Nor is it necessary to create an MKPolygon or even to use the CLLocationCoordinate2D or MKMapPoint structs. They just make the code easier to understand.
The screenshot below was created from the data only for illustration purposes.
int numberOfCoordinates = 10;
//This example draws a crude polygon with 10 coordinates
//around Algonquin Provincial Park. Use as many coordinates
//as you like to achieve the accuracy you require.
CLLocationCoordinate2D algonquinParkCoordinates[numberOfCoordinates];
algonquinParkCoordinates[0] = CLLocationCoordinate2DMake(46.105, -79.4);
algonquinParkCoordinates[1] = CLLocationCoordinate2DMake(46.15487, -78.80759);
algonquinParkCoordinates[2] = CLLocationCoordinate2DMake(46.16629, -78.12095);
algonquinParkCoordinates[3] = CLLocationCoordinate2DMake(46.11964, -77.70896);
algonquinParkCoordinates[4] = CLLocationCoordinate2DMake(45.74140, -77.45627);
algonquinParkCoordinates[5] = CLLocationCoordinate2DMake(45.52630, -78.22532);
algonquinParkCoordinates[6] = CLLocationCoordinate2DMake(45.18662, -78.06601);
algonquinParkCoordinates[7] = CLLocationCoordinate2DMake(45.11689, -78.29123);
algonquinParkCoordinates[8] = CLLocationCoordinate2DMake(45.42230, -78.69773);
algonquinParkCoordinates[9] = CLLocationCoordinate2DMake(45.35672, -78.90647);
//Create CGPath from the above coordinates...
CGMutablePathRef mpr = CGPathCreateMutable();
for (int p=0; p < numberOfCoordinates; p++)
{
CLLocationCoordinate2D c = algonquinParkCoordinates[p];
if (p == 0)
CGPathMoveToPoint(mpr, NULL, c.longitude, c.latitude);
else
CGPathAddLineToPoint(mpr, NULL, c.longitude, c.latitude);
}
//set up some test coordinates and test them...
int numberOfTests = 7;
CLLocationCoordinate2D testCoordinates[numberOfTests];
testCoordinates[0] = CLLocationCoordinate2DMake(45.5, -78.5);
testCoordinates[1] = CLLocationCoordinate2DMake(45.3, -79.1);
testCoordinates[2] = CLLocationCoordinate2DMake(45.1, -77.9);
testCoordinates[3] = CLLocationCoordinate2DMake(47.3, -79.6);
testCoordinates[4] = CLLocationCoordinate2DMake(45.5, -78.7);
testCoordinates[5] = CLLocationCoordinate2DMake(46.8, -78.4);
testCoordinates[6] = CLLocationCoordinate2DMake(46.1, -78.2);
for (int t=0; t < numberOfTests; t++)
{
CGPoint testCGPoint = CGPointMake(testCoordinates[t].longitude, testCoordinates[t].latitude);
BOOL tcInPolygon = CGPathContainsPoint(mpr, NULL, testCGPoint, FALSE);
NSLog(#"tc[%d] (%f,%f) in polygon = %#",
t,
testCoordinates[t].latitude,
testCoordinates[t].longitude,
(tcInPolygon ? #"Yes" : #"No"));
}
CGPathRelease(mpr);
Here are the results of the above test:
tc[0] (45.500000,-78.500000) in polygon = Yes
tc[1] (45.300000,-79.100000) in polygon = No
tc[2] (45.100000,-77.900000) in polygon = No
tc[3] (47.300000,-79.600000) in polygon = No
tc[4] (45.500000,-78.700000) in polygon = Yes
tc[5] (46.800000,-78.400000) in polygon = No
tc[6] (46.100000,-78.200000) in polygon = Yes
This screenshot is to illustrate the data only (actual MKMapView is not required to run the code above):
Anna's solution converted to Swift 3.0:
extension CLLocationCoordinate2D {
func contained(by vertices: [CLLocationCoordinate2D]) -> Bool {
let path = CGMutablePath()
for vertex in vertices {
if path.isEmpty {
path.move(to: CGPoint(x: vertex.longitude, y: vertex.latitude))
} else {
path.addLine(to: CGPoint(x: vertex.longitude, y: vertex.latitude))
}
}
let point = CGPoint(x: self.longitude, y: self.latitude)
return path.contains(point)
}
}

Get/Calculate zoom level from lat/long delta

is there any way to get Google Maps zoom level calculate from lat/long delta values from the Google Maps SDK for iOS?
or maybe calculate it via Objective C ?
thanks
Perhaps this is what you are looking for.
From GMSCoordinateBounds.h:
/**
* Inits the northEast and southWest bounds corresponding
* to the rectangular region defined by the two corners.
*
* It is ambiguous whether the longitude of the box
* extends from |coord1| to |coord2| or vice-versa;
* the box is constructed as the smaller of the two variants, eliminating the
* ambiguity.
*/
- (id)initWithCoordinate:(CLLocationCoordinate2D)coord1
coordinate:(CLLocationCoordinate2D)coord2;
It can be used to set the camera to fit the bounds with the appropriate zoom level.
CLLocationCoordinate2D coord1 = CLLocationCoordinate2DMake(-45.43563456, -23.32543646);
CLLocationCoordinate2D coord2 = CLLocationCoordinate2DMake(-21.32145323, -12.32455435);
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithCoordinate:coord1 coordinate:coord2];
[mapView moveCamera: [GMSCameraUpdate fitBounds:bounds]];
if somebody is searching it for swift, i also needed it for autocompletion, you can set bounds (example for south west germany near freiburg and stuttgart):
let coord1 : CLLocationCoordinate2D = CLLocationCoordinate2DMake(48.10009, 8.206787);
let coord2 : CLLocationCoordinate2D = CLLocationCoordinate2DMake(48.10009, 8.206787);
let bounds = GMSCoordinateBounds(coordinate: (coord1), coordinate: (coord2))
placesClient?.autocompleteQuery(autoQuery, bounds: bounds, filter: filter, callback: { (results, error: NSError?) -> Void in and so on.......

How can I expand a MKMapRect by a fixed percentage?

I want to get a result MKMapRect that's 10-20% larger in all directions than the current visibleMapRect. If this were a CGRect I'd use CGRectInset with negative x and y values, providing me with an inverse inset (i.e. a larger rect). Unfortunately, MKMapInset doesn't support negative inset values so it's not quite that easy.
This might be easier if the the values for the map rect were recognizable units but the origin x and y values are on the order of 4.29445e+07, and the width/height is 2500-3000.
I'm about 10 seconds from writing a category to do this manually but I wanted to make sure I wasn't missing something first. Is there an easier way to expand MKMapRect?
In iOS7, rectForMapRect: and mapRectForRect: has been deprecated and now are part of the MKOverlayRenderer class. I'd rather recommend to use the MapView mapRectThatFits: edgePadding: methods. Here is a sample code :
MKMapRect visibleRect = self.mapView.visibleMapRect;
UIEdgeInsets insets = UIEdgeInsetsMake(50, 50, 50, 50);
MKMapRect biggerRect = [self.mapView mapRectThatFits:visibleRect edgePadding:insets];
latest Swift for 2017...
func updateMap() {
mkMap.removeAnnotations(mkMap.annotations)
mkMap.addAnnotations(yourAnnotationsArray)
var union = MKMapRectNull
for p in yourAnnotationsArray {
// make a small, say, 50meter square for each
let pReg = MKCoordinateRegionMakeWithDistance( pa.coordinate, 50, 50 )
// convert it to a MKMapRect
let r = mkMapRect(forMKCoordinateRegion: pReg)
// union all of those
union = MKMapRectUnion(union, r)
// probably want to turn on the "sign" for each
mkMap.selectAnnotation(pa, animated: false)
}
// expand the union, using the new #edgePadding call. T,L,B,R
let f = mkMap.mapRectThatFits(union, edgePadding: UIEdgeInsetsMake(70, 0, 10, 35))
// NOTE you want the TOP padding much bigger than the BOTTOM padding
// because the pins/signs are actually very tall
mkMap.setVisibleMapRect(f, animated: false)
}
What about converting the visibleMapRect to a CGRect with rectForMapRect:, getting a new CGRect with CGRectInset and then converting it back to a MKMapRect with mapRectForRect:?
Simple and clean solution for Xcode 10+, Swift 4.2
Just set the edge insets for the maps' margins like this:
self.mapView.layoutMargins = UIEdgeInsets(top: 8, right: 8, bottom: 8, left: 8)
self.mapView.showAnnotations(map.annotations, animated: true)
Please let us know if it works for you.
Refined and corrected user2285781's answer for Swift 4:
// reference: https://stackoverflow.com/a/15683034/347339
func MKMapRectForCoordinateRegion(region:MKCoordinateRegion) -> MKMapRect {
let topLeft = CLLocationCoordinate2D(latitude: region.center.latitude + (region.span.latitudeDelta/2), longitude: region.center.longitude - (region.span.longitudeDelta/2))
let bottomRight = CLLocationCoordinate2D(latitude: region.center.latitude - (region.span.latitudeDelta/2), longitude: region.center.longitude + (region.span.longitudeDelta/2))
let a = MKMapPointForCoordinate(topLeft)
let b = MKMapPointForCoordinate(bottomRight)
return MKMapRect(origin: MKMapPoint(x:min(a.x,b.x), y:min(a.y,b.y)), size: MKMapSize(width: abs(a.x-b.x), height: abs(a.y-b.y)))
}
// reference: https://stackoverflow.com/a/19307286/347339
// assuming coordinates that create a polyline as well as a destination annotation
func updateMap(coordinates: [CLLocationCoordinate2D], annotation: MKAnnotation) {
var union = MKMapRectNull
var coordinateArray = coordinates
coordinateArray.append(annotation.coordinate)
for coordinate in coordinateArray {
// make a small, say, 50meter square for each
let pReg = MKCoordinateRegionMakeWithDistance( coordinate, 50, 50 )
// convert it to a MKMapRect
let r = MKMapRectForCoordinateRegion(region: pReg)
// union all of those
union = MKMapRectUnion(union, r)
}
// expand the union, using the new #edgePadding call. T,L,B,R
let f = mapView.mapRectThatFits(union, edgePadding: UIEdgeInsetsMake(70, 35, 10, 35))
// NOTE you want the TOP padding much bigger than the BOTTOM padding
// because the pins/signs are actually very tall
mapView.setVisibleMapRect(f, animated: false)
}

JavaFX 2 Slider for circular knob and snap to value

based on the volume knob from this example, http://fxexperience.com/2012/01/fun-javafx-2-0-audio-player/
How would you make a volume knob that snaps to particular angle value, every 15 or 30 degree for example ? Thanks for any hint.
What i did is redefine rotateKnob in subclass and set the angle in this manner for the slider to snap at values 180, 120, 60, 0, -180, -160, -120, -60 :
Slider s = getSkinnable();
double zeroOneValue = (s.getValue() - s.getMin()) / (s.getMax() - s.getMin());
double angle = minAngle + ((maxAngle - minAngle) * zeroOneValue);
int angleMod = (int) (angle % 60);
double val;
if (angleMod == 0) {
val = (int) angle;
} else if (angleMod > (60 / 2)) {
val = (int) angle - angleMod;
} else {
val = (int) angle - angleMod + 60;
}
You don't need to do anything special. Just make use of the "snapToTicks" property. In the main class, after the volume knob is defined, put this code:
volumeKnob.setMinorTickCount(0);
volumeKnob.setMajorTickUnit(1.0/14.0);
volumeKnob.snapToTicksProperty().set(true);
The numbers here are based on the fact that there are 14 "dots" around the volume knob. This code will make sure that you can only set the volume to one of those dots.
#Enwired has a good answer. you need a different graphical resource to change the number of dots. but that is not a part of what makes the angle between each tick around the rotary control.
just as he divided the circle into 1/14's, you can choose to divide it into 60 degree slices by 60.0/360.0 or 1.0/6.0.

Getting minimum number of MKMapRects from a MKPolygon

So I have a function that takes two MKMapRect's and the second intersects with the first one. So the function creates an MKPolygon that is the first rect without the intersecting parts:
-(void) polygons:(MKMapRect)fullRect exclude:(MKMapRect)excludeArea{
NSLog(#"Y is: %f height: %f",excludeArea.origin.y,excludeArea.size.height);
double top = excludeArea.origin.y - fullRect.origin.y;
double lft = excludeArea.origin.x - fullRect.origin.x;
double btm = (fullRect.origin.y + fullRect.size.height) - (excludeArea.origin.y + excludeArea.size.height);
double rgt = (fullRect.origin.x + fullRect.size.width) - (excludeArea.origin.x + excludeArea.size.width);
double ot = fullRect.origin.y, it = (ot + top);
double ol = fullRect.origin.x, il = (ol + lft);
double ob = (fullRect.origin.y + fullRect.size.height), ib = (ob - btm);
double or = (fullRect.origin.x + fullRect.size.width), ir = (or - rgt);
MKMapPoint points[11] = {{ol,it}, {ol,ot}, {or,ot}, {or,ob}, {ol,ob}, {ol,it}, {il,it}, {ir,it}, {ir,ib}, {il,ib}, {il,it}};
MKPolygon *polygon = [MKPolygon polygonWithPoints:points count:11];
}
And my question is now how do I get the minimum number of MKMapRects from this MKPolygon? I have done some googling as well as looking through the forum but havn't found anything.
EDIT:
So the goal is the following:
I have a MKMapRect rect1, then I have a list of rectangles, rectList, which is MKMapRects intersecting with rect1 and what I want to do is create a rectilinear MKPolygon of rect1, remove the surface of all MKMapRects in rectList from rect1 and then create the minimum number of MKMaprects from the created rectilinear MKPolygon.
Right now the problem is the following: I am able to create a polygon when removing one MKMapRect from rect1 but I dont know how to remove the following maprects from rect1 and I dont know how to extract the minimum set of MkMapRects from the polygon created.
Best regards
Peep
I'm not sure if this is what you're looking for or if I understand the question fully, but if all you need to know is the minimum number of rectangles in a polygon that's created by subtracting one rectangle from another you should be able to do it by checking the number of corner points in the second rectangle that are contained in the first rectangle. In pseudo code:
int minNumRects(MKRect r1, MKRect r2) {
int numPointsContained = 0;
for (Point p in r2) {
if (MKMapRectContainsPoint(r1, p)) {
numPointsContained++;
}
}
if (numPointsContained == 1) {
return 2;
} else if (numPointsContained == 2) {
return 3;
} else if (numPointsContained == 4) {
return 4;
} else {
return 0;
}
}
P.S. - This assumes that the rectangles are axis-aligned but as far as I know that's the case with MKRects