Zoom To Polygon and Selected Point Outside Polygon

4403
9
05-23-2011 12:50 PM
ChrisSergent
Regular Contributor III
I want my application to zoom to the extent of our city corporate boundaries and if an address point is outside of the city corporate boundary, I want to zoom to the extent where the city corporate boundary and the address point are visible.


I have been able to get a envelope for the point, so what would the syntax be if I am correct to set the extent of the envelope of the city corporate boundary polygon and the created envelope from my address point combined?

Here is our external web service for our corporate boundary:
http://maps.decaturil.gov/ArcGIS/rest/services/InternetVector/MapServer/39

If there is a point outside of that polygon, how do I include it and zoom to both?

Still trying to figure out how I should ask this question, so please ask for clarity if needed.

chris
0 Kudos
9 Replies
TonyContreras
Occasional Contributor
It seems that you would want a function that creates a custom envelope. The input would be the envelope for the point and inside the function it would compare each value of the part of the envelope (xmin, ymin, etc.) with that of the city boundary and assign the more extreme value to the new envelope. This way the smallest value for a min and largest value of max will be used to expand the envelope when the point is outside the city boundary.
0 Kudos
derekswingley1
Frequent Contributor
Is your city boundary geometry sent to the client? If so, you can do the following:
-create an esri.geometry.Polygon from your city boundary
-use polygon.contains() to test if your point is in your city boundary
-if the point is in your polygon, set the map extent to the city boundary's extent
-if the point is not in your polygon, create an extent from your point
-union your point extent with the extent of your city boundary
-set the map's extent to the unioned extent
0 Kudos
ChrisSergent
Regular Contributor III
I have one final issue. The polygon that is the city boundaries is disappearing when I zoom to the new envelope.
Here is what my application is doing right now. Any ideas?


It seems that you would want a function that creates a custom envelope. The input would be the envelope for the point and inside the function it would compare each value of the part of the envelope (xmin, ymin, etc.) with that of the city boundary and assign the more extreme value to the new envelope. This way the smallest value for a min and largest value of max will be used to expand the envelope when the point is outside the city boundary.
0 Kudos
ChrisSergent
Regular Contributor III
Derek,
I do think Union is what I should have done, but I am not sure how to apply it.
Here is what I did, but I am still trying to figure out why the city boundary disappears on zooming in.


Any ideas?

Is your city boundary geometry sent to the client? If so, you can do the following:
-create an esri.geometry.Polygon from your city boundary
-use polygon.contains() to test if your point is in your city boundary
-if the point is in your polygon, set the map extent to the city boundary's extent
-if the point is not in your polygon, create an extent from your point
-union your point extent with the extent of your city boundary
-set the map's extent to the unioned extent
0 Kudos
derekswingley1
Frequent Contributor
Hi Chris,

Thanks for posting the video, very helpful.

If I have this right, your city boundary is a dynamic map service layer? I was thinking it was a graphic on your map and not an overlay. Any chance you're willing to move to using your city boundary as a graphic instead of a dynamic map service layer?

To answer your question about the union method I mentioned, you need two extent geometries so you would need to create an extent from your point. Here's one method:
// point objects don't have an extent so  you need to
// calculate a small value to use as padding for your point
var px = (map.extent.xmax - map.extent.xmin) / map.width
// then create an extent
var ptExtent = new esri.geometry.Extent(
  pt.x - px, // xmin
  pt.y - px, // ymin
  pt.x + px, // xmax
  pt.y + px,  //ymax
  map.spatialReference
);
// union the two extents
// cityExtent would be the result of
// cityGraphic.getExtent()
var newExtent = ptExtent.union(cityExtent);
map.setExtent(newExtent);
0 Kudos
ChrisSergent
Regular Contributor III
Since you can see what I am attempting, the next question is, how to modify my code. I have no problem with using the city boundary as a graphic. It serves no purpose besides display.

Here is my code. I have quite a few comments, so hopefully it will answer any questions about how it works. Limited comments are when I am using an ESRI example; which did not really explain what was being done; this is just to explain gaps in my documentation.

I have the code for the entire app at: http://dl.dropbox.com/u/26169505/CityHireEligibleSample.zip
It's 3.94mb ESRI's limit is 2.0mb It's a public URL, so you do not need to have a dropbox account. I will remove this file when you download it or tomorrow.

Thanks for your feedback. I will attempt to modify my code, but if you see what I need to do, that would be great too.

Chris

Hi Chris,

Thanks for posting the video, very helpful.

If I have this right, your city boundary is a dynamic map service layer? I was thinking it was a graphic on your map and not an overlay. Any chance you're willing to move to using your city boundary as a graphic instead of a dynamic map service layer?

To answer your question about the union method I mentioned, you need two extent geometries so you would need to create an extent from your point. Here's one method:
// point objects don't have an extent so  you need to
// calculate a small value to use as padding for your point
var px = (map.extent.xmax - map.extent.xmin) / map.width
// then create an extent
var ptExtent = new esri.geometry.Extent(
  pt.x - px, // xmin
  pt.y - px, // ymin
  pt.x + px, // xmax
  pt.y + px,  //ymax
  map.spatialReference
);
// union the two extents
// cityExtent would be the result of
// cityGraphic.getExtent()
var newExtent = ptExtent.union(cityExtent);
map.setExtent(newExtent);
0 Kudos
ChrisSergent
Regular Contributor III
I have modified the code and it buffers fine and the city boundaries remain, but it no longer zooms.
Here is a video of what is happening. I was providing an online demonstration while preparing it.
http://youtu.be/BOcFc9deLLQ?hd=1

