AR - Annotation to a fix Location - iphone

I made an augmented reality Application, there I have an arrow points on the z-axis to the location (longitude & latitude) of one shop now I'd like to make an annotation in the "sky" which points direct on the shop coordinate. I found some projects on github, like iPhone-AR-Toolkit, but I don't understand this.
Is there a simple way to add such an annotation above the location?
Edit:
After searching a lot I find a pdf document in de web, which contains some code for that what I want, but the problem is, I don't understand it and it doesn't do the things right.
The Code:
// Artificial Horizon - compensate for rotation along x-axis
// need to know the field of view of the camera to find horizon position inside of camera view
// about 53 degrees vertical and 37.5 degrees horizontal
// for directional Horizon - artificial horizon pegged to a specific cardinal direction (North)
// in (void)viewDidAppear
// Load the image to show in the overlay
UIImage *overlayGraphic = [UIImage imageNamed:#"Punkt.png"];
overlayGraphicView = [[UIImageView alloc] initWithImage:overlayGraphic];
overlayGraphicView.frame = CGRectMake(30, 100, 50, 50);
[self addSubview:overlayGraphicView];
[[UIAccelerometer sharedAccelerometer] setDelegate:self];
locationManager = [[CoreLocationMangager alloc] init];
[locationManager setDelegate:self];
[locationManager startUpdatingHeading];
- (void) updateUI {
CGPoint overlayCenter = [overlayGraphicView center];
overlayCenter.y = 240.0 - 537.8 * sin(vertAngle);
overlayCenter.x = 160.0 - 497.8 * sin((magCompassHeadingInDeg) * (M_PI / 180.0));
[overlayGraphicView setCenter:overlayCenter];
overlayGraphicView.transform = CGAffineTransformMakeRotation(angle);
}
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
vertAngle = -atan2(acceleration.y, acceleration.z) - M_PI/2.0;
vertAngleInDeg = vertAngle * 180.0f/M_PI;
angle = -atan2(acceleration.y, acceleration.x) - M_PI/2.0;
angleInDeg = angle * 180.0f / M_PI;
[self updateUI];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
magCompassHeadingInDeg = [newHeading magneticHeading];
[self updateUI];
}
There is an image View is added to a camera overlay, and this image should point to North - but my problem is it also points to South. How can i fix that? And can anybody explain me thr values from the overlayCenter.y and .x - I don't understand them.

You need to Specify an altitude to specify the height from sea-level that is z-axis.
Mixare SDK will allow you to specify and load your POI's with latitude, longitude and altitude.
You can refer it from here
I have used this sdk and it works great and allows you specify Altitude.
Hope this helps:)

Related

Device motion detection in iOS

I want to detect the device motion like Panorama i.e. motion from my left side to Right side.
I tried with the accelerometer but i can't able to do it.
I like to move one image in a straight line as the device move.
My code is as follow:
- (void)viewDidLoad
{
[super viewDidLoad];
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:1/60];
[[UIAccelerometer sharedAccelerometer]setDelegate:self];
}
pragma mark - Accelerometer Delegate
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:
(UIAcceleration *)acceleration{
valueX = acceleration.x*100.0;
valueY = acceleration.y*30.0;
float newX = (float)(ball.center.x + valueX);
CGPoint newCenter = CGPointMake(newX, 50);
ball.center = newCenter;
}
How can I do this? Because there are many apps who uses this.
Please guide me.
Thanks..

Match the zoom/bounds of a MapKit map with the zoom/bounds of a RouteMe map

