Detect Collisions and reposition callouts
Opened this issue · 22 comments
I haven't checked out Yelp yet - but just an idea, what if we always had the closest to the centre at the foreground using z-indexing on the CALayer?
I have a feeling the altitude is a little broken too so will need to confirm this, and if so open an issue.
I think the z-index would be a great idea - just to verify that the closest is in the front. Basically, if two objects are going to collide, they stack them on op of each other.
The data I'm using doesn't have altitude data associated with it, so i'm not sure I can test that.
So getting back to this... I've got live data to test now. I think that because of line 510 on AugmentedRealityController.m sometimes locations that are further away get set in front of locations that are closer.
Here's an example. You can see that the 2.07mile marker is on top of the 1.19 mile marker.
Ideally, I'd like to see there be a variation in the y-positioning of the markers based on distance. Here's a mockup i threw together:
Hey guys, it looks like Yelp! stacks the POIs on top of each other, but an app called Wikitude takes nearby POI's and bundles them together. The user taps the bundle it "expands out" (see screenshots)
What is elevation supposed to? I have created several coordinates and set them to different inclinations as shown below but I see no difference in the view. Am I doing something wrong?
tempCoordinate.inclination = M_PI/30;
Whatever gets implemented to help show bunched up points would be AWESOME guys, it's a great project!
POI - Point of interest in Lat and Long
Thanks for the input, Jonathan.
I actually have it implemented in my app as-is, but would love to see it get better. I haven't had a lot of time to hack on it myself.
Is your implementation (I'm assuming what you have above in your post) available for download?
I've got some uncommitted changes to the arkit library (don't want rotation in my app). I'll try and throw it together and commit it to my fork.
Here's the project: https://github.com/markrickert/WSCrime but it's in RubyMotion. So you'll need that to compile it. You can also get it in the app store here: https://itunes.apple.com/us/app/winston-salem-crime-map/id472546582?mt=8
Email me through my contact form on my website - http://mohawkapps.com and i'll shoot you over a promo code... unless you want to give me $0.99 :)
Hey,
I like the idea of stacking them together but that would cause problems with the second issue: elevation. I could either:
- Include an option to either stack "close" POIs
- Overlap and have elevation working?
Which do you reckon would work best?
Thanks for the input!
@markrickert I just purchased your app, I am working on a virtual tours app of my college/wildlife reserve up here and your app really looks helpful to view the source on. Unfortunately I'm so far away that all the markers are bunched into one spot :P I'll send you an email shortly.
@a1phanumeric I think removing the overlap would be the biggest benefit to the application (I push to a new new after touching a marker) and not being able to see what I'm pressing is a little frustrating. Is there a way to get elevation working and if one marker can detect if another marker is on top of it (stack them together) ?
@jchri853 if you have rubymotion and can compile my application, you can artificially set your location so that they're not all bunched up in one direction (i no longer live in that city so I have to do that as well)
In AugmentedReailtyController.m
change this method:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
[self setCenterLocation:newLocation];
[[self delegate] didUpdateLocation:newLocation];
}
to this:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
CLLocation *temporaryLocation = [[CLLocation alloc] initWithLatitude:36.0997 longitude:-80.2444];
[self setCenterLocation:temporaryLocation];
[[self delegate] didUpdateLocation:newLocation];
}
Then run rake clean && rake device
(since the app can't simulate motion and rotation in the simulator) and you'll be artificially placed smack dab in the middle of Winston-salem and you should see the markers all around you.
I'll take a swing at it (I have only been in the Objectice C/xCode world for about 7 weeks now) would using your xcode fork include all the changes to the AR view from your app?
Looks like I would have to buy Rubymotion
I'll update everything right now and I'll let you know when it's all updated.
Also, you'll need to purchase RubyMotion in order to compile my app since it's written in ruby and not Obj-C. http://www.rubymotion.com/
Ok much appreciated, I'll wait on the RubyMotion
I've pushed up my changes here: https://github.com/markrickert/iPhone-AR-Toolkit/tree/wscrime-changes
These are just tweaks for my production implementation.
And good call on RubyMotion... you probably don't want to delve into that until you've got a bit more understanding about the CocoaTouch APIs and iOS applications in general.
ok thanks!
@a1phanumeric Hey! Any luck on your end for fixing the overlay issue?
@a1phanumeric Did you get any luck to solve this overlay location issue ?
I found a small solution
in - (void)updateLocations {
(AugmentedRealityController.m)
I wrote this code:
if([ item distanceFromOrigin] <= (_radarRange*1000)/10){
scaleFactor = 1.0;
[markerView setFrame:CGRectMake(loc.x - width / 2.0, loc.y, width, height)];
[markerView setNeedsDisplay];
}
else {
scaleFactor = 0.5;
[markerView setFrame:CGRectMake(loc.x - width / 100.0, loc.y-50, width, height)];
[markerView setNeedsDisplay];
}
Hi,
Is the issue been resolved ?
I have solve the problem of the callout collision made some little bit changes in your code and the your problem will be solve .
- In AugmentedRealityViewController there is updateLocations method, go into if condition and
if (!([markerView superview])) {
[[self displayView] insertSubview:markerView atIndex:1];
[self listSubviewsOfView:markerView]; // retrive the subviews from the markerview which is display on the camera screen...
}
this condition is updatelocation method and i call the "listSubviewsOfView" method, that is used for retriving subview from superView.
-
(void)listSubviewsOfView:(UIView *)view {
// Get the subviews of the view
NSArray *subviews = [view subviews];
// Return if there are no subviews
if ([subviews count] == 0) return;for (UIView _subview in subviews) {
if ([subview isKindOfClass:[UIImageView class]]) {
UIImageView *myLabel = (UIImageView *)subview;
myLabel.clipsToBounds = YES;
if (myLabel.tag == 1)
{
numberOfImageView++;
CGRect rect = myLabel.frame;
rect.origin.y = 0+numberOfImageView_50;
myLabel.frame = rect;
}
}
// List the subviews of subview
[self listSubviewsOfView:subview];
}
}
there is variable numberOfImageView. declare in .h file
int numberOfImageView;
and do one thing in else condition of the updateLocation Method , set the "numberOfImageView" to zero.
else
if ([markerView superview])
{
[markerView removeFromSuperview];
numberOfImageView =0;
}
then compile and run your code problem will be solve..
Add in updateLocations of AugmentedRealityController.m :-
int totalDisplayed=0;
for (ARGeoCoordinate *item in [self coordinates]) {
UIView *markerView = [item displayView];
if ([self shouldDisplayCoordinate:item]) {
CGPoint loc = [self pointForCoordinate:item];
CGFloat scaleFactor = SCALE_FACTOR;
if ([self scaleViewsBasedOnDistance])
scaleFactor = scaleFactor - [self minimumScaleFactor]*([item radialDistance] / [self maximumScaleDistance]);
float width = [markerView bounds].size.width * scaleFactor;
float height = [markerView bounds].size.height * scaleFactor;
int offset = totalDisplayed%2 ? totalDisplayed*25 : -totalDisplayed*25;
[markerView setFrame:CGRectMake(loc.x - width / 2.0, loc.y - (height / 2.0) + offset, width, height)];
totalDisplayed ++;
//[markerView setFrame:CGRectMake(loc.x - width / 2.0, loc.y, width, height)];
[markerView setNeedsDisplay];
if ([item distanceFromOrigin]>0) {
float difference = [item distanceFromOrigin]-prevLoc;
if ((difference>0 &&difference<200) || ( difference < 0 && difference>(-200))) {
[markerView setFrame:CGRectMake(loc.x - width / 2.0, loc.y - (height / 2.0) + offset, width, height)];
totalDisplayed ++;
}
prevLoc = [item distanceFromOrigin];
}
CATransform3D transform = CATransform3DIdentity;
// Set the scale if it needs it. Scale the perspective transform if we have one.
if ([self scaleViewsBasedOnDistance])
transform = CATransform3DScale(transform, scaleFactor, scaleFactor, scaleFactor);
if ([self rotateViewsBasedOnPerspective]) {
transform.m34 = 1.0 / 300.0;
}
[[markerView layer] setTransform:transform];
//if marker is not already set then insert it
if (!([markerView superview])) {
[[self displayView] insertSubview:markerView atIndex:1];
}
}
else {
if ([markerView superview]){
[markerView removeFromSuperview];
}
}