I uploaded a modified application here: http://db.tt/w6bI4sK
Since you can see what I am attempting, the next question is, how to modify my code. I have no problem with using the city boundary as a graphic. It serves no purpose besides display.

Please let me know if I need to explain anything.

Here is my code. I have quite a few comments, so hopefully it will answer any questions about how it works. Limited comments are when I am using an ESRI example; which did not really explain what was being done; this is just to explain gaps in my documentation.

I have the code for the entire app at: http://dl.dropbox.com/u/26169505/CityHireEligibleSample.zip
It's 3.94mb ESRI's limit is 2.0mb It's a public URL, so you do not need to have a dropbox account. I will remove this file when you download it or tomorrow.

Thanks for your feedback. I will attempt to modify my code, but if you see what I need to do, that would be great too.

Chris
0 Kudos
derekswingley1
Frequent Contributor
Hey Chris,

Thanks for posting another video, that makes it crystal clear to see what you're trying to do.


I'm going to suggest a slightly new idea...since you're adding a buffer to your map, how about setting your map extent to include the buffer and the city boundary?

To do this, you would take the extent of your buffer geometry, union it with your map extent and then set your map extent to the new extent. I'm looking at the code you uploaded yesterday and you would do this inside your "showBuffer" function. Here's how it would look:

function showBuffer(geometries) {
    var symbol = new esri.symbol.SimpleFillSymbol(
        esri.symbol.SimpleFillSymbol.STYLE_SOLID,
        new esri.symbol.SimpleLineSymbol(
          esri.symbol.SimpleLineSymbol.STYLE_SOLID,
          new dojo.Color([0, 0, 255, 0.65]), 2
        ),
        new dojo.Color([0, 0, 255, 0.35])
    );
    dojo.forEach(geometries, function (geometry) {
        var graphic = new esri.Graphic(geometry, symbol);
        map.graphics.add(graphic);
    });

    // looks like you only buffer one point
    // so take the first geometry in the geometries array
    // and get its extent
    var bufferExtent = geometries[0].getExtent();
    // create a new extent that is the union of the buffer's
    // extent and the map's current extent
    var newExtent = bufferExtent.union(map.getExtent());
    // set the map's extent
    map.setExtent(newExtent);

    queryParams.spatialRelationship = esri.tasks.Query.SPATIAL_REL_INTERIORINTERSECTION;
    queryParams.returnGeometry = true;
    queryParams.geometry = geometries[0];
    queryTask.execute(queryParams);
}
0 Kudos
ChrisSergent
Regular Contributor III
Derek,
I have gotten everything to work using the method of Zooming to the Polygon and City Boundary, but still need to figure out how to perform a union with a code driven envelope of a point against the City Boundary. I have a video that provides a demo of the code working with the Buffered Point and City Boundary that you can watch here - http://youtu.be/PMeB016v_xE?hd=1. I also provide an example as to why I only want the Address Point and City Boundary.

In addition, I have attached the JavaScript code that is used in the aforementioned video. There was also a ticket on this issue originally, incident number - #933278. Thang; the tech support staff may be able to provide you with additional information about the issue with the WKID and the attempt to create a union on the point and city boundary.

Only one piece to go. I hope you know what I need to do! 😄

Just in case you want to record feedback, here is the recording tool I use: http://camstudio.org/

Thanks again.

Chris

Hey Chris, 

Thanks for posting another video, that makes it crystal clear to see what you're trying to do. 


I'm going to suggest a slightly new idea...since you're adding a buffer to your map, how about setting your map extent to include the buffer and the city boundary? 

To do this, you would take the extent of your buffer geometry, union it with your map extent and then set your map extent to the new extent. I'm looking at the code you uploaded yesterday and you would do this inside your "showBuffer" function. Here's how it would look: 

function showBuffer(geometries) {
    var symbol = new esri.symbol.SimpleFillSymbol(
        esri.symbol.SimpleFillSymbol.STYLE_SOLID,
        new esri.symbol.SimpleLineSymbol(
          esri.symbol.SimpleLineSymbol.STYLE_SOLID,
          new dojo.Color([0, 0, 255, 0.65]), 2
        ),
        new dojo.Color([0, 0, 255, 0.35])
    );
    dojo.forEach(geometries, function (geometry) {
        var graphic = new esri.Graphic(geometry, symbol);
        map.graphics.add(graphic);
    });

    // looks like you only buffer one point
    // so take the first geometry in the geometries array
    // and get its extent
    var bufferExtent = geometries[0].getExtent();
    // create a new extent that is the union of the buffer's
    // extent and the map's current extent
    var newExtent = bufferExtent.union(map.getExtent());
    // set the map's extent
    map.setExtent(newExtent);

    queryParams.spatialRelationship = esri.tasks.Query.SPATIAL_REL_INTERIORINTERSECTION;
    queryParams.returnGeometry = true;
    queryParams.geometry = geometries[0];
    queryTask.execute(queryParams);
}
0 Kudos