EDIT: I believe my issue is that this code works for integer zoom levels, but I would like it to work for float zoom levels.
I have an iOS app in which the user can switch between a RouteMe-based map and a MapKit-based map.
When they switch sources, I would like to be able to show the exact same area in one as in the other. However, I can't figure out how to make them match because RouteMe and MapKit use different data structures to describe the map bounds.
Here is some code that gets it to be somewhat close, but it's not exact. This code comes from: http://troybrant.net/blog/2010/01/set-the-zoom-level-of-an-mkmapview/
I'm not sure whether this code should be fixed, or possibly I am overlooking a much easier solution. The code executes starting with the last method listed:
#define MERCATOR_OFFSET 268435456
#define MERCATOR_RADIUS 85445659.44705395
#pragma mark -
#pragma mark Map conversion methods
- (double)longitudeToPixelSpaceX:(double)longitude {
return round(MERCATOR_OFFSET + MERCATOR_RADIUS * longitude * M_PI / 180.0);
}
- (double)latitudeToPixelSpaceY:(double)latitude {
return round(MERCATOR_OFFSET - MERCATOR_RADIUS * logf((1 + sinf(latitude * M_PI / 180.0)) / (1 - sinf(latitude * M_PI / 180.0))) / 2.0);
}
- (double)pixelSpaceXToLongitude:(double)pixelX {
return ((round(pixelX) - MERCATOR_OFFSET) / MERCATOR_RADIUS) * 180.0 / M_PI;
}
- (double)pixelSpaceYToLatitude:(double)pixelY {
return (M_PI / 2.0 - 2.0 * atan(exp((round(pixelY) - MERCATOR_OFFSET) / MERCATOR_RADIUS))) * 180.0 / M_PI;
}
- (MKCoordinateSpan)coordinateSpanWithMapView:(MKMapView *)mapView
centerCoordinate:(CLLocationCoordinate2D)centerCoordinate
andZoomLevel:(NSInteger)zoomLevel {
// convert center coordiate to pixel space
double centerPixelX = [self longitudeToPixelSpaceX:centerCoordinate.longitude];
double centerPixelY = [self latitudeToPixelSpaceY:centerCoordinate.latitude];
// determine the scale value from the zoom level
NSInteger zoomExponent = 20 - zoomLevel;
double zoomScale = pow(2, zoomExponent);
// scale the map’s size in pixel space
CGSize mapSizeInPixels = mapView.bounds.size;
double scaledMapWidth = mapSizeInPixels.width * zoomScale;
double scaledMapHeight = mapSizeInPixels.height * zoomScale;
// figure out the position of the top-left pixel
double topLeftPixelX = centerPixelX - (scaledMapWidth / 2);
double topLeftPixelY = centerPixelY - (scaledMapHeight / 2);
// find delta between left and right longitudes
CLLocationDegrees minLng = [self pixelSpaceXToLongitude:topLeftPixelX];
CLLocationDegrees maxLng = [self pixelSpaceXToLongitude:topLeftPixelX + scaledMapWidth];
CLLocationDegrees longitudeDelta = maxLng - minLng;
// find delta between top and bottom latitudes
CLLocationDegrees minLat = [self pixelSpaceYToLatitude:topLeftPixelY];
CLLocationDegrees maxLat = [self pixelSpaceYToLatitude:topLeftPixelY + scaledMapHeight];
CLLocationDegrees latitudeDelta = -1 * (maxLat - minLat);
// create and return the lat/lng span
MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
return span;
}
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
zoomLevel:(NSUInteger)zoomLevel
animated:(BOOL)animated {
// use the zoom level to compute the region
MKCoordinateSpan span = [self coordinateSpanWithMapView:self
centerCoordinate:centerCoordinate
andZoomLevel:zoomLevel];
MKCoordinateRegion region = MKCoordinateRegionMake(centerCoordinate, span);
// set the region like normal
[self setRegion:region animated:animated];
}
Unfortunately this is a limitation of the Google Maps API, which only accepts integer values when setting the map's zoom level: Apple's MapKit code is calling the underlying Google Maps APIs when you set a MKMapView's displayed area, and the result – no matter which MapKit method you use to set the area – is a map that's zoomed out to the nearest integer zoom level.
Troy Brant's code takes you full circle, and puts a layer above the MapKit APIs that allows you to set the zoom level directly… but ultimately you don't have precise control over the area displayed by an MKMapView, unless the zoom level of your desired map happens to be an integer.
Several variations on this question have appeared on Stack Overflow (e.g., MKMapView setRegion "snaps" to predefined zoom levels? and MKMapView show incorrectly saved region), but so far no one has come up with a programmatic way to make a map with a non-integer zoom level, and I suspect it'd take cooperation between Google and Apple to ever make it happen.

