{"id":58060,"date":"2024-06-21T12:22:39","date_gmt":"2024-06-21T16:22:39","guid":{"rendered":"https:\/\/www.aaroads.com\/?p=58060"},"modified":"2024-11-11T10:21:00","modified_gmt":"2024-11-11T15:21:00","slug":"working-with-geometries-in-python","status":"publish","type":"post","link":"https:\/\/www.aaroads.com\/blog\/working-with-geometries-in-python\/","title":{"rendered":"Working with Geometries in Python"},"content":{"rendered":"<div class=\"fusion-fullwidth fullwidth-box fusion-builder-row-1 fusion-flex-container has-pattern-background has-mask-background nonhundred-percent-fullwidth non-hundred-percent-height-scrolling\" style=\"--awb-border-radius-top-left:0px;--awb-border-radius-top-right:0px;--awb-border-radius-bottom-right:0px;--awb-border-radius-bottom-left:0px;--awb-flex-wrap:wrap;\" ><div class=\"fusion-builder-row fusion-row fusion-flex-align-items-flex-start fusion-flex-content-wrap\" style=\"max-width:1144px;margin-left: calc(-4% \/ 2 );margin-right: calc(-4% \/ 2 );\"><div class=\"fusion-layout-column fusion_builder_column fusion-builder-column-0 fusion_builder_column_1_1 1_1 fusion-flex-column\" style=\"--awb-bg-size:cover;--awb-width-large:100%;--awb-margin-top-large:0px;--awb-spacing-right-large:1.92%;--awb-margin-bottom-large:20px;--awb-spacing-left-large:1.92%;--awb-width-medium:100%;--awb-order-medium:0;--awb-spacing-right-medium:1.92%;--awb-spacing-left-medium:1.92%;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:1.92%;--awb-spacing-left-small:1.92%;\"><div class=\"fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-flex-start fusion-content-layout-column\"><div class=\"fusion-text fusion-text-1\"><p>Module 6 introduces both working with geometries with Python and external text files or tabular data. Using geometry objects in memory can be used for input and output in geoprocessing. This also circumvents the need to make temporary feature classes. Utilizing the\u00a0<span style=\"font-family: courier;\" data-keep-original-tag=\"false\" data-original-attrs=\"\">open()<\/span>\u00a0function,\u00a0<span style=\"font-family: courier;\" data-keep-original-tag=\"false\" data-original-attrs=\"\">fileinput<\/span>\u00a0module, and\u00a0<span style=\"font-family: courier;\" data-keep-original-tag=\"false\" data-original-attrs=\"\">write<\/span>\u00a0module, text from .txt, .csv and other files can be imported into Python or exported to a file outside of ArcGIS Pro. The\u00a0<span style=\"font-family: courier;\" data-keep-original-tag=\"false\" data-original-attrs=\"\">readlines()<\/span>\u00a0and\u00a0<span style=\"font-family: courier;\" data-keep-original-tag=\"false\" data-original-attrs=\"\">writelines()<\/span>\u00a0methods also work with external files, but on a line by line basis, sometimes with iteration through a loop. These aspects further add to the utility of automating processes with Python.<\/p>\n<p>The Lab assignment for Module 6 is to write a Python script that creates a new text file outside of ArcGIS, and to populate it with geometry data from a feature class of polylines for rivers in Maui, Hawaii.<\/p>\n<\/div><div class=\"fusion-image-element awb-imageframe-style awb-imageframe-style-below awb-imageframe-style-1\" style=\"text-align:center;--awb-caption-margin-top:10px;--awb-caption-margin-bottom:10px;--awb-caption-title-font-family:var(--h4_typography-font-family);--awb-caption-title-font-weight:var(--h4_typography-font-weight);--awb-caption-title-font-style:var(--h4_typography-font-style);--awb-caption-title-size:var(--h4_typography-font-size);--awb-caption-title-transform:var(--h4_typography-text-transform);--awb-caption-title-line-height:var(--h4_typography-line-height);--awb-caption-title-letter-spacing:var(--h4_typography-letter-spacing);\"><span class=\" fusion-imageframe imageframe-none imageframe-1 hover-type-none\"><a href=\"https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/maui-rivers.png\" class=\"fusion-lightbox\" data-rel=\"iLightbox[python]\" data-title=\"Maui, Hawaii Rivers feature class\" title=\"Maui, Hawaii Rivers feature class\"><img decoding=\"async\" width=\"768\" height=\"416\" alt=\"Maui, Hawaii Rivers feature class\" src=\"https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/maui-rivers-768x416.png\" class=\"img-responsive wp-image-58061 disable-lazyload\" srcset=\"https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/maui-rivers-320x173.png 320w, https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/maui-rivers-480x260.png 480w, https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/maui-rivers-768x416.png 768w, https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/maui-rivers.png 1254w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/><\/a><\/span><div class=\"awb-imageframe-caption-container\" style=\"text-align:center;\"><div class=\"awb-imageframe-caption\"><h4 class=\"awb-imageframe-caption-title\">The Maui, Hawaii rivers feature class for Module 6<\/h4><\/div><\/div><\/div><div class=\"fusion-text fusion-text-2\"><p>Following is a graphic I made in an attempt to better explain how to work with geometries in Python. The\u00a0<span style=\"font-family: courier;\" data-keep-original-tag=\"false\" data-original-attrs=\"\">getPart() method<\/span>, which returns an array of point objects for each geometry part, is the crux of the assignment.\u00a0<\/p>\n<\/div><div class=\"fusion-image-element \" style=\"text-align:center;--awb-margin-bottom:20px;--awb-caption-margin-top:10px;--awb-caption-margin-bottom:10px;--awb-caption-title-font-family:var(--h4_typography-font-family);--awb-caption-title-font-weight:var(--h4_typography-font-weight);--awb-caption-title-font-style:var(--h4_typography-font-style);--awb-caption-title-size:var(--h4_typography-font-size);--awb-caption-title-transform:var(--h4_typography-text-transform);--awb-caption-title-line-height:var(--h4_typography-line-height);--awb-caption-title-letter-spacing:var(--h4_typography-letter-spacing);\"><span class=\" fusion-imageframe imageframe-none imageframe-2 hover-type-none\"><a href=\"https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/get-part-method-explanation.png\" class=\"fusion-lightbox\" data-rel=\"iLightbox[python]\" data-title=\"Feature Class Architecture and getPart Method\" title=\"Feature Class Architecture and getPart Method\"><img decoding=\"async\" width=\"768\" height=\"522\" alt=\"Diagram outlining Feature Class Architecture and the getPart Method\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%271426%27%20height%3D%27969%27%20viewBox%3D%270%200%201426%20969%27%3E%3Crect%20width%3D%271426%27%20height%3D%27969%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-orig-src=\"https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/get-part-method-explanation-768x522.png\" class=\"lazyload img-responsive wp-image-58065\"\/><\/a><\/span><\/div><div class=\"fusion-text fusion-text-3\"><p>The SearchCursor function is used to read feature class geometries. Using the SearchCursor function requires several iterations of a feature class to return the points or vertices that make up the geometry of a feature. All polylines and polygons in a feature class are comprised of point objects.<\/p>\n<p>Every feature class is comprised of individual features, things we can see and interact with in ArcGIS Pro. Each feature has a record, which is tabulated in an attribute table. The rows of an attribute table contain the\u00a0<b>records<\/b>\u00a0of every feature found within the feature class. The columns contain the attributes based upon a field.<\/p>\n<p>When using a SearchCursor function to work with geometries, the initial loop iterates through the records and returns a tuple with two objects for each feature. The first variable is the row index number and the second is the\u00a0<b>polyline object<\/b>. A polyline object is a shape defined by one or more paths.<\/p>\n<p>A second iteration within the first iteration is required to ultimately return point objects from each polyline object. This is what is known as a\u00a0<i>nested loop<\/i>. The\u00a0<i>for loop<\/i>\u00a0that is the nested loop iterates through each polyline object and returns an\u00a0<b>array object<\/b>. Part of the ArcPy package, arrays are groupings of points that comprise the geometry of a feature.\u00a0<i>An array in other programming languages\u00a0 is a list.<\/i><\/p>\n<p>A second nested loop iterates through the array object to extract the\u00a0<b>point object<\/b>, which contains the coordinate information of the vertices that make up each feature. The\u00a0<span style=\"font-family: courier;\" data-keep-original-tag=\"false\" data-original-attrs=\"\">getPart()<\/span>\u00a0method however allows a script to bypass this third iteration by coupling the operation with the previous\u00a0<i>for loop<\/i>\u00a0that returns the array object of a feature. That is because the polyline object has this method, which receives an input parameter and index, and returns an array of point objects.<\/p>\n<p>The\u00a0<span style=\"font-family: courier;\" data-keep-original-tag=\"false\" data-original-attrs=\"\">getPart()<\/span>\u00a0method iterates through the tuple output by the\u00a0<span style=\"font-family: courier;\" data-keep-original-tag=\"false\" data-original-attrs=\"\">SearchCursor<\/span>\u00a0function. The index inputs the first element of the tuple, which for the SearchCursor is based upon the\u00a0<span style=\"font-family: courier;\" data-keep-original-tag=\"false\" data-original-attrs=\"\">field names<\/span>\u00a0argument.\u00a0<i>Part<\/i>\u00a0in the function name references the return of an array object of point objects for a particular part of the geometry, which for Module 6 is index 0, the FID number. The method iterates off the polyline object returned from the tuple.<\/p>\n<p>The flowchart for the Module 6 script outlines the SearchCursor function and one nested loop used to obtain point objects for each part of the array object of a feature:<\/p>\n<\/div><div class=\"fusion-image-element \" style=\"text-align:center;--awb-margin-top:20px;--awb-margin-bottom:20px;--awb-caption-margin-top:10px;--awb-caption-margin-bottom:10px;--awb-caption-title-font-family:var(--h4_typography-font-family);--awb-caption-title-font-weight:var(--h4_typography-font-weight);--awb-caption-title-font-style:var(--h4_typography-font-style);--awb-caption-title-size:var(--h4_typography-font-size);--awb-caption-title-transform:var(--h4_typography-text-transform);--awb-caption-title-line-height:var(--h4_typography-line-height);--awb-caption-title-letter-spacing:var(--h4_typography-letter-spacing);\"><span class=\" fusion-imageframe imageframe-none imageframe-3 hover-type-none\"><a href=\"https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/Mod6_ANitzman.drawio.png\" class=\"fusion-lightbox\" data-rel=\"iLightbox[python]\" data-title=\"Nested Loops Program Flowchart\" title=\"Nested Loops Program Flowchart\"><img decoding=\"async\" width=\"777\" height=\"1012\" alt=\"Nested Loops Program Flowchart\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27777%27%20height%3D%271012%27%20viewBox%3D%270%200%20777%201012%27%3E%3Crect%20width%3D%27777%27%20height%3D%271012%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-orig-src=\"https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/Mod6_ANitzman.drawio.png\" class=\"lazyload img-responsive wp-image-58064\"\/><\/a><\/span><\/div><div class=\"fusion-text fusion-text-4\"><p>This becomes a little more complicated with multipart features, where a feature is comprised of multiple arrays of point objects making up one set of attributes. Scenarios of this are where a feature contains polygons that are not physically connected, or where empty (interior) polygons fall within a larger (exterior) polygon. Think of St. Martin Parish, Louisiana, which consists of two areas separated by Iberia Parish in between, or Shively, Kentucky, a city encircled on all sides by Louisville.<\/p>\n<p>With multipart features, an iteration over all distinct parts comprising the overall feature is required to return its geometry. In summary, the polyline object returned from the SearchCursor contains array objects for each part. Within those array objects is another array which contains the point objects.<\/p>\n<p>The output of the script compiled for Module 6 produced a formatted text file for each river feature in the Maui rivers feature class:<\/p>\n<\/div><div class=\"fusion-image-element \" style=\"text-align:center;--awb-margin-bottom:10px;--awb-caption-margin-top:10px;--awb-caption-margin-bottom:10px;--awb-caption-title-font-family:var(--h4_typography-font-family);--awb-caption-title-font-weight:var(--h4_typography-font-weight);--awb-caption-title-font-style:var(--h4_typography-font-style);--awb-caption-title-size:var(--h4_typography-font-size);--awb-caption-title-transform:var(--h4_typography-text-transform);--awb-caption-title-line-height:var(--h4_typography-line-height);--awb-caption-title-letter-spacing:var(--h4_typography-letter-spacing);\"><span class=\" fusion-imageframe imageframe-none imageframe-4 hover-type-none\"><a href=\"https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/Mod6_AN_result.png\" class=\"fusion-lightbox\" data-rel=\"iLightbox[python]\" data-title=\"Module 6 Script Output\" title=\"Module 6 Script Output\"><img decoding=\"async\" width=\"493\" height=\"886\" alt=\"Module 6 text file screenshot of output data\" src=\"https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/Mod6_AN_result.png\" data-orig-src=\"https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/Mod6_AN_result.png\" class=\"lazyload img-responsive wp-image-58063\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27493%27%20height%3D%27886%27%20viewBox%3D%270%200%20493%20886%27%3E%3Crect%20width%3D%27493%27%20height%3D%27886%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-srcset=\"https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/Mod6_AN_result-200x360.png 200w, https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/Mod6_AN_result.png 493w\" data-sizes=\"auto\" data-orig-sizes=\"(max-width: 1024px) 100vw, (max-width: 640px) 100vw, 493px\" \/><\/a><\/span><\/div><div class=\"fusion-text fusion-text-5\"><p>Data output from point objects in the\u00a0<span style=\"font-family: courier;\" data-keep-original-tag=\"false\" data-original-attrs=\"\">writelines()<\/span>\u00a0method produced the ID number and the X-coordinate and Y-coordinate for each vertex of all records in the rivers feature class. This in turn was written to the new text file created at the beginning of the script with the\u00a0<span style=\"font-family: courier;\" data-keep-original-tag=\"false\" data-original-attrs=\"\">open()<\/span>\u00a0function.<\/p>\n<p>The vertex number for the vertices were assigned as part of the nested loop on the array object, where a variable\u00a0<i>vertexnum<\/i>\u00a0increased by one for each pass. The\u00a0<span style=\"font-family: courier;\" data-keep-original-tag=\"false\" data-original-attrs=\"\">getPart()<\/span>\u00a0method also returned the name object of each vertex, which was derived from the SearchCursor iteration.<\/p>\n<\/div><div class=\"fusion-image-element awb-imageframe-style awb-imageframe-style-below awb-imageframe-style-5\" style=\"text-align:center;--awb-caption-margin-top:10px;--awb-caption-margin-bottom:10px;--awb-caption-title-font-family:var(--h4_typography-font-family);--awb-caption-title-font-weight:var(--h4_typography-font-weight);--awb-caption-title-font-style:var(--h4_typography-font-style);--awb-caption-title-size:var(--h4_typography-font-size);--awb-caption-title-transform:var(--h4_typography-text-transform);--awb-caption-title-line-height:var(--h4_typography-line-height);--awb-caption-title-letter-spacing:var(--h4_typography-letter-spacing);\"><span class=\" fusion-imageframe imageframe-none imageframe-5 hover-type-none\"><a href=\"https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/oheo-gulch-maui.jpg\" class=\"fusion-lightbox\" data-rel=\"iLightbox[python]\" data-title=\"\u2018Ohe\u2019o Gulch in Maui, Hawaii\" title=\"\u2018Ohe\u2019o Gulch in Maui, Hawaii\"><img decoding=\"async\" width=\"768\" height=\"576\" alt=\"\u2018Ohe\u2019o Gulch in Maui, Hawaii\" src=\"https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/oheo-gulch-maui-768x576.jpg\" class=\"img-responsive wp-image-58066 disable-lazyload\" srcset=\"https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/oheo-gulch-maui-320x240.jpg 320w, https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/oheo-gulch-maui-480x360.jpg 480w, https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/oheo-gulch-maui-768x576.jpg 768w, https:\/\/www.aaroads.com\/blog\/wp-content\/uploads\/gis-classes\/oheo-gulch-maui.jpg 1200w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/><\/a><\/span><div class=\"awb-imageframe-caption-container\" style=\"text-align:center;\"><div class=\"awb-imageframe-caption\"><h4 class=\"awb-imageframe-caption-title\">\u2018Ohe\u2019o Gulch, downriver from Palikea Stream, which is one of the features from the Module 6 dataset<\/h4><\/div><\/div><\/div><div class=\"fusion-text fusion-text-6\"><p>My wife and I visited Maui in January 2011 and drove the iconic Hana Highway to Haleakal\u0101 National Park. The above photo is one of \u2018Ohe\u2019o Gulch, which is connects Palikea Stream to the Pacific Ocean at the southeast end of the island.<\/p>\n<\/div><\/div><\/div><\/div><\/div>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":58061,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1582],"tags":[1581,1602,1603,1601],"class_list":["post-58060","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-gis","tag-geographic-information-systems","tag-gis4102","tag-programming","tag-python"],"_links":{"self":[{"href":"https:\/\/www.aaroads.com\/blog\/wp-json\/wp\/v2\/posts\/58060","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.aaroads.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.aaroads.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.aaroads.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.aaroads.com\/blog\/wp-json\/wp\/v2\/comments?post=58060"}],"version-history":[{"count":3,"href":"https:\/\/www.aaroads.com\/blog\/wp-json\/wp\/v2\/posts\/58060\/revisions"}],"predecessor-version":[{"id":58068,"href":"https:\/\/www.aaroads.com\/blog\/wp-json\/wp\/v2\/posts\/58060\/revisions\/58068"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.aaroads.com\/blog\/wp-json\/wp\/v2\/media\/58061"}],"wp:attachment":[{"href":"https:\/\/www.aaroads.com\/blog\/wp-json\/wp\/v2\/media?parent=58060"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.aaroads.com\/blog\/wp-json\/wp\/v2\/categories?post=58060"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.aaroads.com\/blog\/wp-json\/wp\/v2\/tags?post=58060"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}