[{"data":1,"prerenderedAt":1666},["ShallowReactive",2],{"doc:\u002Fpyqgis-fundamentals-environment-setup\u002Ffeatures-geometries-and-memory-layers\u002Fconvert-geometry-type-pyqgis":3},{"id":4,"title":5,"body":6,"description":1655,"extension":1656,"meta":1657,"navigation":251,"path":1662,"seo":1663,"stem":1664,"__hash__":1665},"docs\u002Fpyqgis-fundamentals-environment-setup\u002Ffeatures-geometries-and-memory-layers\u002Fconvert-geometry-type-pyqgis\u002Findex.md","Convert Geometry Types in PyQGIS",{"type":7,"value":8,"toc":1641},"minimark",[9,13,26,39,189,194,212,216,219,385,417,421,424,490,623,649,653,656,795,824,828,841,882,1015,1031,1035,1042,1149,1174,1178,1181,1440,1461,1465,1488,1492,1531,1535,1554,1558,1564,1574,1580,1589,1603,1607,1637],[10,11,5],"h1",{"id":12},"convert-geometry-types-in-pyqgis",[14,15,16,17,21,22,25],"p",{},"Geometry types are strict in QGIS. A polygon layer accepts polygons, a ",[18,19,20],"code",{},"LineStringZ"," layer expects a Z value on every vertex, and a shapefile written as ",[18,23,24],{},"Polygon"," rejects the multipolygon that a dissolve just produced. Converting between types is therefore a routine part of moving data between layers, formats and tools: promoting singles to multi before an append, turning parcel boundaries into lines for a road-frontage measure, collapsing buildings to points for a density map, or stripping elevation from a survey before it goes into a 2D database.",[14,27,28,29,34,35,38],{},"This recipe belongs to ",[30,31,33],"a",{"href":32},"\u002Fpyqgis-fundamentals-environment-setup\u002Ffeatures-geometries-and-memory-layers\u002F","Features, Geometries & Memory Layers",". It covers each common conversion for a single ",[18,36,37],{},"QgsGeometry",", then the Processing algorithms that do the same for a whole layer.",[14,40,41],{},[42,43,48,52,56,63,80,89,97,102,108,114,119,123,128,133,136,141,147,152,159,162,167,172,177,181,185],"svg",{"viewBox":44,"role":45,"ariaLabel":46,"xmlns":47},"0 0 760 300","img","Conversions between point, line and polygon families, plus single to multi, curve to straight and Z\u002FM changes within each family","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg",[49,50,51],"title",{},"The common conversions between families",[53,54,55],"desc",{},"Polygons convert to lines by taking their boundary and to points through centroid or point on surface. Lines convert to polygons only when closed, and to points through their vertices or a centroid. Points convert to lines by connecting them in order and to polygons through a buffer or a convex hull. Each family also converts between single and multipart, and between curved and straight segments, and can gain or lose Z and M.",[57,58],"rect",{"x":59,"y":59,"width":60,"height":61,"fill":62},"0","760","300","#f6f3ea",[64,65,66],"defs",{},[67,68,75],"marker",{"id":69,"viewBox":70,"refX":71,"refY":72,"markerWidth":73,"markerHeight":73,"orient":74},"convMapArrow","0 0 10 10","8","5","7","auto-start-reverse",[76,77],"path",{"d":78,"fill":79},"M0 0 L10 5 L0 10 z","#2f3b35",[81,82,88],"text",{"x":83,"y":84,"style":85,"fill":86,"textAnchor":87},"380","28","text-anchor:middle;font-size:14px;font-family:sans-serif;font-weight:bold","#17211d","middle","Moving between point, line and polygon",[57,90],{"x":61,"y":91,"width":92,"height":93,"rx":71,"fill":94,"stroke":95,"style":96},"50","160","64","#fdf2e2","#b45309","stroke-width:2",[81,98,101],{"x":83,"y":99,"style":100,"fill":95,"textAnchor":87},"75.805","text-anchor:middle;font-size:11.5px;font-family:sans-serif;font-weight:bold","polygon",[81,103,107],{"x":83,"y":104,"style":105,"fill":106,"textAnchor":87},"95.755","text-anchor:middle;font-size:10.5px;font-family:sans-serif","#59645f","Polygon · Multi",[57,109],{"x":110,"y":111,"width":92,"height":93,"rx":71,"fill":112,"stroke":113,"style":96},"60","196","#eff3ff","#2563eb",[81,115,118],{"x":116,"y":117,"style":100,"fill":113,"textAnchor":87},"140","221.805","line",[81,120,122],{"x":116,"y":121,"style":105,"fill":106,"textAnchor":87},"241.755","LineString · Multi",[57,124],{"x":125,"y":111,"width":92,"height":93,"rx":71,"fill":126,"stroke":127,"style":96},"540","#e8efe6","#15803d",[81,129,132],{"x":130,"y":117,"style":100,"fill":131,"textAnchor":87},"620","#166534","point",[81,134,135],{"x":130,"y":121,"style":105,"fill":106,"textAnchor":87},"Point · Multi",[118,137],{"x1":61,"y1":138,"x2":139,"y2":111,"stroke":79,"style":140},"98","222","stroke-width:1.8;marker-end:url(#convMapArrow)",[81,142,146],{"x":143,"y":116,"style":144,"fill":79,"textAnchor":145},"214","text-anchor:end;font-size:10.0px;font-family:monospace","end","boundary()",[118,148],{"x1":143,"y1":149,"x2":150,"y2":151,"stroke":79,"style":140},"210","296","108",[81,153,158],{"x":154,"y":155,"style":156,"fill":106,"textAnchor":157},"252","182","text-anchor:start;font-size:10.0px;font-family:sans-serif","start","close + polygon",[118,160],{"x1":161,"y1":138,"x2":125,"y2":111,"stroke":79,"style":140},"460",[81,163,166],{"x":164,"y":116,"style":165,"fill":79,"textAnchor":157},"530","text-anchor:start;font-size:10.0px;font-family:monospace","centroid()",[118,168],{"x1":169,"y1":170,"x2":171,"y2":170,"stroke":79,"style":140},"220","238","536",[81,173,176],{"x":83,"y":174,"style":175,"fill":106,"textAnchor":87},"230","text-anchor:middle;font-size:10.0px;font-family:sans-serif","vertices · centroid",[118,178],{"x1":125,"y1":143,"x2":179,"y2":143,"stroke":79,"style":180},"224","stroke-width:1.8;marker-end:url(#convMapArrow);stroke-dasharray:5 4",[81,182,184],{"x":83,"y":183,"style":175,"fill":106,"textAnchor":87},"206","connect in order",[81,186,188],{"x":83,"y":187,"style":105,"fill":106,"textAnchor":87},"284","within every family: single ↔ multi · curve ↔ straight · ±Z ±M",[190,191,193],"h2",{"id":192},"prerequisites","Prerequisites",[195,196,197,201],"ul",{},[198,199,200],"li",{},"QGIS 3.34 LTR or newer, or the QGIS 4 series.",[198,202,203,204,207,208,211],{},"A clear idea of the target layer's geometry type. ",[18,205,206],{},"QgsWkbTypes.displayString(layer.wkbType())"," prints it, for example ",[18,209,210],{},"MultiPolygonZ",".",[190,213,215],{"id":214},"single-part-and-multipart","Single part and multipart",[14,217,218],{},"The most frequent conversion is between single and multipart within the same family. It is lossless in one direction and potentially lossy in the other.",[220,221,226],"pre",{"className":222,"code":223,"language":224,"meta":225,"style":225},"language-python shiki shiki-themes github-dark","from qgis.core import QgsGeometry, QgsWkbTypes\n\nsingle = QgsGeometry.fromWkt(\"Polygon ((0 0, 10 0, 10 10, 0 10, 0 0))\")\nsingle.convertToMultiType()\nprint(single.asWkt())                    # MultiPolygon (((0 0, 10 0, ...)))\n\nislands = QgsGeometry.fromWkt(\n    \"MultiPolygon (((0 0, 4 0, 4 4, 0 4, 0 0)), ((10 0, 14 0, 14 4, 10 4, 10 0)))\")\nparts = [QgsGeometry(p.clone()) for p in islands.constParts()]\nprint(len(parts), \"single parts\")\n\nok = islands.convertToSingleType()       # keeps only the first part!\nprint(ok, islands.asWkt())\n","python","",[18,227,228,246,253,272,278,292,297,308,316,339,358,363,377],{"__ignoreMap":225},[229,230,232,236,240,243],"span",{"class":118,"line":231},1,[229,233,235],{"class":234},"snl16","from",[229,237,239],{"class":238},"s95oV"," qgis.core ",[229,241,242],{"class":234},"import",[229,244,245],{"class":238}," QgsGeometry, QgsWkbTypes\n",[229,247,249],{"class":118,"line":248},2,[229,250,252],{"emptyLinePlaceholder":251},true,"\n",[229,254,256,259,262,265,269],{"class":118,"line":255},3,[229,257,258],{"class":238},"single ",[229,260,261],{"class":234},"=",[229,263,264],{"class":238}," QgsGeometry.fromWkt(",[229,266,268],{"class":267},"sU2Wk","\"Polygon ((0 0, 10 0, 10 10, 0 10, 0 0))\"",[229,270,271],{"class":238},")\n",[229,273,275],{"class":118,"line":274},4,[229,276,277],{"class":238},"single.convertToMultiType()\n",[229,279,281,285,288],{"class":118,"line":280},5,[229,282,284],{"class":283},"sDLfK","print",[229,286,287],{"class":238},"(single.asWkt())                    ",[229,289,291],{"class":290},"sjoCn","# MultiPolygon (((0 0, 10 0, ...)))\n",[229,293,295],{"class":118,"line":294},6,[229,296,252],{"emptyLinePlaceholder":251},[229,298,300,303,305],{"class":118,"line":299},7,[229,301,302],{"class":238},"islands ",[229,304,261],{"class":234},[229,306,307],{"class":238}," QgsGeometry.fromWkt(\n",[229,309,311,314],{"class":118,"line":310},8,[229,312,313],{"class":267},"    \"MultiPolygon (((0 0, 4 0, 4 4, 0 4, 0 0)), ((10 0, 14 0, 14 4, 10 4, 10 0)))\"",[229,315,271],{"class":238},[229,317,319,322,324,327,330,333,336],{"class":118,"line":318},9,[229,320,321],{"class":238},"parts ",[229,323,261],{"class":234},[229,325,326],{"class":238}," [QgsGeometry(p.clone()) ",[229,328,329],{"class":234},"for",[229,331,332],{"class":238}," p ",[229,334,335],{"class":234},"in",[229,337,338],{"class":238}," islands.constParts()]\n",[229,340,342,344,347,350,353,356],{"class":118,"line":341},10,[229,343,284],{"class":283},[229,345,346],{"class":238},"(",[229,348,349],{"class":283},"len",[229,351,352],{"class":238},"(parts), ",[229,354,355],{"class":267},"\"single parts\"",[229,357,271],{"class":238},[229,359,361],{"class":118,"line":360},11,[229,362,252],{"emptyLinePlaceholder":251},[229,364,366,369,371,374],{"class":118,"line":365},12,[229,367,368],{"class":238},"ok ",[229,370,261],{"class":234},[229,372,373],{"class":238}," islands.convertToSingleType()       ",[229,375,376],{"class":290},"# keeps only the first part!\n",[229,378,380,382],{"class":118,"line":379},13,[229,381,284],{"class":283},[229,383,384],{"class":238},"(ok, islands.asWkt())\n",[14,386,387,391,392,395,396,399,400,403,404,407,408,412,413,416],{},[388,389,390],"strong",{},"Breakdown:"," ",[18,393,394],{},"convertToMultiType()"," wraps the geometry in a one-member collection in place and always succeeds. Going the other way, ",[18,397,398],{},"convertToSingleType()"," succeeds even when there are several parts — and silently discards all but the first. That is almost never what you want; iterate ",[18,401,402],{},"constParts()"," and create one feature per part instead, or use ",[18,405,406],{},"native:multiparttosingleparts"," for a layer as shown in ",[30,409,411],{"href":410},"\u002Fspatial-data-processing-automation\u002Fgeometry-operations-and-predicates\u002Fconvert-multipart-to-singlepart-pyqgis\u002F","converting multipart to singlepart",". Promoting everything to multi is the safe default when writing to a layer, which is why many workflows create every output layer as a ",[18,414,415],{},"Multi"," type.",[190,418,420],{"id":419},"polygons-to-lines-and-lines-to-polygons","Polygons to lines and lines to polygons",[14,422,423],{},"A polygon's outline is a line; a closed line encloses a polygon. QGIS converts in both directions, with one condition for the second.",[14,425,426],{},[42,427,430,433,436,439,446,449,452,455,461,467,470,474,478,482,487],{"viewBox":428,"role":45,"ariaLabel":429,"xmlns":47},"0 0 760 250","A polygon with a hole becomes two boundary lines; a closed line becomes a polygon, while an open line must be closed first",[49,431,432],{},"Boundary out, closed ring in",[53,434,435],{},"A polygon with a hole converts with boundary to a multilinestring holding the exterior ring and the hole ring. A closed linestring whose first and last vertex coincide converts to a polygon. An open line, whose ends do not meet, cannot form a polygon without first adding the start point at the end, which may create a self-intersection if the ends are far apart.",[57,437],{"x":59,"y":59,"width":60,"height":438,"fill":62},"250",[64,440,441],{},[67,442,444],{"id":443,"viewBox":70,"refX":71,"refY":72,"markerWidth":73,"markerHeight":73,"orient":74},"convRingArrow",[76,445],{"d":78,"fill":79},[81,447,448],{"x":83,"y":84,"style":85,"fill":86,"textAnchor":87},"boundary() and its inverse",[101,450],{"points":451,"fill":94,"stroke":95,"style":96},"40,80 220,80 220,210 40,210",[101,453],{"points":454,"fill":62,"stroke":95,"style":96},"100,120 160,120 160,170 100,170",[118,456],{"x1":457,"y1":458,"x2":459,"y2":458,"stroke":79,"style":460},"228","145","276","stroke-width:1.8;marker-end:url(#convRingArrow)",[462,463],"polyline",{"points":464,"fill":465,"stroke":113,"style":466},"290,80 470,80 470,210 290,210 290,80","none","stroke-width:3",[462,468],{"points":469,"fill":465,"stroke":113,"style":466},"350,120 410,120 410,170 350,170 350,120",[81,471,473],{"x":83,"y":472,"style":175,"fill":106,"textAnchor":87},"236","MultiLineString: exterior + hole",[81,475,477],{"x":476,"y":472,"style":175,"fill":106,"textAnchor":87},"130","polygon with a hole",[462,479],{"points":480,"fill":465,"stroke":481,"style":466},"540,200 560,90 700,96 720,200","#b91c1c",[81,483,486],{"x":484,"y":485,"style":105,"fill":481,"textAnchor":87},"630","150","open line",[81,488,489],{"x":484,"y":472,"style":175,"fill":106,"textAnchor":87},"first ≠ last: close it first",[220,491,493],{"className":222,"code":492,"language":224,"meta":225,"style":225},"from qgis.core import QgsGeometry, QgsLineString, QgsPolygon\n\nparcel = QgsGeometry.fromWkt(\n    \"Polygon ((0 0, 40 0, 40 30, 0 30, 0 0), (10 10, 20 10, 20 20, 10 20, 10 10))\")\noutline = QgsGeometry(parcel.constGet().boundary())\nprint(outline.asWkt())                   # MultiLineString ((0 0, 40 0, ...), (10 10, ...))\nprint(\"perimeter incl. hole:\", outline.length())\n\ntrace = QgsGeometry.fromWkt(\"LineString (0 0, 50 0, 50 20, 0 20)\")\nline = trace.constGet().clone()\nif not line.isClosed():\n    line.addVertex(line.startPoint())    # close the ring\npoly = QgsGeometry(QgsPolygon(line))\nprint(poly.asWkt(), poly.isGeosValid())\n",[18,494,495,506,510,519,526,536,546,558,562,576,586,597,605,615],{"__ignoreMap":225},[229,496,497,499,501,503],{"class":118,"line":231},[229,498,235],{"class":234},[229,500,239],{"class":238},[229,502,242],{"class":234},[229,504,505],{"class":238}," QgsGeometry, QgsLineString, QgsPolygon\n",[229,507,508],{"class":118,"line":248},[229,509,252],{"emptyLinePlaceholder":251},[229,511,512,515,517],{"class":118,"line":255},[229,513,514],{"class":238},"parcel ",[229,516,261],{"class":234},[229,518,307],{"class":238},[229,520,521,524],{"class":118,"line":274},[229,522,523],{"class":267},"    \"Polygon ((0 0, 40 0, 40 30, 0 30, 0 0), (10 10, 20 10, 20 20, 10 20, 10 10))\"",[229,525,271],{"class":238},[229,527,528,531,533],{"class":118,"line":280},[229,529,530],{"class":238},"outline ",[229,532,261],{"class":234},[229,534,535],{"class":238}," QgsGeometry(parcel.constGet().boundary())\n",[229,537,538,540,543],{"class":118,"line":294},[229,539,284],{"class":283},[229,541,542],{"class":238},"(outline.asWkt())                   ",[229,544,545],{"class":290},"# MultiLineString ((0 0, 40 0, ...), (10 10, ...))\n",[229,547,548,550,552,555],{"class":118,"line":299},[229,549,284],{"class":283},[229,551,346],{"class":238},[229,553,554],{"class":267},"\"perimeter incl. hole:\"",[229,556,557],{"class":238},", outline.length())\n",[229,559,560],{"class":118,"line":310},[229,561,252],{"emptyLinePlaceholder":251},[229,563,564,567,569,571,574],{"class":118,"line":318},[229,565,566],{"class":238},"trace ",[229,568,261],{"class":234},[229,570,264],{"class":238},[229,572,573],{"class":267},"\"LineString (0 0, 50 0, 50 20, 0 20)\"",[229,575,271],{"class":238},[229,577,578,581,583],{"class":118,"line":341},[229,579,580],{"class":238},"line ",[229,582,261],{"class":234},[229,584,585],{"class":238}," trace.constGet().clone()\n",[229,587,588,591,594],{"class":118,"line":360},[229,589,590],{"class":234},"if",[229,592,593],{"class":234}," not",[229,595,596],{"class":238}," line.isClosed():\n",[229,598,599,602],{"class":118,"line":365},[229,600,601],{"class":238},"    line.addVertex(line.startPoint())    ",[229,603,604],{"class":290},"# close the ring\n",[229,606,607,610,612],{"class":118,"line":379},[229,608,609],{"class":238},"poly ",[229,611,261],{"class":234},[229,613,614],{"class":238}," QgsGeometry(QgsPolygon(line))\n",[229,616,618,620],{"class":118,"line":617},14,[229,619,284],{"class":283},[229,621,622],{"class":238},"(poly.asWkt(), poly.isGeosValid())\n",[14,624,625,391,627,629,630,633,634,636,637,640,641,644,645,648],{},[388,626,390],{},[18,628,146],{}," lives on the abstract geometry (",[18,631,632],{},"constGet()","), returning a new object that ",[18,635,37],{}," takes ownership of. For a polygon with holes the result is multipart: one line per ring, so its length is the full perimeter including the hole edges — use ",[18,638,639],{},"parcel.constGet().exteriorRing()"," for the outer edge alone. Creating a polygon from a line requires a closed ring; closing an open trace by appending the start point is correct when the ends nearly meet and produces a self-intersecting shape when they do not, so check ",[18,642,643],{},"isGeosValid()"," afterwards. For lines that form a network of edges rather than single rings, ",[18,646,647],{},"native:polygonize"," builds polygons from every enclosed face.",[190,650,652],{"id":651},"any-shape-to-points","Any shape to points",[14,654,655],{},"Points stand for features in density maps, labelling and joins. Which point depends on the question being asked.",[220,657,659],{"className":222,"code":658,"language":224,"meta":225,"style":225},"building = QgsGeometry.fromWkt(\n    \"Polygon ((0 0, 30 0, 30 10, 10 10, 10 30, 0 30, 0 0))\")   # an L-shape\n\ncentroid = building.centroid()              # may fall outside the shape\ninside = building.pointOnSurface()          # always inside\npole = building.poleOfInaccessibility(0.5)[0]  # most central interior point\nvertices = [QgsGeometry(v) for v in building.vertices()]\nprint(centroid.asWkt(1), building.contains(centroid))\nprint(inside.asWkt(1), pole.asWkt(1), len(vertices), \"vertices\")\n",[18,660,661,670,681,685,698,711,735,755,768],{"__ignoreMap":225},[229,662,663,666,668],{"class":118,"line":231},[229,664,665],{"class":238},"building ",[229,667,261],{"class":234},[229,669,307],{"class":238},[229,671,672,675,678],{"class":118,"line":248},[229,673,674],{"class":267},"    \"Polygon ((0 0, 30 0, 30 10, 10 10, 10 30, 0 30, 0 0))\"",[229,676,677],{"class":238},")   ",[229,679,680],{"class":290},"# an L-shape\n",[229,682,683],{"class":118,"line":255},[229,684,252],{"emptyLinePlaceholder":251},[229,686,687,690,692,695],{"class":118,"line":274},[229,688,689],{"class":238},"centroid ",[229,691,261],{"class":234},[229,693,694],{"class":238}," building.centroid()              ",[229,696,697],{"class":290},"# may fall outside the shape\n",[229,699,700,703,705,708],{"class":118,"line":280},[229,701,702],{"class":238},"inside ",[229,704,261],{"class":234},[229,706,707],{"class":238}," building.pointOnSurface()          ",[229,709,710],{"class":290},"# always inside\n",[229,712,713,716,718,721,724,727,729,732],{"class":118,"line":294},[229,714,715],{"class":238},"pole ",[229,717,261],{"class":234},[229,719,720],{"class":238}," building.poleOfInaccessibility(",[229,722,723],{"class":283},"0.5",[229,725,726],{"class":238},")[",[229,728,59],{"class":283},[229,730,731],{"class":238},"]  ",[229,733,734],{"class":290},"# most central interior point\n",[229,736,737,740,742,745,747,750,752],{"class":118,"line":299},[229,738,739],{"class":238},"vertices ",[229,741,261],{"class":234},[229,743,744],{"class":238}," [QgsGeometry(v) ",[229,746,329],{"class":234},[229,748,749],{"class":238}," v ",[229,751,335],{"class":234},[229,753,754],{"class":238}," building.vertices()]\n",[229,756,757,759,762,765],{"class":118,"line":310},[229,758,284],{"class":283},[229,760,761],{"class":238},"(centroid.asWkt(",[229,763,764],{"class":283},"1",[229,766,767],{"class":238},"), building.contains(centroid))\n",[229,769,770,772,775,777,780,782,785,787,790,793],{"class":118,"line":318},[229,771,284],{"class":283},[229,773,774],{"class":238},"(inside.asWkt(",[229,776,764],{"class":283},[229,778,779],{"class":238},"), pole.asWkt(",[229,781,764],{"class":283},[229,783,784],{"class":238},"), ",[229,786,349],{"class":283},[229,788,789],{"class":238},"(vertices), ",[229,791,792],{"class":267},"\"vertices\"",[229,794,271],{"class":238},[14,796,797,799,800,803,804,807,808,811,812,815,816,819,820,823],{},[388,798,390],{}," The centroid of an L-shaped or crescent polygon can lie outside it, which breaks point-in-polygon joins and puts labels in the wrong place. ",[18,801,802],{},"pointOnSurface()"," guarantees an interior point; ",[18,805,806],{},"poleOfInaccessibility()"," finds the interior point furthest from any edge, which is the visually central point and what QGIS uses for polygon labels. Vertex points are useful for inspecting digitizing quality or snapping. For whole layers, ",[18,809,810],{},"native:centroids"," with ",[18,813,814],{},"ALL_PARTS",", ",[18,817,818],{},"native:pointonsurface"," and ",[18,821,822],{},"native:extractvertices"," do the same.",[190,825,827],{"id":826},"curves-to-straight-segments","Curves to straight segments",[14,829,830,831,815,834,819,837,840],{},"Curved geometries — circular arcs in ",[18,832,833],{},"CircularString",[18,835,836],{},"CompoundCurve",[18,838,839],{},"CurvePolygon"," — come from CAD data, some national cadastres and QGIS's own curve digitizing. Many formats and tools cannot store them.",[14,842,843],{},[42,844,847,850,853,856,859,863,867,871,875,878],{"viewBox":845,"role":45,"ariaLabel":846,"xmlns":47},"0 0 760 240","A circular arc stored as a curve, approximated by a coarse polyline with few segments and by a fine polyline with many vertices",[49,848,849],{},"Segmentizing a circular arc",[53,851,852],{},"A circular arc defined by three points is stored exactly as a curve. Converting it to straight segments approximates it with a polyline; a coarse tolerance produces few, visibly straight segments, and a fine tolerance produces many vertices that hug the arc. The tolerance is the maximum angle or distance between the arc and the chord.",[57,854],{"x":59,"y":59,"width":60,"height":855,"fill":62},"240",[81,857,858],{"x":83,"y":84,"style":85,"fill":86,"textAnchor":87},"Exact curve or approximation?",[76,860],{"d":861,"fill":465,"stroke":862,"style":466},"M 60 190 A 110 110 0 0 1 280 190","#0f766e",[81,864,866],{"x":865,"y":143,"style":175,"fill":106,"textAnchor":87},"170","CircularString — 3 points",[462,868],{"points":869,"fill":465,"stroke":95,"style":870},"300,190 355,110 455,80 555,110 610,190","stroke-width:2.5",[81,872,874],{"x":873,"y":143,"style":175,"fill":106,"textAnchor":87},"455","coarse: 4 segments",[462,876],{"points":877,"fill":465,"stroke":113,"style":870},"630,190 637,160 650,135 668,115 690,102 710,98 730,102",[81,879,881],{"x":880,"y":143,"style":175,"fill":106,"textAnchor":87},"690","fine: many",[220,883,885],{"className":222,"code":884,"language":224,"meta":225,"style":225},"from qgis.core import QgsGeometry, QgsAbstractGeometry\n\narc_road = QgsGeometry.fromWkt(\n    \"CompoundCurve (CircularString (0 0, 50 50, 100 0), (100 0, 160 0))\")\nprint(arc_road.isMultipart(), arc_road.constGet().hasCurvedSegments())\n\ncoarse = arc_road.constGet().segmentize(0.2, QgsAbstractGeometry.MaximumAngle)\nfine = arc_road.constGet().segmentize(0.01, QgsAbstractGeometry.MaximumAngle)\nprint(coarse.nCoordinates(), \"vs\", fine.nCoordinates(), \"vertices\")\n\nstraight = QgsGeometry(fine)                 # LineString, ready for any format\nprint(straight.asWkt(1)[:60], \"…\")\n",[18,886,887,898,902,911,918,925,929,945,959,976,980,993],{"__ignoreMap":225},[229,888,889,891,893,895],{"class":118,"line":231},[229,890,235],{"class":234},[229,892,239],{"class":238},[229,894,242],{"class":234},[229,896,897],{"class":238}," QgsGeometry, QgsAbstractGeometry\n",[229,899,900],{"class":118,"line":248},[229,901,252],{"emptyLinePlaceholder":251},[229,903,904,907,909],{"class":118,"line":255},[229,905,906],{"class":238},"arc_road ",[229,908,261],{"class":234},[229,910,307],{"class":238},[229,912,913,916],{"class":118,"line":274},[229,914,915],{"class":267},"    \"CompoundCurve (CircularString (0 0, 50 50, 100 0), (100 0, 160 0))\"",[229,917,271],{"class":238},[229,919,920,922],{"class":118,"line":280},[229,921,284],{"class":283},[229,923,924],{"class":238},"(arc_road.isMultipart(), arc_road.constGet().hasCurvedSegments())\n",[229,926,927],{"class":118,"line":294},[229,928,252],{"emptyLinePlaceholder":251},[229,930,931,934,936,939,942],{"class":118,"line":299},[229,932,933],{"class":238},"coarse ",[229,935,261],{"class":234},[229,937,938],{"class":238}," arc_road.constGet().segmentize(",[229,940,941],{"class":283},"0.2",[229,943,944],{"class":238},", QgsAbstractGeometry.MaximumAngle)\n",[229,946,947,950,952,954,957],{"class":118,"line":310},[229,948,949],{"class":238},"fine ",[229,951,261],{"class":234},[229,953,938],{"class":238},[229,955,956],{"class":283},"0.01",[229,958,944],{"class":238},[229,960,961,963,966,969,972,974],{"class":118,"line":318},[229,962,284],{"class":283},[229,964,965],{"class":238},"(coarse.nCoordinates(), ",[229,967,968],{"class":267},"\"vs\"",[229,970,971],{"class":238},", fine.nCoordinates(), ",[229,973,792],{"class":267},[229,975,271],{"class":238},[229,977,978],{"class":118,"line":341},[229,979,252],{"emptyLinePlaceholder":251},[229,981,982,985,987,990],{"class":118,"line":360},[229,983,984],{"class":238},"straight ",[229,986,261],{"class":234},[229,988,989],{"class":238}," QgsGeometry(fine)                 ",[229,991,992],{"class":290},"# LineString, ready for any format\n",[229,994,995,997,1000,1002,1005,1007,1010,1013],{"class":118,"line":365},[229,996,284],{"class":283},[229,998,999],{"class":238},"(straight.asWkt(",[229,1001,764],{"class":283},[229,1003,1004],{"class":238},")[:",[229,1006,110],{"class":283},[229,1008,1009],{"class":238},"], ",[229,1011,1012],{"class":267},"\"…\"",[229,1014,271],{"class":238},[14,1016,1017,391,1019,1022,1023,1026,1027,1030],{},[388,1018,390],{},[18,1020,1021],{},"segmentize"," approximates arcs with straight segments. With ",[18,1024,1025],{},"MaximumAngle",", the tolerance is the angle in radians subtended by each segment; with ",[18,1028,1029],{},"MaximumDifference",", it is the maximum distance between arc and chord in layer units, which is easier to relate to data accuracy — a centimetre on a cadastre. Curves are worth keeping where the target supports them (GeoPackage and PostGIS do); convert only at the boundary with a format that does not, such as shapefile or GeoJSON.",[190,1032,1034],{"id":1033},"add-or-drop-z-and-m","Add or drop Z and M",[14,1036,1037,1038,1041],{},"Elevation and measure values must match the target layer: a 2D table rejects Z values on some providers and silently drops them on others, while a ",[18,1039,1040],{},"PointZ"," layer fills missing Z with NaN or zero.",[220,1043,1045],{"className":222,"code":1044,"language":224,"meta":225,"style":225},"from qgis.core import QgsGeometry\n\npt = QgsGeometry.fromWkt(\"Point (571200 5934000)\")\ngeom3d = QgsGeometry(pt.constGet().clone())\ngeom3d.get().addZValue(0.0)\nprint(geom3d.asWkt())                   # Point Z (571200 5934000 0)\n\nsurvey = QgsGeometry.fromWkt(\"LineString Z (0 0 410, 10 0 412, 20 0 415)\")\nflat = QgsGeometry(survey.constGet().clone())\nflat.get().dropZValue()\nprint(flat.asWkt())                     # LineString (0 0, 10 0, 20 0)\n",[18,1046,1047,1058,1062,1076,1086,1096,1106,1110,1124,1134,1139],{"__ignoreMap":225},[229,1048,1049,1051,1053,1055],{"class":118,"line":231},[229,1050,235],{"class":234},[229,1052,239],{"class":238},[229,1054,242],{"class":234},[229,1056,1057],{"class":238}," QgsGeometry\n",[229,1059,1060],{"class":118,"line":248},[229,1061,252],{"emptyLinePlaceholder":251},[229,1063,1064,1067,1069,1071,1074],{"class":118,"line":255},[229,1065,1066],{"class":238},"pt ",[229,1068,261],{"class":234},[229,1070,264],{"class":238},[229,1072,1073],{"class":267},"\"Point (571200 5934000)\"",[229,1075,271],{"class":238},[229,1077,1078,1081,1083],{"class":118,"line":274},[229,1079,1080],{"class":238},"geom3d ",[229,1082,261],{"class":234},[229,1084,1085],{"class":238}," QgsGeometry(pt.constGet().clone())\n",[229,1087,1088,1091,1094],{"class":118,"line":280},[229,1089,1090],{"class":238},"geom3d.get().addZValue(",[229,1092,1093],{"class":283},"0.0",[229,1095,271],{"class":238},[229,1097,1098,1100,1103],{"class":118,"line":294},[229,1099,284],{"class":283},[229,1101,1102],{"class":238},"(geom3d.asWkt())                   ",[229,1104,1105],{"class":290},"# Point Z (571200 5934000 0)\n",[229,1107,1108],{"class":118,"line":299},[229,1109,252],{"emptyLinePlaceholder":251},[229,1111,1112,1115,1117,1119,1122],{"class":118,"line":310},[229,1113,1114],{"class":238},"survey ",[229,1116,261],{"class":234},[229,1118,264],{"class":238},[229,1120,1121],{"class":267},"\"LineString Z (0 0 410, 10 0 412, 20 0 415)\"",[229,1123,271],{"class":238},[229,1125,1126,1129,1131],{"class":118,"line":318},[229,1127,1128],{"class":238},"flat ",[229,1130,261],{"class":234},[229,1132,1133],{"class":238}," QgsGeometry(survey.constGet().clone())\n",[229,1135,1136],{"class":118,"line":341},[229,1137,1138],{"class":238},"flat.get().dropZValue()\n",[229,1140,1141,1143,1146],{"class":118,"line":360},[229,1142,284],{"class":283},[229,1144,1145],{"class":238},"(flat.asWkt())                     ",[229,1147,1148],{"class":290},"# LineString (0 0, 10 0, 20 0)\n",[14,1150,1151,391,1153,1156,1157,815,1160,815,1163,819,1166,1169,1170,1173],{},[388,1152,390],{},[18,1154,1155],{},"get()"," returns a mutable pointer to the abstract geometry, on which ",[18,1158,1159],{},"addZValue",[18,1161,1162],{},"dropZValue",[18,1164,1165],{},"addMValue",[18,1167,1168],{},"dropMValue"," work in place. Adding a constant Z is rarely the end of the story — real elevations come from a DEM via ",[18,1171,1172],{},"native:setzfromraster"," (Drape) for a whole layer. Dropping Z before writing to a 2D target is preferable to letting the provider decide. Cloning first keeps the original intact, which matters when the same geometry is used elsewhere in the script.",[190,1175,1177],{"id":1176},"convert-a-whole-layer-with-processing","Convert a whole layer with Processing",[14,1179,1180],{},"For layers, the Processing algorithms are faster than a Python loop and handle attributes for you. Most single-geometry conversions above have a layer equivalent.",[220,1182,1184],{"className":222,"code":1183,"language":224,"meta":225,"style":225},"import processing\n\nsteps = {\n    \"promote\": (\"native:promotetomulti\", {}),\n    \"boundary\": (\"native:boundary\", {}),\n    \"points\": (\"native:pointonsurface\", {\"ALL_PARTS\": False}),\n    \"straight\": (\"native:segmentizebymaxangle\", {\"ANGLE\": 1.0}),\n    \"flatten\": (\"native:dropmzvalues\", {\"DROP_Z_VALUES\": True, \"DROP_M_VALUES\": True}),\n}\nalg, extra = steps[\"boundary\"]\nresult = processing.run(alg, {\"INPUT\": \"\u002Fdata\u002Fparcels.gpkg|layername=parcels\",\n                              \"OUTPUT\": \"memory:\", **extra})[\"OUTPUT\"]\nprint(result.wkbType(), result.featureCount())\n\nconverted = processing.run(\"qgis:convertgeometrytype\", {\n    \"INPUT\": result, \"TYPE\": 2, \"OUTPUT\": \"memory:\"})[\"OUTPUT\"]   # 2 = Linestrings\n",[18,1185,1186,1193,1197,1207,1221,1233,1258,1280,1311,1316,1332,1353,1376,1383,1387,1404],{"__ignoreMap":225},[229,1187,1188,1190],{"class":118,"line":231},[229,1189,242],{"class":234},[229,1191,1192],{"class":238}," processing\n",[229,1194,1195],{"class":118,"line":248},[229,1196,252],{"emptyLinePlaceholder":251},[229,1198,1199,1202,1204],{"class":118,"line":255},[229,1200,1201],{"class":238},"steps ",[229,1203,261],{"class":234},[229,1205,1206],{"class":238}," {\n",[229,1208,1209,1212,1215,1218],{"class":118,"line":274},[229,1210,1211],{"class":267},"    \"promote\"",[229,1213,1214],{"class":238},": (",[229,1216,1217],{"class":267},"\"native:promotetomulti\"",[229,1219,1220],{"class":238},", {}),\n",[229,1222,1223,1226,1228,1231],{"class":118,"line":280},[229,1224,1225],{"class":267},"    \"boundary\"",[229,1227,1214],{"class":238},[229,1229,1230],{"class":267},"\"native:boundary\"",[229,1232,1220],{"class":238},[229,1234,1235,1238,1240,1243,1246,1249,1252,1255],{"class":118,"line":294},[229,1236,1237],{"class":267},"    \"points\"",[229,1239,1214],{"class":238},[229,1241,1242],{"class":267},"\"native:pointonsurface\"",[229,1244,1245],{"class":238},", {",[229,1247,1248],{"class":267},"\"ALL_PARTS\"",[229,1250,1251],{"class":238},": ",[229,1253,1254],{"class":283},"False",[229,1256,1257],{"class":238},"}),\n",[229,1259,1260,1263,1265,1268,1270,1273,1275,1278],{"class":118,"line":299},[229,1261,1262],{"class":267},"    \"straight\"",[229,1264,1214],{"class":238},[229,1266,1267],{"class":267},"\"native:segmentizebymaxangle\"",[229,1269,1245],{"class":238},[229,1271,1272],{"class":267},"\"ANGLE\"",[229,1274,1251],{"class":238},[229,1276,1277],{"class":283},"1.0",[229,1279,1257],{"class":238},[229,1281,1282,1285,1287,1290,1292,1295,1297,1300,1302,1305,1307,1309],{"class":118,"line":310},[229,1283,1284],{"class":267},"    \"flatten\"",[229,1286,1214],{"class":238},[229,1288,1289],{"class":267},"\"native:dropmzvalues\"",[229,1291,1245],{"class":238},[229,1293,1294],{"class":267},"\"DROP_Z_VALUES\"",[229,1296,1251],{"class":238},[229,1298,1299],{"class":283},"True",[229,1301,815],{"class":238},[229,1303,1304],{"class":267},"\"DROP_M_VALUES\"",[229,1306,1251],{"class":238},[229,1308,1299],{"class":283},[229,1310,1257],{"class":238},[229,1312,1313],{"class":118,"line":318},[229,1314,1315],{"class":238},"}\n",[229,1317,1318,1321,1323,1326,1329],{"class":118,"line":341},[229,1319,1320],{"class":238},"alg, extra ",[229,1322,261],{"class":234},[229,1324,1325],{"class":238}," steps[",[229,1327,1328],{"class":267},"\"boundary\"",[229,1330,1331],{"class":238},"]\n",[229,1333,1334,1337,1339,1342,1345,1347,1350],{"class":118,"line":360},[229,1335,1336],{"class":238},"result ",[229,1338,261],{"class":234},[229,1340,1341],{"class":238}," processing.run(alg, {",[229,1343,1344],{"class":267},"\"INPUT\"",[229,1346,1251],{"class":238},[229,1348,1349],{"class":267},"\"\u002Fdata\u002Fparcels.gpkg|layername=parcels\"",[229,1351,1352],{"class":238},",\n",[229,1354,1355,1358,1360,1363,1365,1368,1371,1374],{"class":118,"line":365},[229,1356,1357],{"class":267},"                              \"OUTPUT\"",[229,1359,1251],{"class":238},[229,1361,1362],{"class":267},"\"memory:\"",[229,1364,815],{"class":238},[229,1366,1367],{"class":234},"**",[229,1369,1370],{"class":238},"extra})[",[229,1372,1373],{"class":267},"\"OUTPUT\"",[229,1375,1331],{"class":238},[229,1377,1378,1380],{"class":118,"line":379},[229,1379,284],{"class":283},[229,1381,1382],{"class":238},"(result.wkbType(), result.featureCount())\n",[229,1384,1385],{"class":118,"line":617},[229,1386,252],{"emptyLinePlaceholder":251},[229,1388,1390,1393,1395,1398,1401],{"class":118,"line":1389},15,[229,1391,1392],{"class":238},"converted ",[229,1394,261],{"class":234},[229,1396,1397],{"class":238}," processing.run(",[229,1399,1400],{"class":267},"\"qgis:convertgeometrytype\"",[229,1402,1403],{"class":238},", {\n",[229,1405,1407,1410,1413,1416,1418,1421,1423,1425,1427,1429,1432,1434,1437],{"class":118,"line":1406},16,[229,1408,1409],{"class":267},"    \"INPUT\"",[229,1411,1412],{"class":238},": result, ",[229,1414,1415],{"class":267},"\"TYPE\"",[229,1417,1251],{"class":238},[229,1419,1420],{"class":283},"2",[229,1422,815],{"class":238},[229,1424,1373],{"class":267},[229,1426,1251],{"class":238},[229,1428,1362],{"class":267},[229,1430,1431],{"class":238},"})[",[229,1433,1373],{"class":267},[229,1435,1436],{"class":238},"]   ",[229,1438,1439],{"class":290},"# 2 = Linestrings\n",[14,1441,1442,1444,1445,1448,1449,1452,1453,1456,1457,211],{},[388,1443,390],{}," Each algorithm keeps the attributes and writes one output feature per input feature (or per part, where noted). Running the conversion in Processing also records it in the Processing history, so the exact parameters can be reviewed or repeated later, and invalid input geometry is handled according to the global invalid-feature setting rather than crashing the loop halfway through a large layer. ",[18,1446,1447],{},"native:promotetomulti"," is the bulk version of ",[18,1450,1451],{},"convertToMultiType"," and should precede appends into a multi-typed target. ",[18,1454,1455],{},"qgis:convertgeometrytype"," is the general converter, choosing among centroids, nodes, linestrings, multilinestrings and polygons by an enum. Chaining several conversions through memory layers follows the pattern in ",[30,1458,1460],{"href":1459},"\u002Fspatial-data-processing-automation\u002Fchaining-processing-algorithms\u002Fuse-memory-layers-between-algorithms-pyqgis\u002F","using memory layers between algorithms",[190,1462,1464],{"id":1463},"qgis-version-compatibility","QGIS version compatibility",[14,1466,1467,1468,819,1471,1473,1474,819,1477,1480,1481,1484,1485,211],{},"All methods shown exist in QGIS 3.x and QGIS 4. ",[18,1469,1470],{},"poleOfInaccessibility",[18,1472,818],{}," require 3.0 and later; ",[18,1475,1476],{},"native:dropmzvalues",[18,1478,1479],{},"native:segmentizebymaxangle"," arrived in 3.0 as well. On QGIS 4, the ",[18,1482,1483],{},"QgsAbstractGeometry.MaximumAngle"," enum is spelled ",[18,1486,1487],{},"QgsAbstractGeometry.SegmentationToleranceType.MaximumAngle",[190,1489,1491],{"id":1490},"troubleshooting","Troubleshooting",[195,1493,1494,1505,1513,1525],{},[198,1495,1496,1499,1500,1502,1503,211],{},[388,1497,1498],{},"An append fails with a type mismatch."," The source has singles and the target is multi, or vice versa; promote with ",[18,1501,394],{}," or ",[18,1504,1447],{},[198,1506,1507,391,1510,1512],{},[388,1508,1509],{},"Only one part survives conversion to single.",[18,1511,398],{}," drops the rest; split parts into separate features instead.",[198,1514,1515,1518,1519,1521,1522,211],{},[388,1516,1517],{},"The polygon from a closed line is invalid."," The ring self-intersects; check ",[18,1520,643],{}," and repair with ",[18,1523,1524],{},"makeValid()",[198,1526,1527,1530],{},[388,1528,1529],{},"Shapefile export fails on curves."," Segmentize first; shapefiles cannot store arcs.",[190,1532,1534],{"id":1533},"conclusion","Conclusion",[14,1536,1537,1538,1540,1541,1544,1545,1547,1548,1502,1551,1553],{},"Use ",[18,1539,1451],{}," freely and ",[18,1542,1543],{},"convertToSingleType"," only for genuinely single geometries, take ",[18,1546,146],{}," for outlines and close rings before building polygons, pick ",[18,1549,1550],{},"pointOnSurface",[18,1552,1470],{}," when a point must lie inside, segmentize curves only at format boundaries, match Z and M to the target, and use the Processing equivalents for whole layers.",[190,1555,1557],{"id":1556},"frequently-asked-questions","Frequently Asked Questions",[14,1559,1560,1563],{},[388,1561,1562],{},"Why does QGIS create Multi layers by default?","\nBecause a multi-typed layer accepts both single and multipart geometry, which avoids type errors after operations like dissolve.",[14,1565,1566,1569,1570,1573],{},[388,1567,1568],{},"How do I convert points into a line in visit order?","\nSort by a sequence field and use ",[18,1571,1572],{},"native:pointstopath",", which builds one line per group.",[14,1575,1576,1579],{},[388,1577,1578],{},"Is converting to 2D lossy?","\nYes. Elevation values are discarded; keep the 3D source if you may need them later.",[14,1581,1582,1585,1586,1588],{},[388,1583,1584],{},"How do I turn lines into polygons when they form a network rather than closed rings?","\nUse ",[18,1587,647],{},", which nodes the lines and creates a polygon for every enclosed face. It is the right tool for parcel boundaries digitized as separate line segments, where no single line forms a closed ring on its own.",[14,1590,1591,1594,1595,1598,1599,1602],{},[388,1592,1593],{},"Can I convert a polygon to its convex hull?","\nYes: ",[18,1596,1597],{},"geom.convexHull()",", or ",[18,1600,1601],{},"native:convexhull"," for a layer.",[190,1604,1606],{"id":1605},"related","Related",[195,1608,1609,1614,1620,1625,1631],{},[198,1610,1611,1613],{},[30,1612,33],{"href":32}," — the guide this recipe belongs to",[198,1615,1616],{},[30,1617,1619],{"href":1618},"\u002Fpyqgis-fundamentals-environment-setup\u002Ffeatures-geometries-and-memory-layers\u002Fcreate-geometry-from-wkt-and-geojson-pyqgis\u002F","Create Geometry from WKT and GeoJSON in PyQGIS",[198,1621,1622],{},[30,1623,1624],{"href":410},"Convert Multipart to Singlepart in PyQGIS",[198,1626,1627],{},[30,1628,1630],{"href":1629},"\u002Fspatial-data-processing-automation\u002Fgeometry-operations-and-predicates\u002Fiterate-and-edit-geometry-vertices-pyqgis\u002F","Iterate and Edit Geometry Vertices in PyQGIS",[198,1632,1633],{},[30,1634,1636],{"href":1635},"\u002Fspatial-data-processing-automation\u002Fvector-data-manipulation\u002Fcreate-centroids-and-bounding-geometries-pyqgis\u002F","Create Centroids and Bounding Geometries in PyQGIS",[1638,1639,1640],"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 pre.shiki code .sjoCn, html code.shiki .sjoCn{--shiki-default:#9AA79F}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);}",{"title":225,"searchDepth":248,"depth":248,"links":1642},[1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654],{"id":192,"depth":248,"text":193},{"id":214,"depth":248,"text":215},{"id":419,"depth":248,"text":420},{"id":651,"depth":248,"text":652},{"id":826,"depth":248,"text":827},{"id":1033,"depth":248,"text":1034},{"id":1176,"depth":248,"text":1177},{"id":1463,"depth":248,"text":1464},{"id":1490,"depth":248,"text":1491},{"id":1533,"depth":248,"text":1534},{"id":1556,"depth":248,"text":1557},{"id":1605,"depth":248,"text":1606},"Convert between geometry types in PyQGIS — single to multipart and back, polygons to their boundary lines, lines to polygons, any shape to points, curves to straight segments, and adding or dropping Z and M values — for one geometry or a whole layer.","md",{"slug":1658,"type":1659,"breadcrumb":1660,"datePublished":1661,"dateModified":1661},"convert-geometry-type-pyqgis","article","Convert Geometry Types","2026-10-02","\u002Fpyqgis-fundamentals-environment-setup\u002Ffeatures-geometries-and-memory-layers\u002Fconvert-geometry-type-pyqgis",{"title":5,"description":1655},"pyqgis-fundamentals-environment-setup\u002Ffeatures-geometries-and-memory-layers\u002Fconvert-geometry-type-pyqgis\u002Findex","JG5m4jDIx9cY1JNUJLn-zTV3S-6qVbjKszpkPk3S0Pk",1790966252923]