iphone accelerometer: problem rotating image

Hi everyone I'm french so scue me for my english. So I have a problem.What I'm doing is when I turn device to left or right with accelerometer an image rotate in the opposite direction of the rotation of the device it create a cool effect but when I rotate the device with accelerometer the image is rotating but it is always trembling, vibrating the movement is not smooth. What can I do ? here is the code:
#import "QuartzCore/QuartzCore.h"
#define CONST_fps 100.
#define CONST_map_shift 0.05
#implementation MapViewRotationViewController
- (void)viewDidLoad {
[super viewDidLoad];
// accelerometer settings
[[UIAccelerometer sharedAccelerometer] setDelegate:self];
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / CONST_fps)];
}
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
static CGFloat ZZ = 0.;
CGFloat z = (atan2(acceleration.x, acceleration.y) + M_PI);
if (fabsf(ZZ - z) > CONST_map_shift)
{
viewToRotate.layer.transform = CATransform3DMakeRotation(ZZ=z, 0., 0., 10.);
}
}
#end
You need to do a trick that is called high pass filter. It filters trembling, only significant changes will pass.
You can google it, or search on StackOverflow. For example, here: How do you implement a Highpass filter for the IPhone accelerometer?

Calculate angle for rotation in Pie Chart

I want to rotate the image around its center point.The problem i am facing is i need to get the angle to calculate in touch moved event (i dont want to use multi touch).I am current using the below code
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
NSArray *allTouches = [touches allObjects];
gestureStartPoint = gestureMovedPoint;//i am getting the gestureStartPoint on touch began event
gestureMovedPoint = [[allTouches objectAtIndex:0] locationInView:[self superview]];
NSLog(#"gestureMovedPoint = %#",NSStringFromCGPoint(gestureMovedPoint));
}
CGFloat previousAngle = [self angleBetweenPoints:gestureStartPoint second11:gestureMovedPoint]; // atan2(gestureMovedPoint.y - gestureStartPoint.y, gestureMovedPoint.x - gestureStartPoint.x) * 180 / M_PI;
CGFloat currentAngle =atan2(self.transform.b, self.transform.a);//atan2(gestureMovedPoint.y - gestureStartPoint.y,gestureMovedPoint.x - gestureStartPoint.x) * 180 / M_PI;
CGFloat angleToRotate = currentAngle - previousAngle;
float xpoint = (((atan2((gestureMovedPoint.x - gestureStartPoint.x) , (gestureMovedPoint.y - gestureStartPoint.y)))*180)/M_PI);
CGAffineTransform transform = CGAffineTransformMakeRotation(angleToRotate-100);
self.transform = transform;
Kindly help me find the solution as i am stuck here and need to complete this application very soon as there is a dead line.
Thanks in advance
Glad I remember triginometry
-(void)degreesToRotateObjectWithPosition:(CGPoint)objPos andTouchPoint:(CGPoint)touchPoint{
float dX = touchPoint.x-objPos.x; // distance along X
float dY = touchPoint.y-objPos.y; // distance along Y
float radians = atan2(dY, dX); // tan = opp / adj
//Now we have to convert radians to degrees:
float degrees = radians*M_PI/360;
return degrees;
}
Once you have your nice method, just do this in the touch event method. (I forgot what it's called...)
CGAffineTransform current = view.transform;
[view setTransform:CGAffineTransformRotate(current, [self degreesTorotateObjectWithPosition:view.frame.origin andTouchPoint:[touch locationInView:parentView]]
//Note: parentView = The view that your object to rotate is sitting in.
This is pretty much all the code that you'll need.The math is right, but I'm not sure about the setTransform stuff. I'm at school writing this in a browser. You should be able to figure it out from here.
Good luck,
Aurum Aquila
Have to think at this. But I will prefer rotating the view with two touches. It will be much simpler.
I did struggle a bit with how to get a touch driven rotation, even more so because I want 100% understanding of the code I am using. So I ended up, after many failed attempts, with this:
- (CGFloat) pointToAngleFromCenter: (CGPoint) point {
// transform point to a self.center'ed origin based coordinate system
point.x = point.x - self.center.x ;
// ditto for y, but compensate for y going downwards to y going upwards
point.y = self.center.y - point.y ;
return ::atan2(point.y, point.x) ;
}
If anyone has a better name for this method, I'm all ears.
What it does is that it takes a point in parent view coordinates, remaps it relative to the center of the view (which is in parent view coordinate), and computes the angle between this remapped point and the axis [0X]. To do so, it normalizes y to the normal mathematical coordinates (y goes up when its value increases, not down), hence self.center.y - point.y and not the opposite.
Finally, in touchesMoved:
- (void) touchesMoved: (NSSet *) touches withEvent: (UIEvent *) event {
UITouch * touch = [touches anyObject] ;
CGFloat currA = [self pointToAngleFromCenter:[touch locationInView:self.superview]] ;
CGFloat prevA = [self pointToAngleFromCenter:[touch previousLocationInView:self.superview]] ;
// the current value of the rotation angle
CGFloat tranA = ::atan2(self.transform.b, self.transform.a) ;
// the angle difference between last touch and the current touch
CGFloat diffA = currA - prevA ;
// the new angle resulting from applying the difference
CGFloat angle = tranA - diffA ;
CGAffineTransform t = ::CGAffineTransformMakeRotation(angle) ;
self.transform = t ;
[self setNeedsDisplay] ;
}

iphone image not rotating properly aacording to location upon camera view

i am developing application which point towards the particular location, i have calculate angle between current coordinate to specific coordinate and my image is rotating by that difference but image rotation is fixed means when i change my direction the image is not moved it remain fix to specific postion, i want that the image should be moved aacording to the actual position where it is located(where we want to reach) thanks for the help in advance below is my code..
-(float) angleToRadians:(float) a {
return ((a/180)*M_PI);
}
- (float) getHeadingForDirectionFromCoordinate:(CLLocationCoordinate2D)fromLoc toCoordinate:(CLLocationCoordinate2D)toLoc
{
float fLat = [self angleToRadians:fromLoc.latitude];
float fLng = [self angleToRadians:fromLoc.longitude];
float tLat = [self angleToRadians:toLoc.latitude];
float tLng = [self angleToRadians:toLoc.longitude];
float result= atan2f(sin(tLng-fLng)*cos(tLat), cos(fLat)*sin(tLat)-sin(fLat)*cos(tLat)*cos(tLng-fLng));
return RadiansToDegrees(result);
}
- (void) scanButtonTouchUpInside {
UIImage *overlayGraphic = [UIImage imageNamed:#"GFI.jpg"];
overlayGraphicView = [[UIImageView alloc] initWithImage:overlayGraphic];
overlayGraphicView.frame = CGRectMake(50, 50, 50, 80);
[self addSubview:overlayGraphicView];
float angle =[self getHeadingForDirectionFromCoordinate:currentlocation toCoordinate:pointlocation];
if(angle < 0.0)
angle += 2*M_PI;
overlayGraphicView.transform=CGAffineTransformMakeRotation(angle);
}
Judging by the name of the method that is rotating the image: scanButtonTouchUpInside, I'm guessing that it is called only when a user hits a button. If it is only called once, I would expect the image to only rotate once, then remain fixed. In order to keep the image rotating, you need to put that code somewhere that is called repeatedly. A (cheap hack) way to test this would be to add this line to the end of your - (void)scanButtonTouchUpInside method:
[self performSelector:#selector(scanButtonTouchUpInside) withObject:nil afterDelay:0.25f];
This will make the method call fire repeatedly. One thing to note though: It seems that your calculation of the angle of rotation depends on a variable called currentLocation. This solution will only work if you are updating currentLocation appropriately.
EDIT:
Just a thought, you're currently calculating the angle of rotation based on the location of the device and the location of the destination. You're not taking into account compass bearing at all. Is this intentional? With this approach, your angle will never change unless the device actually moves. Any change in orientation will be ignored.