[{"data":1,"prerenderedAt":2016},["ShallowReactive",2],{"doc:\u002Fspatial-data-processing-automation\u002Fcoordinate-reference-systems\u002Fchoose-projected-crs-for-analysis-pyqgis":3},{"id":4,"title":5,"body":6,"description":2005,"extension":2006,"meta":2007,"navigation":292,"path":2012,"seo":2013,"stem":2014,"__hash__":2015},"docs\u002Fspatial-data-processing-automation\u002Fcoordinate-reference-systems\u002Fchoose-projected-crs-for-analysis-pyqgis\u002Findex.md","Choose a Projected CRS for Analysis in PyQGIS",{"type":7,"value":8,"toc":1992},"minimark",[9,13,22,31,214,219,241,245,248,505,515,519,522,678,686,778,782,785,1067,1072,1076,1079,1502,1518,1606,1610,1613,1845,1854,1858,1879,1883,1917,1921,1924,1928,1934,1943,1949,1955,1959,1988],[10,11,5],"h1",{"id":12},"choose-a-projected-crs-for-analysis-in-pyqgis",[14,15,16,17,21],"p",{},"Data increasingly arrives in WGS 84 longitude and latitude: GPS exports, web APIs, OpenStreetMap extracts, global datasets. That is fine for storage and display and wrong for almost every measurement. A buffer of ",[18,19,20],"code",{},"0.01"," is not a distance, an area in square degrees is not an area, and a nearest-neighbour search in degrees favours north–south neighbours over east–west ones everywhere except the equator. Before buffering, measuring, gridding or interpolating, the data needs to be in a projected CRS — and which one depends on where the data is and what you are measuring.",[14,23,24,25,30],{},"This recipe belongs to ",[26,27,29],"a",{"href":28},"\u002Fspatial-data-processing-automation\u002Fcoordinate-reference-systems\u002F","Coordinate Reference Systems in PyQGIS",". It decides between a national grid, a UTM zone and an equal-area projection, computes the right choice from a layer's extent, measures the distortion to confirm the choice, and wires the reprojection into a workflow so results come back in the original CRS.",[14,32,33],{},[34,35,40,44,48,55,72,81,91,97,102,109,114,119,122,125,131,136,140,145,149,152,154,156,159,163,169,173,176,182,186,192,197,201,204,210],"svg",{"viewBox":36,"role":37,"ariaLabel":38,"xmlns":39},"0 0 760 300","img","A decision path for choosing an analysis CRS: prefer the official national or regional grid when the data lies inside its area of use, else a UTM zone for areas within one zone, else an equal-area projection for area statistics or a local custom projection for large extents","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg",[41,42,43],"title",{},"Which projected CRS?",[45,46,47],"desc",{},"Start with the layer extent in WGS 84. If a national or regional grid covers it, such as British National Grid or ETRS89 UTM, use that. Otherwise, if the extent fits within one UTM zone, use that zone. If the extent spans several zones and the analysis is about areas or densities, use an equal-area projection such as LAEA Europe or a continental Albers. For distances over a large extent, use a projection centred on the data, such as an azimuthal equidistant centred on the study area.",[49,50],"rect",{"x":51,"y":51,"width":52,"height":53,"fill":54},"0","760","300","#f6f3ea",[56,57,58],"defs",{},[59,60,67],"marker",{"id":61,"viewBox":62,"refX":63,"refY":64,"markerWidth":65,"markerHeight":65,"orient":66},"pcrsDecArrow","0 0 10 10","8","5","7","auto-start-reverse",[68,69],"path",{"d":70,"fill":71},"M0 0 L10 5 L0 10 z","#2f3b35",[73,74,80],"text",{"x":75,"y":76,"style":77,"fill":78,"textAnchor":79},"380","28","text-anchor:middle;font-size:14px;font-weight:bold;font-family:sans-serif","#17211d","middle","Let the extent and the measurement decide",[49,82],{"x":83,"y":84,"width":85,"height":86,"rx":87,"fill":88,"stroke":89,"style":90},"24","118","140","56","10","#fffdf7","#59645f","stroke-width:2",[73,92,96],{"x":93,"y":94,"style":95,"fill":78,"textAnchor":79},"94","142","text-anchor:middle;font-size:10.5px;font-weight:bold;font-family:sans-serif","layer extent",[73,98,101],{"x":93,"y":99,"style":100,"fill":71,"textAnchor":79},"160","text-anchor:middle;font-size:9.5px;font-family:sans-serif","in WGS 84",[103,104],"line",{"x1":105,"y1":106,"x2":107,"y2":106,"stroke":71,"style":108},"164","146","196","stroke-width:1.8;marker-end:url(#pcrsDecArrow)",[49,110],{"x":111,"y":84,"width":99,"height":86,"rx":87,"fill":112,"stroke":113,"style":90},"204","#eef7f4","#0f766e",[73,115,118],{"x":116,"y":94,"style":117,"fill":71,"textAnchor":79},"284","text-anchor:middle;font-size:10px;font-family:sans-serif","inside a national",[73,120,121],{"x":116,"y":99,"style":117,"fill":71,"textAnchor":79},"grid's area of use?",[103,123],{"x1":116,"y1":84,"x2":116,"y2":124,"stroke":71,"style":108},"84",[49,126],{"x":111,"y":127,"width":99,"height":128,"rx":63,"fill":129,"stroke":130,"style":90},"44","36","#e8efe6","#15803d",[73,132,135],{"x":116,"y":133,"style":95,"fill":134,"textAnchor":79},"67","#166534","yes: national grid",[103,137],{"x1":138,"y1":106,"x2":139,"y2":106,"stroke":71,"style":108},"364","396",[49,141],{"x":142,"y":84,"width":99,"height":86,"rx":87,"fill":143,"stroke":144,"style":90},"404","#eff3ff","#2563eb",[73,146,148],{"x":147,"y":94,"style":117,"fill":71,"textAnchor":79},"484","fits in one",[73,150,151],{"x":147,"y":99,"style":117,"fill":71,"textAnchor":79},"UTM zone?",[103,153],{"x1":147,"y1":84,"x2":147,"y2":124,"stroke":71,"style":108},[49,155],{"x":142,"y":127,"width":99,"height":128,"rx":63,"fill":129,"stroke":130,"style":90},[73,157,158],{"x":147,"y":133,"style":95,"fill":134,"textAnchor":79},"yes: that UTM zone",[103,160],{"x1":161,"y1":106,"x2":162,"y2":106,"stroke":71,"style":108},"564","596",[49,164],{"x":165,"y":84,"width":166,"height":86,"rx":87,"fill":167,"stroke":168,"style":90},"604","132","#fdf2e2","#b45309",[73,170,172],{"x":171,"y":94,"style":117,"fill":71,"textAnchor":79},"670","measuring",[73,174,175],{"x":171,"y":99,"style":117,"fill":71,"textAnchor":79},"area or distance?",[103,177],{"x1":178,"y1":179,"x2":180,"y2":181,"stroke":71,"style":108},"640","174","590","222",[103,183],{"x1":184,"y1":179,"x2":184,"y2":185,"stroke":71,"style":108},"700","216",[49,187],{"x":188,"y":189,"width":190,"height":191,"rx":63,"fill":129,"stroke":130,"style":90},"430","226","200","52",[73,193,196],{"x":194,"y":195,"style":95,"fill":134,"textAnchor":79},"530","248","area: equal-area",[73,198,200],{"x":194,"y":199,"style":100,"fill":71,"textAnchor":79},"266","LAEA, Albers",[49,202],{"x":178,"y":181,"width":203,"height":86,"rx":63,"fill":129,"stroke":130,"style":90},"100",[73,205,209],{"x":206,"y":207,"style":208,"fill":134,"textAnchor":79},"690","246","text-anchor:middle;font-size:10px;font-weight:bold;font-family:sans-serif","distance:",[73,211,213],{"x":206,"y":212,"style":100,"fill":71,"textAnchor":79},"264","local AEQD",[215,216,218],"h2",{"id":217},"prerequisites","Prerequisites",[220,221,222,230,238],"ul",{},[223,224,225,229],"li",{},[226,227,228],"strong",{},"QGIS 3.40 LTR"," or newer, or the QGIS 4 series.",[223,231,232,233,237],{},"A layer with a correctly assigned CRS. If it has none, fix that first — see ",[26,234,236],{"href":235},"\u002Fspatial-data-processing-automation\u002Fcoordinate-reference-systems\u002Fhandling-missing-crs-in-pyqgis\u002F","handling missing CRS",".",[223,239,240],{},"A clear statement of what the analysis measures: distances, areas, directions, or just topology.",[215,242,244],{"id":243},"get-the-extent-in-wgs-84","Get the extent in WGS 84",[14,246,247],{},"Every choice below starts from where the data is on the globe. Transform the layer's extent to WGS 84 once and derive everything from it.",[249,250,255],"pre",{"className":251,"code":252,"language":253,"meta":254,"style":254},"language-python shiki shiki-themes github-dark","from qgis.core import (\n    QgsProject, QgsCoordinateReferenceSystem, QgsCoordinateTransform,\n)\n\nlayer = QgsProject.instance().mapLayersByName(\"survey_points\")[0]\nwgs84 = QgsCoordinateReferenceSystem(\"EPSG:4326\")\n\nto_wgs = QgsCoordinateTransform(layer.crs(), wgs84, QgsProject.instance())\next = to_wgs.transformBoundingBox(layer.extent())\ncentre = ext.center()\n\nprint(f\"lon {ext.xMinimum():.3f} to {ext.xMaximum():.3f}, \"\n      f\"lat {ext.yMinimum():.3f} to {ext.yMaximum():.3f}\")\nprint(f\"centre {centre.x():.3f}, {centre.y():.3f}; width {ext.width():.2f}° of longitude\")\n","python","",[18,256,257,275,281,287,294,319,335,340,351,362,373,378,420,454],{"__ignoreMap":254},[258,259,261,265,269,272],"span",{"class":103,"line":260},1,[258,262,264],{"class":263},"snl16","from",[258,266,268],{"class":267},"s95oV"," qgis.core ",[258,270,271],{"class":263},"import",[258,273,274],{"class":267}," (\n",[258,276,278],{"class":103,"line":277},2,[258,279,280],{"class":267},"    QgsProject, QgsCoordinateReferenceSystem, QgsCoordinateTransform,\n",[258,282,284],{"class":103,"line":283},3,[258,285,286],{"class":267},")\n",[258,288,290],{"class":103,"line":289},4,[258,291,293],{"emptyLinePlaceholder":292},true,"\n",[258,295,297,300,303,306,310,313,316],{"class":103,"line":296},5,[258,298,299],{"class":267},"layer ",[258,301,302],{"class":263},"=",[258,304,305],{"class":267}," QgsProject.instance().mapLayersByName(",[258,307,309],{"class":308},"sU2Wk","\"survey_points\"",[258,311,312],{"class":267},")[",[258,314,51],{"class":315},"sDLfK",[258,317,318],{"class":267},"]\n",[258,320,322,325,327,330,333],{"class":103,"line":321},6,[258,323,324],{"class":267},"wgs84 ",[258,326,302],{"class":263},[258,328,329],{"class":267}," QgsCoordinateReferenceSystem(",[258,331,332],{"class":308},"\"EPSG:4326\"",[258,334,286],{"class":267},[258,336,338],{"class":103,"line":337},7,[258,339,293],{"emptyLinePlaceholder":292},[258,341,343,346,348],{"class":103,"line":342},8,[258,344,345],{"class":267},"to_wgs ",[258,347,302],{"class":263},[258,349,350],{"class":267}," QgsCoordinateTransform(layer.crs(), wgs84, QgsProject.instance())\n",[258,352,354,357,359],{"class":103,"line":353},9,[258,355,356],{"class":267},"ext ",[258,358,302],{"class":263},[258,360,361],{"class":267}," to_wgs.transformBoundingBox(layer.extent())\n",[258,363,365,368,370],{"class":103,"line":364},10,[258,366,367],{"class":267},"centre ",[258,369,302],{"class":263},[258,371,372],{"class":267}," ext.center()\n",[258,374,376],{"class":103,"line":375},11,[258,377,293],{"emptyLinePlaceholder":292},[258,379,381,384,387,390,393,396,399,402,405,408,410,413,415,417],{"class":103,"line":380},12,[258,382,383],{"class":315},"print",[258,385,386],{"class":267},"(",[258,388,389],{"class":263},"f",[258,391,392],{"class":308},"\"lon ",[258,394,395],{"class":315},"{",[258,397,398],{"class":267},"ext.xMinimum()",[258,400,401],{"class":263},":.3f",[258,403,404],{"class":315},"}",[258,406,407],{"class":308}," to ",[258,409,395],{"class":315},[258,411,412],{"class":267},"ext.xMaximum()",[258,414,401],{"class":263},[258,416,404],{"class":315},[258,418,419],{"class":308},", \"\n",[258,421,423,426,429,431,434,436,438,440,442,445,447,449,452],{"class":103,"line":422},13,[258,424,425],{"class":263},"      f",[258,427,428],{"class":308},"\"lat ",[258,430,395],{"class":315},[258,432,433],{"class":267},"ext.yMinimum()",[258,435,401],{"class":263},[258,437,404],{"class":315},[258,439,407],{"class":308},[258,441,395],{"class":315},[258,443,444],{"class":267},"ext.yMaximum()",[258,446,401],{"class":263},[258,448,404],{"class":315},[258,450,451],{"class":308},"\"",[258,453,286],{"class":267},[258,455,457,459,461,463,466,468,471,473,475,478,480,483,485,487,490,492,495,498,500,503],{"class":103,"line":456},14,[258,458,383],{"class":315},[258,460,386],{"class":267},[258,462,389],{"class":263},[258,464,465],{"class":308},"\"centre ",[258,467,395],{"class":315},[258,469,470],{"class":267},"centre.x()",[258,472,401],{"class":263},[258,474,404],{"class":315},[258,476,477],{"class":308},", ",[258,479,395],{"class":315},[258,481,482],{"class":267},"centre.y()",[258,484,401],{"class":263},[258,486,404],{"class":315},[258,488,489],{"class":308},"; width ",[258,491,395],{"class":315},[258,493,494],{"class":267},"ext.width()",[258,496,497],{"class":263},":.2f",[258,499,404],{"class":315},[258,501,502],{"class":308},"° of longitude\"",[258,504,286],{"class":267},[14,506,507,510,511,514],{},[226,508,509],{},"Breakdown:"," ",[18,512,513],{},"transformBoundingBox"," densifies the box edges before transforming, so a projected extent maps to a correct geographic box even where edges curve. The width in degrees of longitude is the quantity that decides whether a single UTM zone is enough: zones are six degrees wide, and distortion rises towards their edges.",[215,516,518],{"id":517},"prefer-the-official-grid-where-it-applies","Prefer the official grid where it applies",[14,520,521],{},"National and regional grids — British National Grid, the Dutch RD New, the ETRS89 UTM zones used across Europe, US State Plane zones — are designed for their territory, match the coordinates in official data, and are what your colleagues' layers already use. The CRS's area of use tells you whether the data lies inside it.",[249,523,525],{"className":251,"code":524,"language":253,"meta":254,"style":254},"CANDIDATES = [\"EPSG:27700\", \"EPSG:28992\", \"EPSG:25832\", \"EPSG:25833\", \"EPSG:2154\"]\n\ndef covers(crs_id, box):\n    crs = QgsCoordinateReferenceSystem(crs_id)\n    bounds = crs.bounds()\n    return crs.isValid() and bounds.contains(box), crs\n\nusable = [(cid, crs.description()) for cid in CANDIDATES\n          for ok, crs in [covers(cid, ext)] if ok]\nprint(\"official grids covering the data:\", usable or \"none\")\n",[18,526,527,563,567,579,589,599,613,617,639,658],{"__ignoreMap":254},[258,528,529,532,535,538,541,543,546,548,551,553,556,558,561],{"class":103,"line":260},[258,530,531],{"class":315},"CANDIDATES",[258,533,534],{"class":263}," =",[258,536,537],{"class":267}," [",[258,539,540],{"class":308},"\"EPSG:27700\"",[258,542,477],{"class":267},[258,544,545],{"class":308},"\"EPSG:28992\"",[258,547,477],{"class":267},[258,549,550],{"class":308},"\"EPSG:25832\"",[258,552,477],{"class":267},[258,554,555],{"class":308},"\"EPSG:25833\"",[258,557,477],{"class":267},[258,559,560],{"class":308},"\"EPSG:2154\"",[258,562,318],{"class":267},[258,564,565],{"class":103,"line":277},[258,566,293],{"emptyLinePlaceholder":292},[258,568,569,572,576],{"class":103,"line":283},[258,570,571],{"class":263},"def",[258,573,575],{"class":574},"svObZ"," covers",[258,577,578],{"class":267},"(crs_id, box):\n",[258,580,581,584,586],{"class":103,"line":289},[258,582,583],{"class":267},"    crs ",[258,585,302],{"class":263},[258,587,588],{"class":267}," QgsCoordinateReferenceSystem(crs_id)\n",[258,590,591,594,596],{"class":103,"line":296},[258,592,593],{"class":267},"    bounds ",[258,595,302],{"class":263},[258,597,598],{"class":267}," crs.bounds()\n",[258,600,601,604,607,610],{"class":103,"line":321},[258,602,603],{"class":263},"    return",[258,605,606],{"class":267}," crs.isValid() ",[258,608,609],{"class":263},"and",[258,611,612],{"class":267}," bounds.contains(box), crs\n",[258,614,615],{"class":103,"line":337},[258,616,293],{"emptyLinePlaceholder":292},[258,618,619,622,624,627,630,633,636],{"class":103,"line":342},[258,620,621],{"class":267},"usable ",[258,623,302],{"class":263},[258,625,626],{"class":267}," [(cid, crs.description()) ",[258,628,629],{"class":263},"for",[258,631,632],{"class":267}," cid ",[258,634,635],{"class":263},"in",[258,637,638],{"class":315}," CANDIDATES\n",[258,640,641,644,647,649,652,655],{"class":103,"line":353},[258,642,643],{"class":263},"          for",[258,645,646],{"class":267}," ok, crs ",[258,648,635],{"class":263},[258,650,651],{"class":267}," [covers(cid, ext)] ",[258,653,654],{"class":263},"if",[258,656,657],{"class":267}," ok]\n",[258,659,660,662,664,667,670,673,676],{"class":103,"line":364},[258,661,383],{"class":315},[258,663,386],{"class":267},[258,665,666],{"class":308},"\"official grids covering the data:\"",[258,668,669],{"class":267},", usable ",[258,671,672],{"class":263},"or",[258,674,675],{"class":308}," \"none\"",[258,677,286],{"class":267},[14,679,680,510,682,685],{},[226,681,509],{},[18,683,684],{},"bounds()"," returns the CRS's area of use in WGS 84 as recorded in the EPSG database, so a containment test is a quick, authoritative filter. A candidate list keeps the check fast and relevant — keep it to the grids your organisation actually uses. When one applies, use it even if a UTM zone would be marginally less distorted: matching the coordinates of every other dataset in the organisation is worth more than a few parts per million.",[14,687,688],{},[34,689,692,695,698,701,705,724,729,733,737,741,745,748,753,758,762,765,769,772,775],{"viewBox":690,"role":37,"ariaLabel":691,"xmlns":39},"0 0 760 256","UTM zones as six-degree strips: a dataset inside one strip uses that zone, a dataset straddling two strips suffers growing scale error at the far edge, and zone numbers are computed from longitude with separate north and south EPSG codes",[41,693,694],{},"Six-degree strips, and what happens at the edge",[45,696,697],{},"Four vertical strips labelled zones 29, 30, 31 and 32. A small green dataset sits inside zone 30 and uses EPSG 32630. A wide orange dataset spans zones 30 and 31; using zone 30 for all of it leaves the eastern part up to 1 in 1,000 in scale error. The formula zone equals floor of longitude plus 180 over 6 plus 1 is shown, with EPSG 326 plus zone in the northern hemisphere and 327 plus zone in the southern.",[49,699],{"x":51,"y":51,"width":52,"height":700,"fill":54},"256",[73,702,704],{"x":75,"y":703,"style":77,"fill":78,"textAnchor":79},"26","One zone is fine; two zones is a compromise",[706,707,710,716,718,721],"g",{"stroke":708,"style":709},"#9aa39d","stroke-width:1.5",[49,711],{"x":712,"y":713,"width":714,"height":715,"fill":88},"40","46","120","150",[49,717],{"x":99,"y":713,"width":714,"height":715,"fill":88},[49,719],{"x":720,"y":713,"width":714,"height":715,"fill":88},"280",[49,722],{"x":723,"y":713,"width":714,"height":715,"fill":88},"400",[73,725,728],{"x":203,"y":726,"style":727,"fill":89,"textAnchor":79},"68","text-anchor:middle;font-size:10.5px;font-family:sans-serif","zone 29",[73,730,732],{"x":731,"y":726,"style":727,"fill":89,"textAnchor":79},"220","zone 30",[73,734,736],{"x":735,"y":726,"style":727,"fill":89,"textAnchor":79},"340","zone 31",[73,738,740],{"x":739,"y":726,"style":727,"fill":89,"textAnchor":79},"460","zone 32",[68,742],{"d":743,"fill":130,"style":744},"M190 96 L250 90 L256 128 L196 134 z","opacity:0.8",[68,746],{"d":747,"fill":168,"style":744},"M230 146 L380 140 L384 180 L234 186 z",[49,749],{"x":750,"y":713,"width":751,"height":752,"rx":87,"fill":88,"stroke":89,"style":90},"544","192","190",[73,754,757],{"x":178,"y":755,"style":756,"fill":78,"textAnchor":79},"72","text-anchor:middle;font-size:11px;font-weight:bold;font-family:sans-serif","zone from longitude",[73,759,761],{"x":178,"y":203,"style":760,"fill":71,"textAnchor":79},"text-anchor:middle;font-size:10px;font-family:monospace","floor((lon+180)\u002F6)+1",[73,763,764],{"x":178,"y":166,"style":760,"fill":71,"textAnchor":79},"north: EPSG:326zz",[73,766,768],{"x":178,"y":767,"style":760,"fill":71,"textAnchor":79},"154","south: EPSG:327zz",[73,770,771],{"x":178,"y":107,"style":100,"fill":134,"textAnchor":79},"green: inside zone 30",[73,773,774],{"x":178,"y":185,"style":100,"fill":168,"textAnchor":79},"orange: spans 30 and 31",[73,776,777],{"x":720,"y":189,"style":117,"fill":71,"textAnchor":79},"scale error grows towards a zone's edges",[215,779,781],{"id":780},"compute-the-utm-zone","Compute the UTM zone",[14,783,784],{},"When no official grid covers the data and it spans less than a zone, WGS 84 UTM is a safe, universal choice. The zone and hemisphere follow directly from the centre of the extent.",[249,786,788],{"className":251,"code":787,"language":253,"meta":254,"style":254},"import math\n\ndef utm_crs_for(box):\n    lon, lat = box.center().x(), box.center().y()\n    zone = int(math.floor((lon + 180) \u002F 6)) + 1\n    zone = min(max(zone, 1), 60)\n    epsg = (32600 if lat >= 0 else 32700) + zone\n    crs = QgsCoordinateReferenceSystem(f\"EPSG:{epsg}\")\n    zones_spanned = (int(math.floor((box.xMaximum() + 180) \u002F 6))\n                     - int(math.floor((box.xMinimum() + 180) \u002F 6)) + 1)\n    return crs, zones_spanned\n\nutm, spanned = utm_crs_for(ext)\nprint(utm.authid(), utm.description(), \"| zones spanned:\", spanned)\nif spanned > 1:\n    print(\"extent crosses a zone boundary — consider an equal-area or local projection\")\n",[18,789,790,797,801,811,821,857,885,923,947,975,1004,1011,1015,1025,1038,1054],{"__ignoreMap":254},[258,791,792,794],{"class":103,"line":260},[258,793,271],{"class":263},[258,795,796],{"class":267}," math\n",[258,798,799],{"class":103,"line":277},[258,800,293],{"emptyLinePlaceholder":292},[258,802,803,805,808],{"class":103,"line":283},[258,804,571],{"class":263},[258,806,807],{"class":574}," utm_crs_for",[258,809,810],{"class":267},"(box):\n",[258,812,813,816,818],{"class":103,"line":289},[258,814,815],{"class":267},"    lon, lat ",[258,817,302],{"class":263},[258,819,820],{"class":267}," box.center().x(), box.center().y()\n",[258,822,823,826,828,831,834,837,840,843,846,849,852,854],{"class":103,"line":296},[258,824,825],{"class":267},"    zone ",[258,827,302],{"class":263},[258,829,830],{"class":315}," int",[258,832,833],{"class":267},"(math.floor((lon ",[258,835,836],{"class":263},"+",[258,838,839],{"class":315}," 180",[258,841,842],{"class":267},") ",[258,844,845],{"class":263},"\u002F",[258,847,848],{"class":315}," 6",[258,850,851],{"class":267},")) ",[258,853,836],{"class":263},[258,855,856],{"class":315}," 1\n",[258,858,859,861,863,866,868,871,874,877,880,883],{"class":103,"line":321},[258,860,825],{"class":267},[258,862,302],{"class":263},[258,864,865],{"class":315}," min",[258,867,386],{"class":267},[258,869,870],{"class":315},"max",[258,872,873],{"class":267},"(zone, ",[258,875,876],{"class":315},"1",[258,878,879],{"class":267},"), ",[258,881,882],{"class":315},"60",[258,884,286],{"class":267},[258,886,887,890,892,895,898,901,904,907,910,913,916,918,920],{"class":103,"line":337},[258,888,889],{"class":267},"    epsg ",[258,891,302],{"class":263},[258,893,894],{"class":267}," (",[258,896,897],{"class":315},"32600",[258,899,900],{"class":263}," if",[258,902,903],{"class":267}," lat ",[258,905,906],{"class":263},">=",[258,908,909],{"class":315}," 0",[258,911,912],{"class":263}," else",[258,914,915],{"class":315}," 32700",[258,917,842],{"class":267},[258,919,836],{"class":263},[258,921,922],{"class":267}," zone\n",[258,924,925,927,929,931,933,936,938,941,943,945],{"class":103,"line":342},[258,926,583],{"class":267},[258,928,302],{"class":263},[258,930,329],{"class":267},[258,932,389],{"class":263},[258,934,935],{"class":308},"\"EPSG:",[258,937,395],{"class":315},[258,939,940],{"class":267},"epsg",[258,942,404],{"class":315},[258,944,451],{"class":308},[258,946,286],{"class":267},[258,948,949,952,954,956,959,962,964,966,968,970,972],{"class":103,"line":353},[258,950,951],{"class":267},"    zones_spanned ",[258,953,302],{"class":263},[258,955,894],{"class":267},[258,957,958],{"class":315},"int",[258,960,961],{"class":267},"(math.floor((box.xMaximum() ",[258,963,836],{"class":263},[258,965,839],{"class":315},[258,967,842],{"class":267},[258,969,845],{"class":263},[258,971,848],{"class":315},[258,973,974],{"class":267},"))\n",[258,976,977,980,982,985,987,989,991,993,995,997,999,1002],{"class":103,"line":364},[258,978,979],{"class":263},"                     -",[258,981,830],{"class":315},[258,983,984],{"class":267},"(math.floor((box.xMinimum() ",[258,986,836],{"class":263},[258,988,839],{"class":315},[258,990,842],{"class":267},[258,992,845],{"class":263},[258,994,848],{"class":315},[258,996,851],{"class":267},[258,998,836],{"class":263},[258,1000,1001],{"class":315}," 1",[258,1003,286],{"class":267},[258,1005,1006,1008],{"class":103,"line":375},[258,1007,603],{"class":263},[258,1009,1010],{"class":267}," crs, zones_spanned\n",[258,1012,1013],{"class":103,"line":380},[258,1014,293],{"emptyLinePlaceholder":292},[258,1016,1017,1020,1022],{"class":103,"line":422},[258,1018,1019],{"class":267},"utm, spanned ",[258,1021,302],{"class":263},[258,1023,1024],{"class":267}," utm_crs_for(ext)\n",[258,1026,1027,1029,1032,1035],{"class":103,"line":456},[258,1028,383],{"class":315},[258,1030,1031],{"class":267},"(utm.authid(), utm.description(), ",[258,1033,1034],{"class":308},"\"| zones spanned:\"",[258,1036,1037],{"class":267},", spanned)\n",[258,1039,1041,1043,1046,1049,1051],{"class":103,"line":1040},15,[258,1042,654],{"class":263},[258,1044,1045],{"class":267}," spanned ",[258,1047,1048],{"class":263},">",[258,1050,1001],{"class":315},[258,1052,1053],{"class":267},":\n",[258,1055,1057,1060,1062,1065],{"class":103,"line":1056},16,[258,1058,1059],{"class":315},"    print",[258,1061,386],{"class":267},[258,1063,1064],{"class":308},"\"extent crosses a zone boundary — consider an equal-area or local projection\"",[258,1066,286],{"class":267},[14,1068,1069,1071],{},[226,1070,509],{}," The formula maps longitudes to zones 1 to 60, and the clamp handles the antimeridian edge case of exactly 180°. EPSG codes 32601–32660 are the northern hemisphere zones and 32701–32760 the southern; the hemisphere matters because southern zones use a false northing of 10,000 km so coordinates stay positive. Norway and Svalbard have irregular zones that this simple formula ignores; for data there, use the national ETRS89 zones instead. Counting the zones spanned is the flag for the next section.",[215,1073,1075],{"id":1074},"area-statistics-and-large-extents","Area statistics and large extents",[14,1077,1078],{},"UTM preserves shapes and local distances well, but not area across large regions. When the output is an area — hectares of forest per province, land cover shares across a continent — use an equal-area projection so a square kilometre in the north counts the same as one in the south. When the output is distance over a large area, use a projection centred on the data.",[249,1080,1082],{"className":251,"code":1081,"language":253,"meta":254,"style":254},"from qgis.core import QgsDistanceArea\n\nEQUAL_AREA = {\n    \"europe\": \"EPSG:3035\",\n    \"north_america\": \"ESRI:102008\",\n    \"world\": \"EPSG:6933\",\n}\n\nlaea = QgsCoordinateReferenceSystem(EQUAL_AREA[\"europe\"])\n\ncentred = QgsCoordinateReferenceSystem.fromProj(\n    f\"+proj=aeqd +lat_0={centre.y():.4f} +lon_0={centre.x():.4f} \"\n    \"+x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs\")\n\ndef distortion_report(layer, target):\n    da = QgsDistanceArea()\n    da.setSourceCrs(layer.crs(), QgsProject.instance().transformContext())\n    da.setEllipsoid(\"EPSG:7030\")\n    xf = QgsCoordinateTransform(layer.crs(), target, QgsProject.instance())\n    ratios = []\n    for f in layer.getFeatures():\n        g = f.geometry()\n        if g.isEmpty() or g.area() == 0:\n            continue\n        true_area = da.measureArea(g)\n        g.transform(xf)\n        ratios.append(g.area() \u002F true_area)\n    return min(ratios), max(ratios)\n\nparcels = QgsProject.instance().mapLayersByName(\"land_parcels\")[0]\nfor label, crs in ((\"UTM\", utm), (\"LAEA Europe\", laea), (\"local AEQD\", centred)):\n    lo, hi = distortion_report(parcels, crs)\n    print(f\"{label:\u003C12} planar\u002Fellipsoidal area {lo:.5f} – {hi:.5f}\")\n",[18,1083,1084,1095,1099,1109,1123,1135,1147,1152,1156,1176,1180,1190,1221,1228,1232,1242,1252,1258,1269,1280,1291,1305,1316,1337,1343,1354,1360,1371,1386,1391,1410,1441,1452],{"__ignoreMap":254},[258,1085,1086,1088,1090,1092],{"class":103,"line":260},[258,1087,264],{"class":263},[258,1089,268],{"class":267},[258,1091,271],{"class":263},[258,1093,1094],{"class":267}," QgsDistanceArea\n",[258,1096,1097],{"class":103,"line":277},[258,1098,293],{"emptyLinePlaceholder":292},[258,1100,1101,1104,1106],{"class":103,"line":283},[258,1102,1103],{"class":315},"EQUAL_AREA",[258,1105,534],{"class":263},[258,1107,1108],{"class":267}," {\n",[258,1110,1111,1114,1117,1120],{"class":103,"line":289},[258,1112,1113],{"class":308},"    \"europe\"",[258,1115,1116],{"class":267},": ",[258,1118,1119],{"class":308},"\"EPSG:3035\"",[258,1121,1122],{"class":267},",\n",[258,1124,1125,1128,1130,1133],{"class":103,"line":296},[258,1126,1127],{"class":308},"    \"north_america\"",[258,1129,1116],{"class":267},[258,1131,1132],{"class":308},"\"ESRI:102008\"",[258,1134,1122],{"class":267},[258,1136,1137,1140,1142,1145],{"class":103,"line":321},[258,1138,1139],{"class":308},"    \"world\"",[258,1141,1116],{"class":267},[258,1143,1144],{"class":308},"\"EPSG:6933\"",[258,1146,1122],{"class":267},[258,1148,1149],{"class":103,"line":337},[258,1150,1151],{"class":267},"}\n",[258,1153,1154],{"class":103,"line":342},[258,1155,293],{"emptyLinePlaceholder":292},[258,1157,1158,1161,1163,1165,1167,1170,1173],{"class":103,"line":353},[258,1159,1160],{"class":267},"laea ",[258,1162,302],{"class":263},[258,1164,329],{"class":267},[258,1166,1103],{"class":315},[258,1168,1169],{"class":267},"[",[258,1171,1172],{"class":308},"\"europe\"",[258,1174,1175],{"class":267},"])\n",[258,1177,1178],{"class":103,"line":364},[258,1179,293],{"emptyLinePlaceholder":292},[258,1181,1182,1185,1187],{"class":103,"line":375},[258,1183,1184],{"class":267},"centred ",[258,1186,302],{"class":263},[258,1188,1189],{"class":267}," QgsCoordinateReferenceSystem.fromProj(\n",[258,1191,1192,1195,1198,1200,1202,1205,1207,1210,1212,1214,1216,1218],{"class":103,"line":380},[258,1193,1194],{"class":263},"    f",[258,1196,1197],{"class":308},"\"+proj=aeqd +lat_0=",[258,1199,395],{"class":315},[258,1201,482],{"class":267},[258,1203,1204],{"class":263},":.4f",[258,1206,404],{"class":315},[258,1208,1209],{"class":308}," +lon_0=",[258,1211,395],{"class":315},[258,1213,470],{"class":267},[258,1215,1204],{"class":263},[258,1217,404],{"class":315},[258,1219,1220],{"class":308}," \"\n",[258,1222,1223,1226],{"class":103,"line":422},[258,1224,1225],{"class":308},"    \"+x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs\"",[258,1227,286],{"class":267},[258,1229,1230],{"class":103,"line":456},[258,1231,293],{"emptyLinePlaceholder":292},[258,1233,1234,1236,1239],{"class":103,"line":1040},[258,1235,571],{"class":263},[258,1237,1238],{"class":574}," distortion_report",[258,1240,1241],{"class":267},"(layer, target):\n",[258,1243,1244,1247,1249],{"class":103,"line":1056},[258,1245,1246],{"class":267},"    da ",[258,1248,302],{"class":263},[258,1250,1251],{"class":267}," QgsDistanceArea()\n",[258,1253,1255],{"class":103,"line":1254},17,[258,1256,1257],{"class":267},"    da.setSourceCrs(layer.crs(), QgsProject.instance().transformContext())\n",[258,1259,1261,1264,1267],{"class":103,"line":1260},18,[258,1262,1263],{"class":267},"    da.setEllipsoid(",[258,1265,1266],{"class":308},"\"EPSG:7030\"",[258,1268,286],{"class":267},[258,1270,1272,1275,1277],{"class":103,"line":1271},19,[258,1273,1274],{"class":267},"    xf ",[258,1276,302],{"class":263},[258,1278,1279],{"class":267}," QgsCoordinateTransform(layer.crs(), target, QgsProject.instance())\n",[258,1281,1283,1286,1288],{"class":103,"line":1282},20,[258,1284,1285],{"class":267},"    ratios ",[258,1287,302],{"class":263},[258,1289,1290],{"class":267}," []\n",[258,1292,1294,1297,1300,1302],{"class":103,"line":1293},21,[258,1295,1296],{"class":263},"    for",[258,1298,1299],{"class":267}," f ",[258,1301,635],{"class":263},[258,1303,1304],{"class":267}," layer.getFeatures():\n",[258,1306,1308,1311,1313],{"class":103,"line":1307},22,[258,1309,1310],{"class":267},"        g ",[258,1312,302],{"class":263},[258,1314,1315],{"class":267}," f.geometry()\n",[258,1317,1319,1322,1325,1327,1330,1333,1335],{"class":103,"line":1318},23,[258,1320,1321],{"class":263},"        if",[258,1323,1324],{"class":267}," g.isEmpty() ",[258,1326,672],{"class":263},[258,1328,1329],{"class":267}," g.area() ",[258,1331,1332],{"class":263},"==",[258,1334,909],{"class":315},[258,1336,1053],{"class":267},[258,1338,1340],{"class":103,"line":1339},24,[258,1341,1342],{"class":263},"            continue\n",[258,1344,1346,1349,1351],{"class":103,"line":1345},25,[258,1347,1348],{"class":267},"        true_area ",[258,1350,302],{"class":263},[258,1352,1353],{"class":267}," da.measureArea(g)\n",[258,1355,1357],{"class":103,"line":1356},26,[258,1358,1359],{"class":267},"        g.transform(xf)\n",[258,1361,1363,1366,1368],{"class":103,"line":1362},27,[258,1364,1365],{"class":267},"        ratios.append(g.area() ",[258,1367,845],{"class":263},[258,1369,1370],{"class":267}," true_area)\n",[258,1372,1374,1376,1378,1381,1383],{"class":103,"line":1373},28,[258,1375,603],{"class":263},[258,1377,865],{"class":315},[258,1379,1380],{"class":267},"(ratios), ",[258,1382,870],{"class":315},[258,1384,1385],{"class":267},"(ratios)\n",[258,1387,1389],{"class":103,"line":1388},29,[258,1390,293],{"emptyLinePlaceholder":292},[258,1392,1394,1397,1399,1401,1404,1406,1408],{"class":103,"line":1393},30,[258,1395,1396],{"class":267},"parcels ",[258,1398,302],{"class":263},[258,1400,305],{"class":267},[258,1402,1403],{"class":308},"\"land_parcels\"",[258,1405,312],{"class":267},[258,1407,51],{"class":315},[258,1409,318],{"class":267},[258,1411,1413,1415,1418,1420,1423,1426,1429,1432,1435,1438],{"class":103,"line":1412},31,[258,1414,629],{"class":263},[258,1416,1417],{"class":267}," label, crs ",[258,1419,635],{"class":263},[258,1421,1422],{"class":267}," ((",[258,1424,1425],{"class":308},"\"UTM\"",[258,1427,1428],{"class":267},", utm), (",[258,1430,1431],{"class":308},"\"LAEA Europe\"",[258,1433,1434],{"class":267},", laea), (",[258,1436,1437],{"class":308},"\"local AEQD\"",[258,1439,1440],{"class":267},", centred)):\n",[258,1442,1444,1447,1449],{"class":103,"line":1443},32,[258,1445,1446],{"class":267},"    lo, hi ",[258,1448,302],{"class":263},[258,1450,1451],{"class":267}," distortion_report(parcels, crs)\n",[258,1453,1455,1457,1459,1461,1463,1465,1468,1471,1473,1476,1478,1481,1484,1486,1489,1491,1494,1496,1498,1500],{"class":103,"line":1454},33,[258,1456,1059],{"class":315},[258,1458,386],{"class":267},[258,1460,389],{"class":263},[258,1462,451],{"class":308},[258,1464,395],{"class":315},[258,1466,1467],{"class":267},"label",[258,1469,1470],{"class":263},":\u003C12",[258,1472,404],{"class":315},[258,1474,1475],{"class":308}," planar\u002Fellipsoidal area ",[258,1477,395],{"class":315},[258,1479,1480],{"class":267},"lo",[258,1482,1483],{"class":263},":.5f",[258,1485,404],{"class":315},[258,1487,1488],{"class":308}," – ",[258,1490,395],{"class":315},[258,1492,1493],{"class":267},"hi",[258,1495,1483],{"class":263},[258,1497,404],{"class":315},[258,1499,451],{"class":308},[258,1501,286],{"class":267},[14,1503,1504,510,1506,1509,1510,1513,1514,237],{},[226,1505,509],{},[18,1507,1508],{},"QgsDistanceArea"," with an ellipsoid measures areas on the ellipsoid itself, which is the reference any planar area should be compared against. The ratio of planar to ellipsoidal area per feature shows how much a projection inflates or shrinks areas across the dataset: an equal-area projection gives ratios within a few parts per million everywhere, while UTM drifts by a part in a thousand or more far from its central meridian. ",[18,1511,1512],{},"ESRI:"," codes are available because PROJ ships the Esri registry alongside EPSG. The azimuthal equidistant projection centred on the data preserves distances from its centre, which suits service-radius and travel-distance work over a region too big for one UTM zone. The planar-versus-ellipsoidal distinction is also discussed in ",[26,1515,1517],{"href":1516},"\u002Fspatial-data-processing-automation\u002Fvector-data-manipulation\u002Fpyqgis-script-to-calculate-polygon-areas\u002F","calculating polygon areas",[14,1519,1520],{},[34,1521,1524,1527,1530,1533,1540,1543,1547,1552,1556,1561,1564,1568,1571,1573,1575,1579,1582,1586,1589,1593,1596,1602],{"viewBox":1522,"role":37,"ariaLabel":1523,"xmlns":39},"0 0 760 236","A reproject-analyse-reproject pipeline: the source layer stays in its original CRS, a temporary copy is reprojected to the analysis CRS, measurements and buffers are computed there, and results are reprojected back or joined by id to the original",[41,1525,1526],{},"Reproject for the analysis, not for storage",[45,1528,1529],{},"The source layer in EPSG 4326 is reprojected to a temporary layer in the chosen analysis CRS. Buffers, distances and areas are computed on the temporary layer. Numeric results are joined back to the source by feature id, and any output geometry is reprojected back to the original CRS or delivered in the analysis CRS with the choice documented.",[49,1531],{"x":51,"y":51,"width":52,"height":1532,"fill":54},"236",[56,1534,1535],{},[59,1536,1538],{"id":1537,"viewBox":62,"refX":63,"refY":64,"markerWidth":65,"markerHeight":65,"orient":66},"pcrsPipeArrow",[68,1539],{"d":70,"fill":71},[73,1541,1542],{"x":75,"y":703,"style":77,"fill":78,"textAnchor":79},"Measure in metres, deliver in the source CRS",[49,1544],{"x":83,"y":1545,"width":715,"height":1546,"rx":87,"fill":88,"stroke":89,"style":90},"70","90",[73,1548,1551],{"x":1549,"y":1550,"style":95,"fill":78,"textAnchor":79},"99","104","source",[73,1553,1555],{"x":1549,"y":1554,"style":760,"fill":71,"textAnchor":79},"126","EPSG:4326",[103,1557],{"x1":179,"y1":1558,"x2":1559,"y2":1558,"stroke":71,"style":1560},"115","206","stroke-width:1.8;marker-end:url(#pcrsPipeArrow)",[49,1562],{"x":1563,"y":1545,"width":715,"height":1546,"rx":87,"fill":143,"stroke":144,"style":90},"214",[73,1565,1567],{"x":1566,"y":1550,"style":95,"fill":144,"textAnchor":79},"289","reproject",[73,1569,1570],{"x":1566,"y":1554,"style":117,"fill":71,"textAnchor":79},"temporary copy",[103,1572],{"x1":138,"y1":1558,"x2":139,"y2":1558,"stroke":71,"style":1560},[49,1574],{"x":142,"y":1545,"width":715,"height":1546,"rx":87,"fill":112,"stroke":113,"style":90},[73,1576,1578],{"x":1577,"y":1550,"style":95,"fill":113,"textAnchor":79},"479","analyse",[73,1580,1581],{"x":1577,"y":1554,"style":117,"fill":71,"textAnchor":79},"buffers, areas",[103,1583],{"x1":1584,"y1":1558,"x2":1585,"y2":1558,"stroke":71,"style":1560},"554","586",[49,1587],{"x":1588,"y":1545,"width":94,"height":1546,"rx":87,"fill":129,"stroke":130,"style":90},"594",[73,1590,1592],{"x":1591,"y":1550,"style":95,"fill":134,"textAnchor":79},"665","deliver",[73,1594,1595],{"x":1591,"y":1554,"style":117,"fill":71,"textAnchor":79},"join or reproject",[49,1597],{"x":714,"y":1598,"width":1599,"height":1600,"rx":63,"fill":88,"stroke":89,"style":1601},"188","520","30","stroke-width:1.8",[73,1603,1605],{"x":75,"y":1604,"style":727,"fill":71,"textAnchor":79},"208","record the analysis CRS in the output metadata",[215,1607,1609],{"id":1608},"reproject-only-for-the-analysis","Reproject only for the analysis",[14,1611,1612],{},"Reprojecting the stored data is rarely necessary. Reproject a temporary copy, do the metric work there, and bring results back — numbers by joining on id, geometries by reprojecting.",[249,1614,1616],{"className":251,"code":1615,"language":253,"meta":254,"style":254},"import processing\n\nanalysis_crs = next((QgsCoordinateReferenceSystem(cid) for cid, _ in usable), utm)\n\nwork = processing.run(\"native:reprojectlayer\", {\n    \"INPUT\": layer, \"TARGET_CRS\": analysis_crs, \"OUTPUT\": \"TEMPORARY_OUTPUT\",\n})[\"OUTPUT\"]\n\nbuffers = processing.run(\"native:buffer\", {\n    \"INPUT\": work, \"DISTANCE\": 250, \"SEGMENTS\": 16, \"DISSOLVE\": False,\n    \"OUTPUT\": \"TEMPORARY_OUTPUT\",\n})[\"OUTPUT\"]\n\ndelivered = processing.run(\"native:reprojectlayer\", {\n    \"INPUT\": buffers, \"TARGET_CRS\": layer.crs(),\n    \"OUTPUT\": \"\u002Fdata\u002Fwork\u002Fsurvey_buffers_250m.gpkg\",\n})[\"OUTPUT\"]\nprint(\"buffers computed in\", analysis_crs.authid(), \"delivered in\", layer.crs().authid())\n",[18,1617,1618,1625,1629,1652,1656,1672,1696,1705,1709,1723,1760,1771,1779,1783,1796,1808,1819,1827],{"__ignoreMap":254},[258,1619,1620,1622],{"class":103,"line":260},[258,1621,271],{"class":263},[258,1623,1624],{"class":267}," processing\n",[258,1626,1627],{"class":103,"line":277},[258,1628,293],{"emptyLinePlaceholder":292},[258,1630,1631,1634,1636,1639,1642,1644,1647,1649],{"class":103,"line":283},[258,1632,1633],{"class":267},"analysis_crs ",[258,1635,302],{"class":263},[258,1637,1638],{"class":315}," next",[258,1640,1641],{"class":267},"((QgsCoordinateReferenceSystem(cid) ",[258,1643,629],{"class":263},[258,1645,1646],{"class":267}," cid, _ ",[258,1648,635],{"class":263},[258,1650,1651],{"class":267}," usable), utm)\n",[258,1653,1654],{"class":103,"line":289},[258,1655,293],{"emptyLinePlaceholder":292},[258,1657,1658,1661,1663,1666,1669],{"class":103,"line":296},[258,1659,1660],{"class":267},"work ",[258,1662,302],{"class":263},[258,1664,1665],{"class":267}," processing.run(",[258,1667,1668],{"class":308},"\"native:reprojectlayer\"",[258,1670,1671],{"class":267},", {\n",[258,1673,1674,1677,1680,1683,1686,1689,1691,1694],{"class":103,"line":321},[258,1675,1676],{"class":308},"    \"INPUT\"",[258,1678,1679],{"class":267},": layer, ",[258,1681,1682],{"class":308},"\"TARGET_CRS\"",[258,1684,1685],{"class":267},": analysis_crs, ",[258,1687,1688],{"class":308},"\"OUTPUT\"",[258,1690,1116],{"class":267},[258,1692,1693],{"class":308},"\"TEMPORARY_OUTPUT\"",[258,1695,1122],{"class":267},[258,1697,1698,1701,1703],{"class":103,"line":337},[258,1699,1700],{"class":267},"})[",[258,1702,1688],{"class":308},[258,1704,318],{"class":267},[258,1706,1707],{"class":103,"line":342},[258,1708,293],{"emptyLinePlaceholder":292},[258,1710,1711,1714,1716,1718,1721],{"class":103,"line":353},[258,1712,1713],{"class":267},"buffers ",[258,1715,302],{"class":263},[258,1717,1665],{"class":267},[258,1719,1720],{"class":308},"\"native:buffer\"",[258,1722,1671],{"class":267},[258,1724,1725,1727,1730,1733,1735,1738,1740,1743,1745,1748,1750,1753,1755,1758],{"class":103,"line":364},[258,1726,1676],{"class":308},[258,1728,1729],{"class":267},": work, ",[258,1731,1732],{"class":308},"\"DISTANCE\"",[258,1734,1116],{"class":267},[258,1736,1737],{"class":315},"250",[258,1739,477],{"class":267},[258,1741,1742],{"class":308},"\"SEGMENTS\"",[258,1744,1116],{"class":267},[258,1746,1747],{"class":315},"16",[258,1749,477],{"class":267},[258,1751,1752],{"class":308},"\"DISSOLVE\"",[258,1754,1116],{"class":267},[258,1756,1757],{"class":315},"False",[258,1759,1122],{"class":267},[258,1761,1762,1765,1767,1769],{"class":103,"line":375},[258,1763,1764],{"class":308},"    \"OUTPUT\"",[258,1766,1116],{"class":267},[258,1768,1693],{"class":308},[258,1770,1122],{"class":267},[258,1772,1773,1775,1777],{"class":103,"line":380},[258,1774,1700],{"class":267},[258,1776,1688],{"class":308},[258,1778,318],{"class":267},[258,1780,1781],{"class":103,"line":422},[258,1782,293],{"emptyLinePlaceholder":292},[258,1784,1785,1788,1790,1792,1794],{"class":103,"line":456},[258,1786,1787],{"class":267},"delivered ",[258,1789,302],{"class":263},[258,1791,1665],{"class":267},[258,1793,1668],{"class":308},[258,1795,1671],{"class":267},[258,1797,1798,1800,1803,1805],{"class":103,"line":1040},[258,1799,1676],{"class":308},[258,1801,1802],{"class":267},": buffers, ",[258,1804,1682],{"class":308},[258,1806,1807],{"class":267},": layer.crs(),\n",[258,1809,1810,1812,1814,1817],{"class":103,"line":1056},[258,1811,1764],{"class":308},[258,1813,1116],{"class":267},[258,1815,1816],{"class":308},"\"\u002Fdata\u002Fwork\u002Fsurvey_buffers_250m.gpkg\"",[258,1818,1122],{"class":267},[258,1820,1821,1823,1825],{"class":103,"line":1254},[258,1822,1700],{"class":267},[258,1824,1688],{"class":308},[258,1826,318],{"class":267},[258,1828,1829,1831,1833,1836,1839,1842],{"class":103,"line":1260},[258,1830,383],{"class":315},[258,1832,386],{"class":267},[258,1834,1835],{"class":308},"\"buffers computed in\"",[258,1837,1838],{"class":267},", analysis_crs.authid(), ",[258,1840,1841],{"class":308},"\"delivered in\"",[258,1843,1844],{"class":267},", layer.crs().authid())\n",[14,1846,1847,1849,1850,237],{},[226,1848,509],{}," The analysis CRS is the first official grid that covered the data, falling back to the computed UTM zone — the decision logic from this guide in one line. Buffering in metres in a projected CRS and then reprojecting to WGS 84 gives buffers that are correct on the ground and slightly egg-shaped on a lon\u002Flat map, which is the truthful result. Delivering in the source CRS keeps the output compatible with whatever the data owner uses; delivering in the analysis CRS is equally valid if documented. Buffering itself is covered in ",[26,1851,1853],{"href":1852},"\u002Fspatial-data-processing-automation\u002Fgeometry-operations-and-predicates\u002Fbuffer-geometry-pyqgis\u002F","buffering a geometry",[215,1855,1857],{"id":1856},"qgis-version-compatibility","QGIS version compatibility",[14,1859,1860,1863,1864,1866,1867,1870,1871,1874,1875,1878],{},[18,1861,1862],{},"QgsCoordinateReferenceSystem.bounds()"," and ",[18,1865,513],{}," have been available since QGIS 3.0; ",[18,1868,1869],{},"fromProj"," since 3.10. ",[18,1872,1873],{},"QgsDistanceArea.measureArea"," has been stable throughout 3.x. Esri codes such as ",[18,1876,1877],{},"ESRI:102008"," are available wherever PROJ 6 or later is bundled, which covers every supported release and the QGIS 4 series.",[215,1880,1882],{"id":1881},"troubleshooting","Troubleshooting",[220,1884,1885,1891,1897,1903,1911],{},[223,1886,1887,1890],{},[226,1888,1889],{},"Buffers are huge or tiny."," The distance was applied in degrees; reproject first.",[223,1892,1893,1896],{},[226,1894,1895],{},"Areas differ between colleagues by a fraction of a percent."," Different analysis CRSs; agree one and document it.",[223,1898,1899,1902],{},[226,1900,1901],{},"UTM coordinates are negative or enormous."," Wrong hemisphere code, or the data is far outside the zone.",[223,1904,1905,1910],{},[226,1906,1907,1909],{},[18,1908,684],{}," is empty."," The CRS has no recorded area of use, typical for custom definitions.",[223,1912,1913,1916],{},[226,1914,1915],{},"An equal-area result looks distorted on the map."," Equal-area projections trade shape for area; display in another CRS if needed.",[215,1918,1920],{"id":1919},"conclusion","Conclusion",[14,1922,1923],{},"Transform the extent to WGS 84, prefer an official grid whose area of use covers the data, fall back to the computed UTM zone for compact extents, and use an equal-area or data-centred projection when the extent is large or the output is an area. Confirm the choice with a planar-versus-ellipsoidal comparison, reproject a temporary copy for the analysis, and document the CRS you measured in.",[215,1925,1927],{"id":1926},"frequently-asked-questions","Frequently Asked Questions",[14,1929,1930,1933],{},[226,1931,1932],{},"Is Web Mercator ever suitable for analysis?","\nNo. EPSG:3857 inflates scale by a factor of 1\u002Fcos(latitude) — about 60% at 50° north — so distances and areas are badly wrong away from the equator.",[14,1935,1936,1939,1940,1942],{},[226,1937,1938],{},"Can I avoid projecting by measuring on the ellipsoid?","\nFor individual lengths and areas, yes, with ",[18,1941,1508],{},". Buffers, grids and interpolation still need planar coordinates.",[14,1944,1945,1948],{},[226,1946,1947],{},"What about data spanning the antimeridian?","\nUse a projection centred on the data, such as a local azimuthal equidistant, so coordinates are continuous across 180°.",[14,1950,1951,1954],{},[226,1952,1953],{},"Should the project CRS match the analysis CRS?","\nIt does not have to. Processing uses layer CRSs; the project CRS only affects display and on-the-fly measurements.",[215,1956,1958],{"id":1957},"related","Related",[220,1960,1961,1966,1972,1978,1983],{},[223,1962,1963,1965],{},[26,1964,29],{"href":28}," — the guide this recipe belongs to",[223,1967,1968],{},[26,1969,1971],{"href":1970},"\u002Fspatial-data-processing-automation\u002Fcoordinate-reference-systems\u002Fcreate-custom-crs-from-proj-string-pyqgis\u002F","Create a Custom CRS from a PROJ String in PyQGIS",[223,1973,1974],{},[26,1975,1977],{"href":1976},"\u002Fspatial-data-processing-automation\u002Fcoordinate-reference-systems\u002Fset-project-crs-and-datum-transform-pyqgis\u002F","Set the Project CRS and Datum Transform in PyQGIS",[223,1979,1980],{},[26,1981,1982],{"href":1516},"PyQGIS Script to Calculate Polygon Areas",[223,1984,1985],{},[26,1986,1987],{"href":1852},"Buffer a Geometry in PyQGIS",[1989,1990,1991],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}",{"title":254,"searchDepth":277,"depth":277,"links":1993},[1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004],{"id":217,"depth":277,"text":218},{"id":243,"depth":277,"text":244},{"id":517,"depth":277,"text":518},{"id":780,"depth":277,"text":781},{"id":1074,"depth":277,"text":1075},{"id":1608,"depth":277,"text":1609},{"id":1856,"depth":277,"text":1857},{"id":1881,"depth":277,"text":1882},{"id":1919,"depth":277,"text":1920},{"id":1926,"depth":277,"text":1927},{"id":1957,"depth":277,"text":1958},"Pick a projected CRS that suits the measurement — national grids, the right UTM zone computed from a layer's extent, equal-area projections for area statistics — then check its distortion against ellipsoidal measurements and reproject only for the analysis step.","md",{"slug":2008,"type":2009,"breadcrumb":2010,"datePublished":2011,"dateModified":2011},"choose-projected-crs-for-analysis-pyqgis","article","Choose a Projected CRS for Analysis","2026-09-17","\u002Fspatial-data-processing-automation\u002Fcoordinate-reference-systems\u002Fchoose-projected-crs-for-analysis-pyqgis",{"title":5,"description":2005},"spatial-data-processing-automation\u002Fcoordinate-reference-systems\u002Fchoose-projected-crs-for-analysis-pyqgis\u002Findex","tz1bMZlLGG2lS6dWHuYoacooP3s-d36SSEqJC5hN1KM",1789632908252]