+ Reply to Thread
Results 1 to 8 of 8

Thread: AGSGeometryEngine, map not fully loaded

  1. #1
    Vasupree Ryser
    Join Date
    Apr 2012
    Posts
    5
    Points
    1
    Answers Provided
    0


    1

    Question AGSGeometryEngine, map not fully loaded

    Hello,

    I have a problem with AGSGeometryEngine, I have make the possibility to identify some room with an area selection. But it seems the map isn't fully loaded, when I click to the map, it's just the identify symbol it's appear but not my blue square. And after a while it's OK.

    Here is a part of my code :

    Code:
    AGSGeometryEngine *ge = [AGSGeometryEngine defaultGeometryEngine];
    AGSEnvelope *actualEnv = (AGSEnvelope *)[ge projectGeometry:self.mapView.visibleArea.envelope toSpatialReference:self.spaRef] ;
    
    double xLength = actualEnv.xmax - actualEnv.xmin;
    With this, the actualEnv.xmax has a 0.0 value. And after a while it's the good value.

    I have try to make this with the help of the forum :

    Code:
    //Previously in my method
    AGSEnvelope *visibleEnv = [[self.mapView.visibleArea.envelope copy] autorelease];
    AGSSpatialReference *spaRef = [[self.spaRef copy] autorelease];
    ...
    AGSGeometryEngine *ge = [AGSGeometryEngine defaultGeometryEngine];
    AGSEnvelope *actualEnv = (AGSEnvelope *)[ge projectGeometry:visibleEnv toSpatialReference:self.spaRef] ;
    
    double xLength = actualEnv.xmax - actualEnv.xmin;
    But it's not better.

    Thank you in advance for any help.
    Last edited by Vasu01; 04-26-2012 at 11:41 PM.

  2. #2
    Nimesh Jarecha

    Join Date
    Oct 2009
    Posts
    883
    Points
    489
    Answers Provided
    105


    0

    Default Re: AGSGeometryEngine, map not fully loaded

    Okay, let me ask you few questions before suggesting something...

    1. Where are you executing this code?
    2. Are you waiting for map to load before using the self.mapView.visibleArea.envelope and map's spatial reference in geometry engine?

    Regards,
    Nimesh

  3. #3
    Vasupree Ryser
    Join Date
    Apr 2012
    Posts
    5
    Points
    1
    Answers Provided
    0


    0

    Default Re: AGSGeometryEngine, map not fully loaded

    Thanks for your answer.

    1. I execute the code in the didClickAtPoint method. Then in the method I use a segmented control to switch between point search and area seach.
    2. No I don't wait, but I don't know how much time I must wait.

    Best regards.

  4. #4
    Nimesh Jarecha

    Join Date
    Oct 2009
    Posts
    883
    Points
    489
    Answers Provided
    105


    0

    Default Re: AGSGeometryEngine, map not fully loaded

    Could you please post a sample application so I can have a look?

    Regards,
    Nimesh

  5. #5
    Vasupree Ryser
    Join Date
    Apr 2012
    Posts
    5
    Points
    1
    Answers Provided
    0


    0

    Default Re: AGSGeometryEngine, map not fully loaded

    Sorry for the delay, I was away from my office this week.

    Here is the first part of the class for the display of the map.

    Code:
    #import "MapViewController.h"
    @implementation MapViewController
    ...
    
    // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
    - (void)viewDidLoad {
        [super viewDidLoad];
    	self.title = @"MapView";
    	
    	self.mapView.layerDelegate = self;
    	self.mapView.touchDelegate = self;
        self.mapView.calloutDelegate = self;
        
        self.visibleLayers = [NSMutableArray arrayWithObjects:[NSNumber numberWithInt:3],
                                              nil];
        isOSMDisplayed = YES;
        [self setupMapView:YES];
        isAreaSearch = NO;
        
        // zoom to UniNe (WKID 102100) -> OpenStreetMap
    	AGSEnvelope *env = [AGSEnvelope envelopeWithXmin:773466.697310 ymin:5941903.815693 xmax:773768.071705 ymax:5942295.602407 spatialReference:self.mapView.spatialReference];
    	
        [self.mapView zoomToEnvelope:env animated:YES];
         
    	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(respondToZoomlevelChange:) name:@"MapDidEndZooming" object:nil];
    
        // setup the variables for the ResultsViewController
        entryOrder = [NSArray arrayWithObjects: @"BAT_ADRESSE", @"ETG_DESIGNATION", @"LOC_CODE", @"LOC_SURFACE", @"LOC_TYPE_DESIGNATION", @"LOC_OCCUPANTS", nil];
    					
    	self.queryTaskContainer = [self initializeQueryTaskContainer];
    	
    	self.query = [AGSQuery query];
    	self.query.returnGeometry = NO;
    	self.query.spatialRelationship = AGSSpatialRelationshipIntersects;
    	self.query.outFields = entryOrder;
    }
    
    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
        return YES;
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];	
    }
    
    - (void)viewDidUnload {
    }
    
    - (void)dealloc {
    	self.mapView = nil;
    	self.dynamicLayer = nil;
    	self.dynamicLayerView = nil;
    	self.graphicsLayer = nil;
    	self.queryTaskContainer = nil;
    	self.query = nil;
    	self.srUniNe = nil;
    	self.infoView = nil;
    	self.infoLabel = nil;
    	self.scaleBarView = nil;
        entryOrder = nil;
        titleText = nil;
    	
        [super dealloc];
    }
    
    #pragma mark -
    - (void) setupMapView:(BOOL)withOSMLayer {
        
        if(withOSMLayer) {
            // if the dynamic layer base is open during the changing of layers, delete during zoom back
            if ([self.visibleLayers containsObject:[NSNumber numberWithInt:5]]){
                [self.visibleLayers removeObject:[NSNumber numberWithInt:5]];
            }
            
            AGSOpenStreetMapLayer *osmLayer = [[[AGSOpenStreetMapLayer alloc]init]autorelease];
            // add the openStreetMap as basemap 
            UIView<AGSLayerView>* lyr = [self.mapView addMapLayer:osmLayer withName:@"tiledLayer"];
    	
            lyr.drawDuringPanning = YES;
            lyr.drawDuringZooming = YES;
        }
    	// save a reference of the spatial reference from UniNe provided maps
    	self.srUniNe = [AGSSpatialReference spatialReferenceWithWKID:kSpatialRefWkidUniNe];
    	
        if (self.dynamicLayerInfo != nil) {
            self.dynamicLayer = [[[AGSDynamicMapServiceLayer alloc] initWithMapServiceInfo: self.dynamicLayerInfo] autorelease]; 
        } else {
            AGSDynamicMapServiceLayer *dmLayer = [[[AGSDynamicMapServiceLayer alloc] initWithURL:[NSURL URLWithString:kDynamicMapServiceURL]] autorelease];
            self.dynamicLayer = dmLayer;
            // copy the mapServiceInfo, otherwise the pointer gets lost during the reset of the map
            self.dynamicLayerInfo = [[dmLayer.mapServiceInfo copy] autorelease];
        }
    	
        if (withOSMLayer) {
            if ([self.visibleLayers containsObject:[NSNumber numberWithInt:6]]) {
                [self.visibleLayers removeObject:[NSNumber numberWithInt:6]];
            }
            self.dynamicLayer.visibleLayers = [NSArray arrayWithArray:self.visibleLayers];
        } else {
            if (! [self.visibleLayers containsObject:[NSNumber numberWithInt:6]]) {
                [self.visibleLayers addObject:[NSNumber numberWithInt:6]];
            }
            self.dynamicLayer.visibleLayers = [NSArray arrayWithArray:self.visibleLayers];
        }
    	
    	UIView<AGSLayerView> *dynamicLayerView = [self.mapView addMapLayer:self.dynamicLayer withName:@"dynamicLayer"];
    	dynamicLayerView.drawDuringPanning = YES;
    	dynamicLayerView.drawDuringZooming = YES;
    	self.dynamicLayerView.alpha = 0.7;
    	
    	// create and add the graphics layer to the map
    	self.graphicsLayer = [AGSGraphicsLayer graphicsLayer];
    	[self.mapView addMapLayer:self.graphicsLayer withName:@"graphicsLayer"];
    }
    
    - (NSDictionary *) initializeQueryTaskContainer {
        NSMutableDictionary *tmpDic = [[NSMutableDictionary new] autorelease];
        
        //the basemap where we zoom, just use for setting the layers in the menu
        AGSQueryTask *qtl = [[[AGSQueryTask alloc] initWithURL:[NSURL URLWithString:kDynamicMapServiceURL]] autorelease];
        qtl.delegate = self;
        [tmpDic setObject:qtl forKey:[NSNumber numberWithInt:5]];
        
        //the difference floors
        AGSQueryTask *qtl0 = [[[AGSQueryTask alloc] initWithURL:[NSURL URLWithString:kDynamicMapLayer0ServiceURL]] autorelease];
        qtl0.delegate = self;
        [tmpDic setObject:qtl0 forKey:[NSNumber numberWithInt:0]];
        
        ...
        return [NSDictionary dictionaryWithDictionary:tmpDic];
    }
    
    - (void)respondToZoomlevelChange: (NSNotification*) notification {
    	[self.scaleBarView  updateBar:(1 / AGSUnitsToUnits(self.mapView.resolution, self.mapView.units, AGSUnitsMeters))];
        
        AGSEnvelope *actEnv = [[[self.mapView.visibleArea envelope] copy] autorelease]; 
        if (self.mapView.resolution <= 0.6 && isOSMDisplayed) {
            
            [self.mapView reset];
            [self setupMapView:NO];
            isOSMDisplayed = NO;
            
            if (isAreaSearch){
                self.query.returnGeometry = NO;
            } else {
                self.query.returnGeometry = YES;
            }      
            AGSGeometryEngine *ge = [AGSGeometryEngine defaultGeometryEngine];
            [self.mapView zoomToEnvelope:(AGSEnvelope *)[ge projectGeometry:actEnv toSpatialReference:self.mapView.spatialReference] animated:YES];   
        } else if (self.mapView.resolution > 0.6 && ! isOSMDisplayed) {
            
            [self.mapView reset];
            [self setupMapView:YES];
            isOSMDisplayed = YES;    
            self.query.returnGeometry = NO;
            
            AGSGeometryEngine *ge = [AGSGeometryEngine defaultGeometryEngine];
            [self.mapView zoomToEnvelope:(AGSEnvelope *)[ge projectGeometry:actEnv toSpatialReference:self.mapView.spatialReference] animated:YES];
        }
    }
    
    #pragma mark -
    #pragma mark IBAction methods
    -(IBAction) gpsButtonClicked {
    	if (self.mapView.gps.enabled) {
            // according to apple, this should work on iOS 5..but somehow it doesn't...
            self.gpsButton.tintColor = [UIColor blackColor];
            [self.mapView.gps stop];
        } else {
            // according to apple, this should work on iOS 5..but somehow it doesn't...
            self.gpsButton.tintColor = [UIColor whiteColor];
            [self.mapView.gps start];
        }
    }
    
    -(IBAction) infoButtonClicked {
        
    	SettingsMenuViewController *settingsMenuController = [[SettingsMenuViewController alloc] initWithNibName:kXibNameSettingsMenuView bundle:nil];
    	
        settingsMenuController.visibleLayers = self.dynamicLayer.visibleLayers;
        settingsMenuController.isOSMDisplayed = isOSMDisplayed;
        settingsMenuController.parentDelegate = self;
        
        [self presentModalViewController:settingsMenuController animated:YES]; 
    	
        [settingsMenuController release];    
    }
    
    -(IBAction) queryModeValueChanged {
        foundLocation = NO;
        [self.graphicsLayer removeAllGraphics];
        [self.graphicsLayer dataChanged];
        self.mapView.callout.hidden = YES;
        
        if (self.queryModeSwitch.selectedSegmentIndex == 1) {
            self.infoLabel.text = @"area search";
        } else {
            self.infoLabel.text = @"single location search";
        }
    }
    
    #pragma mark -
    #pragma mark AGSMapViewLayerDelegate
    -(void) mapViewDidLoad:(AGSMapView*)mapView {
    	
    	// startup GPS but not autoPan
    	[self.mapView.gps start];
    	[self.scaleBarView  updateBar:(1 / AGSUnitsToUnits(self.mapView.resolution, self.mapView.units, AGSUnitsMeters))];
    }

  6. #6
    Vasupree Ryser
    Join Date
    Apr 2012
    Posts
    5
    Points
    1
    Answers Provided
    0


    0

    Default Re: AGSGeometryEngine, map not fully loaded

    Here is the last part :

    Code:
    #pragma mark AGSMapViewTouchDelegate
    - (void) mapView:(AGSMapView *)mapView didClickAtPoint:(CGPoint)screen mapPoint:(AGSPoint *)mappoint graphics:(NSDictionary *)graphics {
        
        AGSEnvelope *visibleEnv = [[[self.mapView.visibleArea envelope] copy] autorelease];
        AGSSpatialReference *spaRef = [[self.srUniNe copy] autorelease];
        
        foundLocation = NO;
        [self.graphicsLayer removeAllGraphics];
    	self.infoLabel.text = @"";
    	self.clickedPoint = mappoint;
        
        AGSGeometryEngine *ge = [AGSGeometryEngine defaultGeometryEngine];
        AGSPoint *point_srUniNe = (AGSPoint *)[ge projectGeometry:mappoint toSpatialReference:self.srUniNe];
    	
        if (self.queryModeSwitch.selectedSegmentIndex == 1) {
            // arcGIS iOS v2.1 Pay attention!
            // visibleArea can be null, when the baseMap isn't fully loaded yet. (http://forums.arcgis.com/threads/44385-iOS-API-2.1-envelope-to-visibleArea-deprication)        
            AGSEnvelope *actualEnv = (AGSEnvelope *)[ge projectGeometry:visibleEnv toSpatialReference:spaRef];
            
            isAreaSearch = YES;
            self.query.returnGeometry = NO;
            
            double xLength = actualEnv.xmax - actualEnv.xmin;
            // size the square according to the height of the device
            if (self.interfaceOrientation == UIDeviceOrientationLandscapeLeft || self.interfaceOrientation == UIDeviceOrientationLandscapeRight) {
                xLength = actualEnv.ymax - actualEnv.ymin;
            }
            
            double xmin = point_srUniNe.x - (xLength / 13);
            double xmax = point_srUniNe.x + (xLength / 13);
            double ymin = point_srUniNe.y - (xLength / 13);
            double ymax = point_srUniNe.y + (xLength / 13);
            
            AGSEnvelope *queryEnv = [AGSEnvelope envelopeWithXmin:xmin ymin:ymin xmax:xmax ymax:ymax spatialReference:self.srUniNe];
            
            self.query.geometry = queryEnv;
            
            AGSSymbol* symbol = [AGSSimpleFillSymbol simpleFillSymbol];
            symbol.color = [UIColor colorWithRed:0 green:0 blue:1 alpha:0.5];
            AGSEnvelope *queryEnv_srOSM = (AGSEnvelope *)[ge projectGeometry:queryEnv toSpatialReference:self.mapView.spatialReference];
            AGSGraphic *envGraphic = [AGSGraphic graphicWithGeometry:queryEnv_srOSM symbol:symbol attributes:[NSMutableDictionary dictionary]  infoTemplateDelegate:nil];
            [self.graphicsLayer addGraphic:envGraphic];
            [self.graphicsLayer dataChanged];
    
        } else {
            isAreaSearch = NO;
            if (isOSMDisplayed){
                self.query.returnGeometry = NO;
            } else {
                self.query.returnGeometry = YES;
        }
        self.query.geometry = point_srUniNe;
        }
    	for (NSNumber *nr in self.dynamicLayer.visibleLayers) {
    		if (foundLocation) {
    			break;
    		}
    		[[self.queryTaskContainer objectForKey:nr] executeWithQuery:self.query];
    	}
    }
    
    #pragma mark - AGSMapViewCalloutDelegate
    - (void)mapView:(AGSMapView *)mapView didClickCalloutAccessoryButtonForGraphic: (AGSGraphic *) 	graphic {
        
        //The user clicked the callout button, so display the complete set of results
        ResultsViewController *resultsVC = [[ResultsViewController alloc] initWithNibName:kXibNameResultsView bundle:nil];
        resultsVC.entryOrder = entryOrder;
        
        NSMutableDictionary *tmp = [NSMutableDictionary new];
        [tmp setObject:@"Adress" forKey:@"BAT_ADRESSE"];
        ...
        [tmp release];
    	
        //set our attributes/results into the results VC
        if ([self.resultsArray count] > 20) {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Too many results" message:[NSString stringWithFormat:@"%d results found.\nDisplay maximum is 20.\nZoom in for less results", [self.resultsArray count]] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [alert show];
            [alert release];
            
            NSRange range;
            range.location = 0;
            range.length = 20;
            
            resultsVC.resultsArray = [[NSArray arrayWithArray:self.resultsArray] subarrayWithRange:range];
        } else {
            resultsVC.resultsArray = [NSArray arrayWithArray:self.resultsArray];
        }
        
        [self presentModalViewController:resultsVC animated:YES]; 
    	
        [resultsVC release];
    }
    
    #pragma mark - AGSQueryTaskDelegate
    
    - (void)queryTask:(AGSQueryTask *)queryTask operation:(NSOperation*)op didExecuteWithFeatureSetResult:(AGSFeatureSet *)featureSet {
        
        if ([featureSet.features count] > 0) {
            if (foundLocation) {
                for (AGSGraphic *graphic in featureSet.features) {
                    [self.resultsArray addObject:graphic.attributes];
                }
            } else {
                foundLocation = YES;
             
                AGSSymbol* symbol = [AGSSimpleFillSymbol simpleFillSymbol];
                symbol.color = [UIColor colorWithRed:0 green:0 blue:1 alpha:0.5];
                
                // set the symbol and add it to the graphics layer
                AGSGraphic *resultGraphic = [featureSet.features objectAtIndex:0];
                if (self.resultsArray == nil) {
                    self.resultsArray = [[NSMutableArray new] autorelease];
                } else {
                    [self.resultsArray removeAllObjects];
                }
                for (AGSGraphic *graphic in featureSet.features) {
                    [self.resultsArray addObject:graphic.attributes];
                }
                
                resultGraphic.symbol = symbol;
                [self.graphicsLayer addGraphic:resultGraphic];
                
                if (self.queryModeSwitch.selectedSegmentIndex == 1) {
                    
                    self.infoLabel.text = @"area search";
                    self.mapView.callout.title = @"Details";
                    self.mapView.callout.detail = @"Click for more details..";
                } else {
                    
                   NSString *numero = [[NSDictionary dictionaryWithDictionary:resultGraphic.attributes] valueForKey:@"LOC_CODE"];
                   self.infoLabel.text = numero;
                    
                   self.mapView.callout.title = numero;
                   self.mapView.callout.detail = @"Click for more detail..";
                }
              
                [self.mapView showCalloutAtPoint:self.clickedPoint forGraphic:resultGraphic animated:YES];
                [self.graphicsLayer dataChanged];
            }
    	}
    }
    
    - (void)queryTask:(AGSQueryTask *)queryTask operation:(NSOperation*)op didFailWithError:(NSError *)error {
    	UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Query Task Failed"
    													message:[NSString stringWithFormat:@"Error: %@", [error localizedDescription]] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    	[alert show];
    	[alert release];
    }
    
    #pragma mark - ContextMenuReturnDelegate
    - (void) returnVisibleLayers:(NSArray*)visibleLayers {
            
        self.dynamicLayer.visibleLayers = visibleLayers;
        self.visibleLayers = [NSMutableArray arrayWithArray:visibleLayers];
        
        foundLocation = NO;
        [self.dynamicLayer dataChanged];
        [self.graphicsLayer removeAllGraphics];
        [self.graphicsLayer dataChanged];
        self.infoLabel.text = @"";
    	self.clickedPoint = nil;
    }
    
    @end
    With this class, I have another problem. In the menu of Info button, we can change the visible layers = the different floor of the building, but when I change the layer, the symbol is always displaying even I make [self.graphicsLayer removeAllGraphics] , what is my error ?

    Thank you for your help

  7. #7
    Nimesh Jarecha

    Join Date
    Oct 2009
    Posts
    883
    Points
    489
    Answers Provided
    105


    0
    This post is marked as the answer

    Default Re: AGSGeometryEngine, map not fully loaded

    Okay..let’s look at one issue at a time. You can create new thread for other issue.

    By looking at the code…there are few issues.

    1. You are setting up your map view ([self setupMapView:YES]) in videDidLoad and immediately creating an envelope with self.mapView.spatialReference for zoom function. It may happen that spatialReference of the mapView will be nil as map view may or may not be loaded. If you want to do this then you should not rely on self.mapView.spatialReference and provide known spatial reference or you should move this code in the mapViewDid load where you know that self.mapView.spatialReference has valid spatial reference as map view successfully loaded.

    2. You are observing MapDidEndZooming notification and in respondToZoomlevelChange you are keeping a copy of self.mapView.visibleArea.envelope without checking whether it’s not-nil/valid envelope or not.

    3. Immediately you are checking some condition and if it’s true then you are resetting the map view. Again, you are using the self.mapView.spatialReference in the AGSGeometryEngine’s projectGeometry method without verifying whether spatial reference is valid or not. You should use mapView’s properties only when you are confirm whether map is loaded successfully.

    Hope this helps!

    Regards,
    Nimesh

  8. #8
    Vasupree Ryser
    Join Date
    Apr 2012
    Posts
    5
    Points
    1
    Answers Provided
    0


    0

    Default Re: AGSGeometryEngine, map not fully loaded

    Thank you for your reply.

    I have make the thing little bit different, because my boss don't want the select area method. But with your information, it's working better in the few test that I made and it's now more comprehensive for me.

    Best regards.

+ Reply to Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts