[{"data":1,"prerenderedAt":2236},["ShallowReactive",2],{"doc:\u002Fpyqgis-fundamentals-environment-setup\u002Ffeatures-geometries-and-memory-layers\u002Fcreate-geometry-from-wkt-and-geojson-pyqgis":3},{"id":4,"title":5,"body":6,"description":2225,"extension":2226,"meta":2227,"navigation":273,"path":2232,"seo":2233,"stem":2234,"__hash__":2235},"docs\u002Fpyqgis-fundamentals-environment-setup\u002Ffeatures-geometries-and-memory-layers\u002Fcreate-geometry-from-wkt-and-geojson-pyqgis\u002Findex.md","Create Geometry from WKT and GeoJSON in PyQGIS",{"type":7,"value":8,"toc":2211},"minimark",[9,13,22,31,215,220,230,234,241,493,528,532,538,621,900,939,943,946,1201,1236,1240,1243,1346,1550,1569,1573,1576,1893,1911,1915,1928,1991,2015,2019,2050,2054,2102,2106,2123,2127,2137,2149,2165,2175,2179,2207],[10,11,5],"h1",{"id":12},"create-geometry-from-wkt-and-geojson-in-pyqgis",[14,15,16,17,21],"p",{},"Geometry rarely starts life inside QGIS. It arrives as a WKT string in a database export, a GeoJSON fragment from a web API, a hex-encoded WKB column from PostGIS, or a plain list of coordinate pairs in a CSV. ",[18,19,20],"code",{},"QgsGeometry"," can be built from all of them, but each route has its own way of failing — and most of them fail quietly, by returning an empty geometry rather than raising an error.",[14,23,24,25,30],{},"This recipe belongs to ",[26,27,29],"a",{"href":28},"\u002Fpyqgis-fundamentals-environment-setup\u002Ffeatures-geometries-and-memory-layers\u002F","Features, Geometries & Memory Layers",". It covers each input format, the checks that catch a bad parse before it reaches a layer, how Z and M values survive the trip, and how to export geometries back to text for logs, APIs and other tools.",[14,32,33],{},[34,35,40,44,48,55,72,81,90,96,101,104,108,112,115,119,123,126,130,134,140,145,147,151,153,157,159,163,170,173,176,179,184,187,190,193,201,206,211],"svg",{"viewBox":36,"role":37,"ariaLabel":38,"xmlns":39},"0 0 760 290","img","Four input encodings — WKT, WKB, GeoJSON and coordinate lists — each passing through its own factory into one QgsGeometry, followed by a null and validity check","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg",[41,42,43],"title",{},"Many encodings, one geometry object",[45,46,47],"desc",{},"Four common encodings enter on the left: WKT text, WKB bytes or hex, a GeoJSON geometry object and plain coordinate lists. Each has a dedicated factory: fromWkt, fromWkb, a JSON conversion through QgsJsonUtils or OGR, and fromPointXY or fromPolylineXY. All of them produce a QgsGeometry, which then needs an isNull and isGeosValid check before it is used.",[49,50],"rect",{"x":51,"y":51,"width":52,"height":53,"fill":54},"0","760","290","#f6f3ea",[56,57,58],"defs",{},[59,60,67],"marker",{"id":61,"viewBox":62,"refX":63,"refY":64,"markerWidth":65,"markerHeight":65,"orient":66},"geomInArrow","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-family:sans-serif;font-weight:bold","#17211d","middle","Pick the factory that matches the encoding",[49,82],{"x":83,"y":84,"width":85,"height":86,"rx":63,"fill":87,"stroke":88,"style":89},"24","52","190","48","#fffdf7","#59645f","stroke-width:2",[73,91,95],{"x":92,"y":93,"style":94,"fill":78,"textAnchor":79},"119","69.805","text-anchor:middle;font-size:11.5px;font-family:sans-serif;font-weight:bold","WKT text",[73,97,100],{"x":92,"y":98,"style":99,"fill":71,"textAnchor":79},"89.755","text-anchor:middle;font-size:10.0px;font-family:monospace","POLYGON((…))",[49,102],{"x":83,"y":103,"width":85,"height":86,"rx":63,"fill":87,"stroke":88,"style":89},"112",[73,105,107],{"x":92,"y":106,"style":94,"fill":78,"textAnchor":79},"129.805","WKB bytes \u002F hex",[73,109,111],{"x":92,"y":110,"style":99,"fill":71,"textAnchor":79},"149.755","0103000000…",[49,113],{"x":83,"y":114,"width":85,"height":86,"rx":63,"fill":87,"stroke":88,"style":89},"172",[73,116,118],{"x":92,"y":117,"style":94,"fill":78,"textAnchor":79},"189.805","GeoJSON object",[73,120,122],{"x":92,"y":121,"style":99,"fill":71,"textAnchor":79},"209.755","{\"type\": \"Point\"…}",[49,124],{"x":83,"y":125,"width":85,"height":86,"rx":63,"fill":87,"stroke":88,"style":89},"232",[73,127,129],{"x":92,"y":128,"style":94,"fill":78,"textAnchor":79},"249.805","coordinate lists",[73,131,133],{"x":92,"y":132,"style":99,"fill":71,"textAnchor":79},"269.755","[(x, y), (x, y)]",[49,135],{"x":136,"y":84,"width":137,"height":86,"rx":63,"fill":138,"stroke":139,"style":89},"262","200","#eef7f4","#0f766e",[73,141,144],{"x":142,"y":143,"style":94,"fill":139,"textAnchor":79},"362","79.78","fromWkt()",[49,146],{"x":136,"y":103,"width":137,"height":86,"rx":63,"fill":138,"stroke":139,"style":89},[73,148,150],{"x":142,"y":149,"style":94,"fill":139,"textAnchor":79},"139.78","fromWkb()",[49,152],{"x":136,"y":114,"width":137,"height":86,"rx":63,"fill":138,"stroke":139,"style":89},[73,154,156],{"x":142,"y":155,"style":94,"fill":139,"textAnchor":79},"199.78","QgsJsonUtils \u002F OGR",[49,158],{"x":136,"y":125,"width":137,"height":86,"rx":63,"fill":138,"stroke":139,"style":89},[73,160,162],{"x":142,"y":161,"style":94,"fill":139,"textAnchor":79},"259.78","fromPolylineXY()",[164,165],"line",{"x1":166,"y1":167,"x2":168,"y2":167,"stroke":71,"style":169},"214","76","258","stroke-width:1.8;marker-end:url(#geomInArrow)",[164,171],{"x1":166,"y1":172,"x2":168,"y2":172,"stroke":71,"style":169},"136",[164,174],{"x1":166,"y1":175,"x2":168,"y2":175,"stroke":71,"style":169},"196",[164,177],{"x1":166,"y1":178,"x2":168,"y2":178,"stroke":71,"style":169},"256",[164,180],{"x1":181,"y1":167,"x2":182,"y2":183,"stroke":71,"style":169},"462","520","150",[164,185],{"x1":181,"y1":172,"x2":182,"y2":186,"stroke":71,"style":169},"160",[164,188],{"x1":181,"y1":175,"x2":182,"y2":189,"stroke":71,"style":169},"176",[164,191],{"x1":181,"y1":178,"x2":182,"y2":192,"stroke":71,"style":169},"186",[49,194],{"x":195,"y":196,"width":197,"height":198,"rx":63,"fill":199,"stroke":200,"style":89},"528","130","208","80","#e8efe6","#15803d",[73,202,20],{"x":203,"y":204,"style":94,"fill":205,"textAnchor":79},"632","153.83","#166534",[73,207,210],{"x":203,"y":208,"style":209,"fill":88,"textAnchor":79},"173.78","text-anchor:middle;font-size:10.5px;font-family:sans-serif","check isNull()",[73,212,214],{"x":203,"y":213,"style":209,"fill":88,"textAnchor":79},"193.73","then isGeosValid()",[216,217,219],"h2",{"id":218},"prerequisites","Prerequisites",[221,222,223,227],"ul",{},[224,225,226],"li",{},"QGIS 3.34 LTR or newer, or the QGIS 4 series, with the Python console or a standalone script.",[224,228,229],{},"A target CRS in mind. Geometry objects carry no CRS of their own — the layer they are added to supplies it — so you need to know what coordinate system the incoming numbers are in.",[216,231,233],{"id":232},"parse-wkt-and-wkb","Parse WKT and WKB",[14,235,236,237,240],{},"Well-known text is the most readable encoding and the one most likely to arrive hand-edited, which makes it the one most likely to be wrong. ",[18,238,239],{},"QgsGeometry.fromWkt"," never raises; a string it cannot parse becomes a null geometry.",[242,243,248],"pre",{"className":244,"code":245,"language":246,"meta":247,"style":247},"language-python shiki shiki-themes github-dark","from qgis.core import QgsGeometry, QgsWkbTypes\n\ndef geometry_from_wkt(text):\n    geom = QgsGeometry.fromWkt(text.strip())\n    if geom.isNull():\n        raise ValueError(f\"unparseable WKT: {text[:60]!r}\")\n    return geom\n\nparcel = geometry_from_wkt(\n    \"POLYGON((571200 5934000, 571260 5934000, 571260 5934045, 571200 5934045, 571200 5934000))\")\nprint(QgsWkbTypes.displayString(parcel.wkbType()), parcel.area())\n\nline_z = geometry_from_wkt(\"LINESTRING Z (0 0 12.5, 10 0 13.1, 20 5 14.0)\")\nprint(line_z.constGet().is3D(), [v.z() for v in line_z.vertices()])\n\n# WKB as bytes, e.g. from a database cursor or a hex column\nhex_wkb = \"0101000000000000000000F03F0000000000000040\"\npt = QgsGeometry()\npt.fromWkb(bytes.fromhex(hex_wkb))\nprint(pt.asWkt())          # Point (1 2)\n","python","",[18,249,250,268,275,288,300,309,353,362,367,378,386,395,400,416,436,441,448,459,470,482],{"__ignoreMap":247},[251,252,254,258,262,265],"span",{"class":164,"line":253},1,[251,255,257],{"class":256},"snl16","from",[251,259,261],{"class":260},"s95oV"," qgis.core ",[251,263,264],{"class":256},"import",[251,266,267],{"class":260}," QgsGeometry, QgsWkbTypes\n",[251,269,271],{"class":164,"line":270},2,[251,272,274],{"emptyLinePlaceholder":273},true,"\n",[251,276,278,281,285],{"class":164,"line":277},3,[251,279,280],{"class":256},"def",[251,282,284],{"class":283},"svObZ"," geometry_from_wkt",[251,286,287],{"class":260},"(text):\n",[251,289,291,294,297],{"class":164,"line":290},4,[251,292,293],{"class":260},"    geom ",[251,295,296],{"class":256},"=",[251,298,299],{"class":260}," QgsGeometry.fromWkt(text.strip())\n",[251,301,303,306],{"class":164,"line":302},5,[251,304,305],{"class":256},"    if",[251,307,308],{"class":260}," geom.isNull():\n",[251,310,312,315,319,322,325,329,332,335,338,341,344,347,350],{"class":164,"line":311},6,[251,313,314],{"class":256},"        raise",[251,316,318],{"class":317},"sDLfK"," ValueError",[251,320,321],{"class":260},"(",[251,323,324],{"class":256},"f",[251,326,328],{"class":327},"sU2Wk","\"unparseable WKT: ",[251,330,331],{"class":317},"{",[251,333,334],{"class":260},"text[:",[251,336,337],{"class":317},"60",[251,339,340],{"class":260},"]",[251,342,343],{"class":256},"!r",[251,345,346],{"class":317},"}",[251,348,349],{"class":327},"\"",[251,351,352],{"class":260},")\n",[251,354,356,359],{"class":164,"line":355},7,[251,357,358],{"class":256},"    return",[251,360,361],{"class":260}," geom\n",[251,363,365],{"class":164,"line":364},8,[251,366,274],{"emptyLinePlaceholder":273},[251,368,370,373,375],{"class":164,"line":369},9,[251,371,372],{"class":260},"parcel ",[251,374,296],{"class":256},[251,376,377],{"class":260}," geometry_from_wkt(\n",[251,379,381,384],{"class":164,"line":380},10,[251,382,383],{"class":327},"    \"POLYGON((571200 5934000, 571260 5934000, 571260 5934045, 571200 5934045, 571200 5934000))\"",[251,385,352],{"class":260},[251,387,389,392],{"class":164,"line":388},11,[251,390,391],{"class":317},"print",[251,393,394],{"class":260},"(QgsWkbTypes.displayString(parcel.wkbType()), parcel.area())\n",[251,396,398],{"class":164,"line":397},12,[251,399,274],{"emptyLinePlaceholder":273},[251,401,403,406,408,411,414],{"class":164,"line":402},13,[251,404,405],{"class":260},"line_z ",[251,407,296],{"class":256},[251,409,410],{"class":260}," geometry_from_wkt(",[251,412,413],{"class":327},"\"LINESTRING Z (0 0 12.5, 10 0 13.1, 20 5 14.0)\"",[251,415,352],{"class":260},[251,417,419,421,424,427,430,433],{"class":164,"line":418},14,[251,420,391],{"class":317},[251,422,423],{"class":260},"(line_z.constGet().is3D(), [v.z() ",[251,425,426],{"class":256},"for",[251,428,429],{"class":260}," v ",[251,431,432],{"class":256},"in",[251,434,435],{"class":260}," line_z.vertices()])\n",[251,437,439],{"class":164,"line":438},15,[251,440,274],{"emptyLinePlaceholder":273},[251,442,444],{"class":164,"line":443},16,[251,445,447],{"class":446},"sjoCn","# WKB as bytes, e.g. from a database cursor or a hex column\n",[251,449,451,454,456],{"class":164,"line":450},17,[251,452,453],{"class":260},"hex_wkb ",[251,455,296],{"class":256},[251,457,458],{"class":327}," \"0101000000000000000000F03F0000000000000040\"\n",[251,460,462,465,467],{"class":164,"line":461},18,[251,463,464],{"class":260},"pt ",[251,466,296],{"class":256},[251,468,469],{"class":260}," QgsGeometry()\n",[251,471,473,476,479],{"class":164,"line":472},19,[251,474,475],{"class":260},"pt.fromWkb(",[251,477,478],{"class":317},"bytes",[251,480,481],{"class":260},".fromhex(hex_wkb))\n",[251,483,485,487,490],{"class":164,"line":484},20,[251,486,391],{"class":317},[251,488,489],{"class":260},"(pt.asWkt())          ",[251,491,492],{"class":446},"# Point (1 2)\n",[14,494,495,499,500,503,504,507,508,511,512,515,516,519,520,523,524,527],{},[496,497,498],"strong",{},"Breakdown:"," Stripping whitespace avoids the most common trivial failure — a trailing newline or tab from a spreadsheet cell. ",[18,501,502],{},"isNull()"," is the right test for a failed parse; ",[18,505,506],{},"isEmpty()"," is true for valid but empty geometries such as ",[18,509,510],{},"POINT EMPTY",", which some databases emit for missing values. The Z values survive because WKT declares them; ",[18,513,514],{},"constGet()"," gives access to the underlying ",[18,517,518],{},"QgsAbstractGeometry"," where dimension checks live. ",[18,521,522],{},"fromWkb"," is an instance method that fills an existing geometry, unlike the static ",[18,525,526],{},"fromWkt",", and it accepts both ISO and extended WKB, so PostGIS EWKB with an embedded SRID is read correctly — the SRID itself is ignored.",[216,529,531],{"id":530},"convert-geojson-objects","Convert GeoJSON objects",[14,533,534,535,537],{},"GeoJSON is the format web APIs speak. The geometry part is a small JSON object; there are two dependable ways to turn it into a ",[18,536,20],{},", depending on whether you have a single geometry or a whole feature collection.",[14,539,540],{},[34,541,544,547,550,553,560,563,569,574,578,583,587,590,595,597,600,604,608,610,613,616],{"viewBox":542,"role":37,"ariaLabel":543,"xmlns":39},"0 0 760 250","Two GeoJSON routes: a single geometry dictionary converted through OGR, and a whole feature collection parsed with QgsJsonUtils into features with attributes",[41,545,546],{},"Geometry object or feature collection",[45,548,549],{},"For a single GeoJSON geometry dictionary, the shortest route is to dump it to a string and let OGR create a geometry, then convert to WKB and into QgsGeometry. For a full FeatureCollection string, QgsJsonUtils.stringToFeatureList returns QgsFeature objects with geometry and attributes in one call, given fields from stringToFields. GeoJSON coordinates are always longitude then latitude in WGS 84.",[49,551],{"x":51,"y":51,"width":52,"height":552,"fill":54},"250",[56,554,555],{},[59,556,558],{"id":557,"viewBox":62,"refX":63,"refY":64,"markerWidth":65,"markerHeight":65,"orient":66},"geomJsonArrow",[68,559],{"d":70,"fill":71},[73,561,562],{"x":75,"y":76,"style":77,"fill":78,"textAnchor":79},"Geometry dict or whole collection?",[49,564],{"x":83,"y":84,"width":565,"height":566,"rx":63,"fill":567,"stroke":568,"style":89},"340","70","#eff3ff","#2563eb",[73,570,573],{"x":571,"y":572,"style":94,"fill":568,"textAnchor":79},"194","80.805","single geometry dict",[73,575,577],{"x":571,"y":576,"style":99,"fill":71,"textAnchor":79},"100.755","{\"type\": \"LineString\", \"coordinates\": …}",[49,579],{"x":580,"y":84,"width":565,"height":566,"rx":63,"fill":581,"stroke":582,"style":89},"396","#fdf2e2","#b45309",[73,584,586],{"x":585,"y":572,"style":94,"fill":582,"textAnchor":79},"566","FeatureCollection string",[73,588,589],{"x":585,"y":576,"style":99,"fill":71,"textAnchor":79},"{\"type\": \"FeatureCollection\", …}",[164,591],{"x1":571,"y1":592,"x2":571,"y2":593,"stroke":71,"style":594},"122","152","stroke-width:1.8;marker-end:url(#geomJsonArrow)",[164,596],{"x1":585,"y1":592,"x2":585,"y2":593,"stroke":71,"style":594},[49,598],{"x":83,"y":599,"width":565,"height":566,"rx":63,"fill":138,"stroke":139,"style":89},"156",[73,601,603],{"x":571,"y":602,"style":94,"fill":139,"textAnchor":79},"184.805","ogr.CreateGeometryFromJson",[73,605,607],{"x":571,"y":606,"style":209,"fill":88,"textAnchor":79},"204.755","→ ExportToWkb → QgsGeometry",[49,609],{"x":580,"y":599,"width":565,"height":566,"rx":63,"fill":138,"stroke":139,"style":89},[73,611,612],{"x":585,"y":602,"style":94,"fill":139,"textAnchor":79},"QgsJsonUtils.stringToFeatureList",[73,614,615],{"x":585,"y":606,"style":209,"fill":88,"textAnchor":79},"→ features with attributes",[73,617,620],{"x":75,"y":618,"style":619,"fill":88,"textAnchor":79},"244","text-anchor:middle;font-size:10.0px;font-family:sans-serif","coordinates are always lon, lat in EPSG:4326",[242,622,624],{"className":244,"code":623,"language":246,"meta":247,"style":247},"import json\nfrom osgeo import ogr\nfrom qgis.core import QgsGeometry, QgsJsonUtils\n\ndef geometry_from_geojson(obj):\n    \"\"\"obj is a dict like {\"type\": \"Point\", \"coordinates\": [lon, lat]}\"\"\"\n    ogr_geom = ogr.CreateGeometryFromJson(json.dumps(obj))\n    if ogr_geom is None:\n        raise ValueError(f\"bad GeoJSON geometry: {str(obj)[:60]}\")\n    geom = QgsGeometry()\n    geom.fromWkb(ogr_geom.ExportToIsoWkb())\n    return geom\n\nroute = geometry_from_geojson(\n    {\"type\": \"LineString\", \"coordinates\": [[13.37, 52.51], [13.40, 52.52], [13.42, 52.53]]})\nprint(route.length())       # in degrees — reproject before measuring\n\ntext = open(\"\u002Fdata\u002Finbox\u002Fstations.geojson\", encoding=\"utf-8\").read()\nfields = QgsJsonUtils.stringToFields(text)\nfeatures = QgsJsonUtils.stringToFeatureList(text, fields)\nprint(len(features), \"features with fields\", fields.names())\n",[18,625,626,633,645,656,660,670,675,685,701,730,738,743,749,753,763,818,828,832,861,871,881],{"__ignoreMap":247},[251,627,628,630],{"class":164,"line":253},[251,629,264],{"class":256},[251,631,632],{"class":260}," json\n",[251,634,635,637,640,642],{"class":164,"line":270},[251,636,257],{"class":256},[251,638,639],{"class":260}," osgeo ",[251,641,264],{"class":256},[251,643,644],{"class":260}," ogr\n",[251,646,647,649,651,653],{"class":164,"line":277},[251,648,257],{"class":256},[251,650,261],{"class":260},[251,652,264],{"class":256},[251,654,655],{"class":260}," QgsGeometry, QgsJsonUtils\n",[251,657,658],{"class":164,"line":290},[251,659,274],{"emptyLinePlaceholder":273},[251,661,662,664,667],{"class":164,"line":302},[251,663,280],{"class":256},[251,665,666],{"class":283}," geometry_from_geojson",[251,668,669],{"class":260},"(obj):\n",[251,671,672],{"class":164,"line":311},[251,673,674],{"class":327},"    \"\"\"obj is a dict like {\"type\": \"Point\", \"coordinates\": [lon, lat]}\"\"\"\n",[251,676,677,680,682],{"class":164,"line":355},[251,678,679],{"class":260},"    ogr_geom ",[251,681,296],{"class":256},[251,683,684],{"class":260}," ogr.CreateGeometryFromJson(json.dumps(obj))\n",[251,686,687,689,692,695,698],{"class":164,"line":364},[251,688,305],{"class":256},[251,690,691],{"class":260}," ogr_geom ",[251,693,694],{"class":256},"is",[251,696,697],{"class":317}," None",[251,699,700],{"class":260},":\n",[251,702,703,705,707,709,711,714,717,720,722,724,726,728],{"class":164,"line":369},[251,704,314],{"class":256},[251,706,318],{"class":317},[251,708,321],{"class":260},[251,710,324],{"class":256},[251,712,713],{"class":327},"\"bad GeoJSON geometry: ",[251,715,716],{"class":317},"{str",[251,718,719],{"class":260},"(obj)[:",[251,721,337],{"class":317},[251,723,340],{"class":260},[251,725,346],{"class":317},[251,727,349],{"class":327},[251,729,352],{"class":260},[251,731,732,734,736],{"class":164,"line":380},[251,733,293],{"class":260},[251,735,296],{"class":256},[251,737,469],{"class":260},[251,739,740],{"class":164,"line":388},[251,741,742],{"class":260},"    geom.fromWkb(ogr_geom.ExportToIsoWkb())\n",[251,744,745,747],{"class":164,"line":397},[251,746,358],{"class":256},[251,748,361],{"class":260},[251,750,751],{"class":164,"line":402},[251,752,274],{"emptyLinePlaceholder":273},[251,754,755,758,760],{"class":164,"line":418},[251,756,757],{"class":260},"route ",[251,759,296],{"class":256},[251,761,762],{"class":260}," geometry_from_geojson(\n",[251,764,765,768,771,774,777,780,783,786,789,791,794,797,800,802,805,807,810,812,815],{"class":164,"line":438},[251,766,767],{"class":260},"    {",[251,769,770],{"class":327},"\"type\"",[251,772,773],{"class":260},": ",[251,775,776],{"class":327},"\"LineString\"",[251,778,779],{"class":260},", ",[251,781,782],{"class":327},"\"coordinates\"",[251,784,785],{"class":260},": [[",[251,787,788],{"class":317},"13.37",[251,790,779],{"class":260},[251,792,793],{"class":317},"52.51",[251,795,796],{"class":260},"], [",[251,798,799],{"class":317},"13.40",[251,801,779],{"class":260},[251,803,804],{"class":317},"52.52",[251,806,796],{"class":260},[251,808,809],{"class":317},"13.42",[251,811,779],{"class":260},[251,813,814],{"class":317},"52.53",[251,816,817],{"class":260},"]]})\n",[251,819,820,822,825],{"class":164,"line":443},[251,821,391],{"class":317},[251,823,824],{"class":260},"(route.length())       ",[251,826,827],{"class":446},"# in degrees — reproject before measuring\n",[251,829,830],{"class":164,"line":450},[251,831,274],{"emptyLinePlaceholder":273},[251,833,834,837,839,842,844,847,849,853,855,858],{"class":164,"line":461},[251,835,836],{"class":260},"text ",[251,838,296],{"class":256},[251,840,841],{"class":317}," open",[251,843,321],{"class":260},[251,845,846],{"class":327},"\"\u002Fdata\u002Finbox\u002Fstations.geojson\"",[251,848,779],{"class":260},[251,850,852],{"class":851},"s9osk","encoding",[251,854,296],{"class":256},[251,856,857],{"class":327},"\"utf-8\"",[251,859,860],{"class":260},").read()\n",[251,862,863,866,868],{"class":164,"line":472},[251,864,865],{"class":260},"fields ",[251,867,296],{"class":256},[251,869,870],{"class":260}," QgsJsonUtils.stringToFields(text)\n",[251,872,873,876,878],{"class":164,"line":484},[251,874,875],{"class":260},"features ",[251,877,296],{"class":256},[251,879,880],{"class":260}," QgsJsonUtils.stringToFeatureList(text, fields)\n",[251,882,884,886,888,891,894,897],{"class":164,"line":883},21,[251,885,391],{"class":317},[251,887,321],{"class":260},[251,889,890],{"class":317},"len",[251,892,893],{"class":260},"(features), ",[251,895,896],{"class":327},"\"features with fields\"",[251,898,899],{"class":260},", fields.names())\n",[14,901,902,904,905,908,909,912,913,916,917,920,921,924,925,929,930,934,935,938],{},[496,903,498],{}," GDAL's OGR bindings ship with every QGIS installation, so routing a single geometry through ",[18,906,907],{},"CreateGeometryFromJson"," adds no dependency and handles every geometry type including ",[18,910,911],{},"GeometryCollection",". ",[18,914,915],{},"ExportToIsoWkb"," keeps Z and M values in the ISO form QGIS expects. For a complete document, ",[18,918,919],{},"QgsJsonUtils"," parses features and their properties in one step — ",[18,922,923],{},"stringToFields"," infers the schema from the properties, so you can create a matching ",[26,926,928],{"href":927},"\u002Fpyqgis-fundamentals-environment-setup\u002Ffeatures-geometries-and-memory-layers\u002Fcreate-memory-layer-pyqgis\u002F","memory layer"," and add the features directly. The length printed for the route is in degrees, which is meaningless as a distance; GeoJSON is always WGS 84 longitude and latitude, so measure after ",[26,931,933],{"href":932},"\u002Fspatial-data-processing-automation\u002Fcoordinate-reference-systems\u002Ftransform-point-coordinates-pyqgis\u002F","transforming the coordinates"," or with ",[18,936,937],{},"QgsDistanceArea",".",[216,940,942],{"id":941},"build-geometry-from-coordinate-lists","Build geometry from coordinate lists",[14,944,945],{},"When coordinates come as plain numbers — CSV columns, a GPS log, values computed in a loop — the typed factories are faster and clearer than formatting a WKT string only to parse it again.",[242,947,949],{"className":244,"code":948,"language":246,"meta":247,"style":247},"from qgis.core import (QgsGeometry, QgsPointXY, QgsPoint, QgsLineString,\n                       QgsPolygon)\n\nxy = [(571200, 5934000), (571260, 5934000), (571260, 5934045), (571200, 5934045)]\n\npoint = QgsGeometry.fromPointXY(QgsPointXY(*xy[0]))\nline = QgsGeometry.fromPolylineXY([QgsPointXY(x, y) for x, y in xy])\nring = [QgsPointXY(x, y) for x, y in xy] + [QgsPointXY(*xy[0])]\npolygon = QgsGeometry.fromPolygonXY([ring])\n\n# with Z values: build the abstract geometry, then wrap it\ntrack = QgsLineString([QgsPoint(x, y, z) for x, y, z in\n                       [(0, 0, 410.2), (35, 12, 412.8), (71, 30, 415.0)]])\ntrack_geom = QgsGeometry(track)\nprint(polygon.isGeosValid(), track_geom.constGet().is3D())\n",[18,950,951,962,967,971,1019,1023,1044,1064,1098,1108,1112,1117,1135,1184,1194],{"__ignoreMap":247},[251,952,953,955,957,959],{"class":164,"line":253},[251,954,257],{"class":256},[251,956,261],{"class":260},[251,958,264],{"class":256},[251,960,961],{"class":260}," (QgsGeometry, QgsPointXY, QgsPoint, QgsLineString,\n",[251,963,964],{"class":164,"line":270},[251,965,966],{"class":260},"                       QgsPolygon)\n",[251,968,969],{"class":164,"line":277},[251,970,274],{"emptyLinePlaceholder":273},[251,972,973,976,978,981,984,986,989,992,995,997,999,1001,1003,1005,1008,1010,1012,1014,1016],{"class":164,"line":290},[251,974,975],{"class":260},"xy ",[251,977,296],{"class":256},[251,979,980],{"class":260}," [(",[251,982,983],{"class":317},"571200",[251,985,779],{"class":260},[251,987,988],{"class":317},"5934000",[251,990,991],{"class":260},"), (",[251,993,994],{"class":317},"571260",[251,996,779],{"class":260},[251,998,988],{"class":317},[251,1000,991],{"class":260},[251,1002,994],{"class":317},[251,1004,779],{"class":260},[251,1006,1007],{"class":317},"5934045",[251,1009,991],{"class":260},[251,1011,983],{"class":317},[251,1013,779],{"class":260},[251,1015,1007],{"class":317},[251,1017,1018],{"class":260},")]\n",[251,1020,1021],{"class":164,"line":302},[251,1022,274],{"emptyLinePlaceholder":273},[251,1024,1025,1028,1030,1033,1036,1039,1041],{"class":164,"line":311},[251,1026,1027],{"class":260},"point ",[251,1029,296],{"class":256},[251,1031,1032],{"class":260}," QgsGeometry.fromPointXY(QgsPointXY(",[251,1034,1035],{"class":256},"*",[251,1037,1038],{"class":260},"xy[",[251,1040,51],{"class":317},[251,1042,1043],{"class":260},"]))\n",[251,1045,1046,1049,1051,1054,1056,1059,1061],{"class":164,"line":355},[251,1047,1048],{"class":260},"line ",[251,1050,296],{"class":256},[251,1052,1053],{"class":260}," QgsGeometry.fromPolylineXY([QgsPointXY(x, y) ",[251,1055,426],{"class":256},[251,1057,1058],{"class":260}," x, y ",[251,1060,432],{"class":256},[251,1062,1063],{"class":260}," xy])\n",[251,1065,1066,1069,1071,1074,1076,1078,1080,1083,1086,1089,1091,1093,1095],{"class":164,"line":364},[251,1067,1068],{"class":260},"ring ",[251,1070,296],{"class":256},[251,1072,1073],{"class":260}," [QgsPointXY(x, y) ",[251,1075,426],{"class":256},[251,1077,1058],{"class":260},[251,1079,432],{"class":256},[251,1081,1082],{"class":260}," xy] ",[251,1084,1085],{"class":256},"+",[251,1087,1088],{"class":260}," [QgsPointXY(",[251,1090,1035],{"class":256},[251,1092,1038],{"class":260},[251,1094,51],{"class":317},[251,1096,1097],{"class":260},"])]\n",[251,1099,1100,1103,1105],{"class":164,"line":369},[251,1101,1102],{"class":260},"polygon ",[251,1104,296],{"class":256},[251,1106,1107],{"class":260}," QgsGeometry.fromPolygonXY([ring])\n",[251,1109,1110],{"class":164,"line":380},[251,1111,274],{"emptyLinePlaceholder":273},[251,1113,1114],{"class":164,"line":388},[251,1115,1116],{"class":446},"# with Z values: build the abstract geometry, then wrap it\n",[251,1118,1119,1122,1124,1127,1129,1132],{"class":164,"line":397},[251,1120,1121],{"class":260},"track ",[251,1123,296],{"class":256},[251,1125,1126],{"class":260}," QgsLineString([QgsPoint(x, y, z) ",[251,1128,426],{"class":256},[251,1130,1131],{"class":260}," x, y, z ",[251,1133,1134],{"class":256},"in\n",[251,1136,1137,1140,1142,1144,1146,1148,1151,1153,1156,1158,1161,1163,1166,1168,1171,1173,1176,1178,1181],{"class":164,"line":402},[251,1138,1139],{"class":260},"                       [(",[251,1141,51],{"class":317},[251,1143,779],{"class":260},[251,1145,51],{"class":317},[251,1147,779],{"class":260},[251,1149,1150],{"class":317},"410.2",[251,1152,991],{"class":260},[251,1154,1155],{"class":317},"35",[251,1157,779],{"class":260},[251,1159,1160],{"class":317},"12",[251,1162,779],{"class":260},[251,1164,1165],{"class":317},"412.8",[251,1167,991],{"class":260},[251,1169,1170],{"class":317},"71",[251,1172,779],{"class":260},[251,1174,1175],{"class":317},"30",[251,1177,779],{"class":260},[251,1179,1180],{"class":317},"415.0",[251,1182,1183],{"class":260},")]])\n",[251,1185,1186,1189,1191],{"class":164,"line":418},[251,1187,1188],{"class":260},"track_geom ",[251,1190,296],{"class":256},[251,1192,1193],{"class":260}," QgsGeometry(track)\n",[251,1195,1196,1198],{"class":164,"line":438},[251,1197,391],{"class":317},[251,1199,1200],{"class":260},"(polygon.isGeosValid(), track_geom.constGet().is3D())\n",[14,1202,1203,1205,1206,1209,1210,1213,1214,1217,1218,1221,1222,1225,1226,1228,1229,1232,1233,1235],{},[496,1204,498],{}," The ",[18,1207,1208],{},"XY"," factories are 2D only: ",[18,1211,1212],{},"QgsPointXY"," has no Z, so elevation is dropped silently. For 3D data, build a ",[18,1215,1216],{},"QgsLineString"," or ",[18,1219,1220],{},"QgsPolygon"," from ",[18,1223,1224],{},"QgsPoint"," objects, which carry Z and M, and wrap it in ",[18,1227,20],{}," — the wrapper takes ownership. Polygon rings must be closed: ",[18,1230,1231],{},"fromPolygonXY"," closes an open ring for you in current releases, but adding the first point at the end yourself makes the intent explicit and keeps older versions happy. Each list passed to ",[18,1234,1231],{}," after the first is a hole.",[216,1237,1239],{"id":1238},"validate-before-you-store","Validate before you store",[14,1241,1242],{},"A parsed geometry can still be unusable: a self-intersecting polygon, a line with a single vertex, a ring wound the wrong way for a strict consumer. Checking at the point of creation means the error message can name the source row, which is impossible once the geometry is one of fifty thousand in a layer.",[14,1244,1245],{},[34,1246,1249,1252,1255,1258,1265,1268,1274,1278,1282,1286,1290,1293,1296,1299,1302,1305,1308,1312,1315,1318,1321,1326,1330,1335,1339,1343],{"viewBox":1247,"role":37,"ariaLabel":1248,"xmlns":39},"0 0 760 260","Three ordered checks on a new geometry: null after parsing, type matching the layer, and topological validity, each with its remedy",[41,1250,1251],{},"Three checks in order",[45,1253,1254],{},"Each new geometry passes three checks. isNull catches a failed parse. The geometry type check compares the parsed type with the layer type, for example a MultiPolygon arriving for a Polygon layer, which can be fixed by converting to multi. isGeosValid catches topological problems such as self-intersections, which makeValid can usually repair. Only geometries that pass all three are added.",[49,1256],{"x":51,"y":51,"width":52,"height":1257,"fill":54},"260",[56,1259,1260],{},[59,1261,1263],{"id":1262,"viewBox":62,"refX":63,"refY":64,"markerWidth":65,"markerHeight":65,"orient":66},"geomCheckArrow",[68,1264],{"d":70,"fill":71},[73,1266,1267],{"x":75,"y":76,"style":77,"fill":78,"textAnchor":79},"Catch the failure where you can still name the row",[49,1269],{"x":83,"y":1270,"width":1271,"height":1272,"rx":63,"fill":581,"stroke":1273,"style":89},"56","220","120","#b91c1c",[73,1275,502],{"x":1276,"y":1277,"style":94,"fill":1273,"textAnchor":79},"134","89.855",[73,1279,1281],{"x":1276,"y":1280,"style":209,"fill":71,"textAnchor":79},"109.805","parse failed",[73,1283,1285],{"x":1276,"y":1284,"style":209,"fill":88,"textAnchor":79},"129.755","log the raw input",[73,1287,1289],{"x":1276,"y":1288,"style":209,"fill":88,"textAnchor":79},"149.705","skip the row",[49,1291],{"x":1292,"y":1270,"width":1271,"height":1272,"rx":63,"fill":581,"stroke":582,"style":89},"270",[73,1294,1295],{"x":75,"y":1277,"style":94,"fill":582,"textAnchor":79},"type matches layer?",[73,1297,1298],{"x":75,"y":1280,"style":209,"fill":71,"textAnchor":79},"Polygon vs Multi",[73,1300,1301],{"x":75,"y":1284,"style":209,"fill":88,"textAnchor":79},"convertToMultiType()",[73,1303,1304],{"x":75,"y":1288,"style":209,"fill":88,"textAnchor":79},"or create Multi layer",[49,1306],{"x":1307,"y":1270,"width":1271,"height":1272,"rx":63,"fill":567,"stroke":568,"style":89},"516",[73,1309,1311],{"x":1310,"y":1277,"style":94,"fill":568,"textAnchor":79},"626","isGeosValid()",[73,1313,1314],{"x":1310,"y":1280,"style":209,"fill":71,"textAnchor":79},"self-intersections",[73,1316,1317],{"x":1310,"y":1284,"style":209,"fill":88,"textAnchor":79},"makeValid() repairs",[73,1319,1320],{"x":1310,"y":1288,"style":209,"fill":88,"textAnchor":79},"log what changed",[164,1322],{"x1":618,"y1":1323,"x2":1324,"y2":1323,"stroke":71,"style":1325},"116","266","stroke-width:1.8;marker-end:url(#geomCheckArrow)",[164,1327],{"x1":1328,"y1":1323,"x2":1329,"y2":1323,"stroke":71,"style":1325},"490","512",[49,1331],{"x":1332,"y":137,"width":1333,"height":1334,"rx":63,"fill":199,"stroke":200,"style":89},"230","300","44",[73,1336,1338],{"x":75,"y":1337,"style":94,"fill":205,"textAnchor":79},"215.805","addFeatures(...)",[73,1340,1342],{"x":75,"y":1341,"style":209,"fill":88,"textAnchor":79},"235.755","only clean geometry",[164,1344],{"x1":1310,"y1":189,"x2":1345,"y2":137,"stroke":71,"style":1325},"500",[242,1347,1349],{"className":244,"code":1348,"language":246,"meta":247,"style":247},"from qgis.core import QgsWkbTypes\n\ndef clean_for_layer(geom, layer, row_id):\n    if geom.isNull():\n        raise ValueError(f\"row {row_id}: no geometry\")\n    target = layer.wkbType()\n    if QgsWkbTypes.isMultiType(target) and not geom.isMultipart():\n        geom.convertToMultiType()\n    if QgsWkbTypes.geometryType(geom.wkbType()) != QgsWkbTypes.geometryType(target):\n        raise ValueError(f\"row {row_id}: {geom.type()} into {layer.geometryType()} layer\")\n    if not geom.isGeosValid():\n        fixed = geom.makeValid()\n        print(f\"row {row_id}: repaired invalid geometry\")\n        geom = fixed\n    return geom\n",[18,1350,1351,1362,1366,1376,1382,1407,1417,1433,1438,1451,1493,1502,1512,1534,1544],{"__ignoreMap":247},[251,1352,1353,1355,1357,1359],{"class":164,"line":253},[251,1354,257],{"class":256},[251,1356,261],{"class":260},[251,1358,264],{"class":256},[251,1360,1361],{"class":260}," QgsWkbTypes\n",[251,1363,1364],{"class":164,"line":270},[251,1365,274],{"emptyLinePlaceholder":273},[251,1367,1368,1370,1373],{"class":164,"line":277},[251,1369,280],{"class":256},[251,1371,1372],{"class":283}," clean_for_layer",[251,1374,1375],{"class":260},"(geom, layer, row_id):\n",[251,1377,1378,1380],{"class":164,"line":290},[251,1379,305],{"class":256},[251,1381,308],{"class":260},[251,1383,1384,1386,1388,1390,1392,1395,1397,1400,1402,1405],{"class":164,"line":302},[251,1385,314],{"class":256},[251,1387,318],{"class":317},[251,1389,321],{"class":260},[251,1391,324],{"class":256},[251,1393,1394],{"class":327},"\"row ",[251,1396,331],{"class":317},[251,1398,1399],{"class":260},"row_id",[251,1401,346],{"class":317},[251,1403,1404],{"class":327},": no geometry\"",[251,1406,352],{"class":260},[251,1408,1409,1412,1414],{"class":164,"line":311},[251,1410,1411],{"class":260},"    target ",[251,1413,296],{"class":256},[251,1415,1416],{"class":260}," layer.wkbType()\n",[251,1418,1419,1421,1424,1427,1430],{"class":164,"line":355},[251,1420,305],{"class":256},[251,1422,1423],{"class":260}," QgsWkbTypes.isMultiType(target) ",[251,1425,1426],{"class":256},"and",[251,1428,1429],{"class":256}," not",[251,1431,1432],{"class":260}," geom.isMultipart():\n",[251,1434,1435],{"class":164,"line":364},[251,1436,1437],{"class":260},"        geom.convertToMultiType()\n",[251,1439,1440,1442,1445,1448],{"class":164,"line":369},[251,1441,305],{"class":256},[251,1443,1444],{"class":260}," QgsWkbTypes.geometryType(geom.wkbType()) ",[251,1446,1447],{"class":256},"!=",[251,1449,1450],{"class":260}," QgsWkbTypes.geometryType(target):\n",[251,1452,1453,1455,1457,1459,1461,1463,1465,1467,1469,1471,1473,1476,1478,1481,1483,1486,1488,1491],{"class":164,"line":380},[251,1454,314],{"class":256},[251,1456,318],{"class":317},[251,1458,321],{"class":260},[251,1460,324],{"class":256},[251,1462,1394],{"class":327},[251,1464,331],{"class":317},[251,1466,1399],{"class":260},[251,1468,346],{"class":317},[251,1470,773],{"class":327},[251,1472,331],{"class":317},[251,1474,1475],{"class":260},"geom.type()",[251,1477,346],{"class":317},[251,1479,1480],{"class":327}," into ",[251,1482,331],{"class":317},[251,1484,1485],{"class":260},"layer.geometryType()",[251,1487,346],{"class":317},[251,1489,1490],{"class":327}," layer\"",[251,1492,352],{"class":260},[251,1494,1495,1497,1499],{"class":164,"line":388},[251,1496,305],{"class":256},[251,1498,1429],{"class":256},[251,1500,1501],{"class":260}," geom.isGeosValid():\n",[251,1503,1504,1507,1509],{"class":164,"line":397},[251,1505,1506],{"class":260},"        fixed ",[251,1508,296],{"class":256},[251,1510,1511],{"class":260}," geom.makeValid()\n",[251,1513,1514,1517,1519,1521,1523,1525,1527,1529,1532],{"class":164,"line":402},[251,1515,1516],{"class":317},"        print",[251,1518,321],{"class":260},[251,1520,324],{"class":256},[251,1522,1394],{"class":327},[251,1524,331],{"class":317},[251,1526,1399],{"class":260},[251,1528,346],{"class":317},[251,1530,1531],{"class":327},": repaired invalid geometry\"",[251,1533,352],{"class":260},[251,1535,1536,1539,1541],{"class":164,"line":418},[251,1537,1538],{"class":260},"        geom ",[251,1540,296],{"class":256},[251,1542,1543],{"class":260}," fixed\n",[251,1545,1546,1548],{"class":164,"line":438},[251,1547,358],{"class":256},[251,1549,361],{"class":260},[14,1551,1552,1554,1555,1559,1560,1563,1564,1568],{},[496,1553,498],{}," The type check compares geometry ",[1556,1557,1558],"em",{},"families"," — point, line, polygon — so a single polygon going into a multipolygon layer is converted rather than rejected, while a line going into a polygon layer is refused. ",[18,1561,1562],{},"makeValid"," uses GEOS's repair, which can change the geometry type (a bow-tie polygon becomes a multipolygon), so it runs before the layer type is checked in production code if repairs are common. For a whole layer rather than individual rows, ",[26,1565,1567],{"href":1566},"\u002Fspatial-data-processing-automation\u002Fgeometry-operations-and-predicates\u002Ffix-invalid-geometries-pyqgis\u002F","fixing invalid geometries"," with Processing is faster.",[216,1570,1572],{"id":1571},"load-a-whole-file-of-wkt-rows","Load a whole file of WKT rows",[14,1574,1575],{},"The checks above pay off when they run inside a loader. The pattern below reads a text export with an identifier and a WKT column, builds every geometry, keeps a list of rejected rows with the reason, and adds the good features in a single call. It is the same shape whether the input is a CSV, a database cursor or a list returned by an API.",[242,1577,1579],{"className":244,"code":1578,"language":246,"meta":247,"style":247},"import csv\nfrom qgis.core import QgsVectorLayer, QgsFeature, QgsProject\n\nlayer = QgsVectorLayer(\"MultiPolygon?crs=EPSG:25832&field=parcel_id:string(20)\",\n                       \"parcels (import)\", \"memory\")\ngood, rejected = [], []\nwith open(\"\u002Fdata\u002Finbox\u002Fparcels_wkt.csv\", newline=\"\", encoding=\"utf-8\") as fh:\n    for row in csv.DictReader(fh, delimiter=\";\"):\n        try:\n            geom = clean_for_layer(geometry_from_wkt(row[\"wkt\"]), layer, row[\"parcel_id\"])\n        except ValueError as err:\n            rejected.append((row[\"parcel_id\"], str(err)))\n            continue\n        f = QgsFeature(layer.fields())\n        f[\"parcel_id\"] = row[\"parcel_id\"]\n        f.setGeometry(geom)\n        good.append(f)\n\nlayer.dataProvider().addFeatures(good)\nlayer.updateExtents()\nQgsProject.instance().addMapLayer(layer)\nprint(f\"{len(good)} loaded, {len(rejected)} rejected\")\nfor pid, why in rejected[:10]:\n    print(\"  \", pid, why)\n",[18,1580,1581,1588,1599,1603,1619,1631,1641,1680,1704,1711,1733,1746,1762,1767,1777,1797,1802,1807,1811,1816,1821,1826,1860,1879],{"__ignoreMap":247},[251,1582,1583,1585],{"class":164,"line":253},[251,1584,264],{"class":256},[251,1586,1587],{"class":260}," csv\n",[251,1589,1590,1592,1594,1596],{"class":164,"line":270},[251,1591,257],{"class":256},[251,1593,261],{"class":260},[251,1595,264],{"class":256},[251,1597,1598],{"class":260}," QgsVectorLayer, QgsFeature, QgsProject\n",[251,1600,1601],{"class":164,"line":277},[251,1602,274],{"emptyLinePlaceholder":273},[251,1604,1605,1608,1610,1613,1616],{"class":164,"line":290},[251,1606,1607],{"class":260},"layer ",[251,1609,296],{"class":256},[251,1611,1612],{"class":260}," QgsVectorLayer(",[251,1614,1615],{"class":327},"\"MultiPolygon?crs=EPSG:25832&field=parcel_id:string(20)\"",[251,1617,1618],{"class":260},",\n",[251,1620,1621,1624,1626,1629],{"class":164,"line":302},[251,1622,1623],{"class":327},"                       \"parcels (import)\"",[251,1625,779],{"class":260},[251,1627,1628],{"class":327},"\"memory\"",[251,1630,352],{"class":260},[251,1632,1633,1636,1638],{"class":164,"line":311},[251,1634,1635],{"class":260},"good, rejected ",[251,1637,296],{"class":256},[251,1639,1640],{"class":260}," [], []\n",[251,1642,1643,1646,1648,1650,1653,1655,1658,1660,1663,1665,1667,1669,1671,1674,1677],{"class":164,"line":355},[251,1644,1645],{"class":256},"with",[251,1647,841],{"class":317},[251,1649,321],{"class":260},[251,1651,1652],{"class":327},"\"\u002Fdata\u002Finbox\u002Fparcels_wkt.csv\"",[251,1654,779],{"class":260},[251,1656,1657],{"class":851},"newline",[251,1659,296],{"class":256},[251,1661,1662],{"class":327},"\"\"",[251,1664,779],{"class":260},[251,1666,852],{"class":851},[251,1668,296],{"class":256},[251,1670,857],{"class":327},[251,1672,1673],{"class":260},") ",[251,1675,1676],{"class":256},"as",[251,1678,1679],{"class":260}," fh:\n",[251,1681,1682,1685,1688,1690,1693,1696,1698,1701],{"class":164,"line":364},[251,1683,1684],{"class":256},"    for",[251,1686,1687],{"class":260}," row ",[251,1689,432],{"class":256},[251,1691,1692],{"class":260}," csv.DictReader(fh, ",[251,1694,1695],{"class":851},"delimiter",[251,1697,296],{"class":256},[251,1699,1700],{"class":327},"\";\"",[251,1702,1703],{"class":260},"):\n",[251,1705,1706,1709],{"class":164,"line":369},[251,1707,1708],{"class":256},"        try",[251,1710,700],{"class":260},[251,1712,1713,1716,1718,1721,1724,1727,1730],{"class":164,"line":380},[251,1714,1715],{"class":260},"            geom ",[251,1717,296],{"class":256},[251,1719,1720],{"class":260}," clean_for_layer(geometry_from_wkt(row[",[251,1722,1723],{"class":327},"\"wkt\"",[251,1725,1726],{"class":260},"]), layer, row[",[251,1728,1729],{"class":327},"\"parcel_id\"",[251,1731,1732],{"class":260},"])\n",[251,1734,1735,1738,1740,1743],{"class":164,"line":388},[251,1736,1737],{"class":256},"        except",[251,1739,318],{"class":317},[251,1741,1742],{"class":256}," as",[251,1744,1745],{"class":260}," err:\n",[251,1747,1748,1751,1753,1756,1759],{"class":164,"line":397},[251,1749,1750],{"class":260},"            rejected.append((row[",[251,1752,1729],{"class":327},[251,1754,1755],{"class":260},"], ",[251,1757,1758],{"class":317},"str",[251,1760,1761],{"class":260},"(err)))\n",[251,1763,1764],{"class":164,"line":402},[251,1765,1766],{"class":256},"            continue\n",[251,1768,1769,1772,1774],{"class":164,"line":418},[251,1770,1771],{"class":260},"        f ",[251,1773,296],{"class":256},[251,1775,1776],{"class":260}," QgsFeature(layer.fields())\n",[251,1778,1779,1782,1784,1787,1789,1792,1794],{"class":164,"line":438},[251,1780,1781],{"class":260},"        f[",[251,1783,1729],{"class":327},[251,1785,1786],{"class":260},"] ",[251,1788,296],{"class":256},[251,1790,1791],{"class":260}," row[",[251,1793,1729],{"class":327},[251,1795,1796],{"class":260},"]\n",[251,1798,1799],{"class":164,"line":443},[251,1800,1801],{"class":260},"        f.setGeometry(geom)\n",[251,1803,1804],{"class":164,"line":450},[251,1805,1806],{"class":260},"        good.append(f)\n",[251,1808,1809],{"class":164,"line":461},[251,1810,274],{"emptyLinePlaceholder":273},[251,1812,1813],{"class":164,"line":472},[251,1814,1815],{"class":260},"layer.dataProvider().addFeatures(good)\n",[251,1817,1818],{"class":164,"line":484},[251,1819,1820],{"class":260},"layer.updateExtents()\n",[251,1822,1823],{"class":164,"line":883},[251,1824,1825],{"class":260},"QgsProject.instance().addMapLayer(layer)\n",[251,1827,1829,1831,1833,1835,1837,1840,1843,1845,1848,1850,1853,1855,1858],{"class":164,"line":1828},22,[251,1830,391],{"class":317},[251,1832,321],{"class":260},[251,1834,324],{"class":256},[251,1836,349],{"class":327},[251,1838,1839],{"class":317},"{len",[251,1841,1842],{"class":260},"(good)",[251,1844,346],{"class":317},[251,1846,1847],{"class":327}," loaded, ",[251,1849,1839],{"class":317},[251,1851,1852],{"class":260},"(rejected)",[251,1854,346],{"class":317},[251,1856,1857],{"class":327}," rejected\"",[251,1859,352],{"class":260},[251,1861,1863,1865,1868,1870,1873,1876],{"class":164,"line":1862},23,[251,1864,426],{"class":256},[251,1866,1867],{"class":260}," pid, why ",[251,1869,432],{"class":256},[251,1871,1872],{"class":260}," rejected[:",[251,1874,1875],{"class":317},"10",[251,1877,1878],{"class":260},"]:\n",[251,1880,1882,1885,1887,1890],{"class":164,"line":1881},24,[251,1883,1884],{"class":317},"    print",[251,1886,321],{"class":260},[251,1888,1889],{"class":327},"\"  \"",[251,1891,1892],{"class":260},", pid, why)\n",[14,1894,1895,1897,1898,1901,1902,1905,1906,1910],{},[496,1896,498],{}," Declaring the layer as ",[18,1899,1900],{},"MultiPolygon"," lets single polygons and multipolygons coexist, with ",[18,1903,1904],{},"clean_for_layer"," promoting the singles. Collecting rejections instead of stopping at the first one means a single pass tells you everything that is wrong with the file, and printing the first ten keeps the console readable when a systematic problem rejects thousands. If the file is large and well-formed, the ",[26,1907,1909],{"href":1908},"\u002Fspatial-data-processing-automation\u002Flayer-data-sources-and-formats\u002Fload-csv-as-point-layer-pyqgis\u002F","delimited text provider"," reads a WKT column directly and is faster — but it gives no per-row diagnosis, which is exactly what an import from an unfamiliar source needs first.",[216,1912,1914],{"id":1913},"write-geometry-back-out","Write geometry back out",[14,1916,1917,1918,779,1921,779,1924,1927],{},"Exporting is the mirror image, and every format has a method: ",[18,1919,1920],{},"asWkt(precision)",[18,1922,1923],{},"asWkb()",[18,1925,1926],{},"asJson(precision)",". Precision matters when the output is going into logs or an API payload, where full double precision wastes space and implies an accuracy the data does not have.",[242,1929,1931],{"className":244,"code":1930,"language":246,"meta":247,"style":247},"print(parcel.asWkt(2))      # Polygon ((571200 5934000, 571260 5934000, ...))\nprint(parcel.asJson(1))     # {\"type\":\"Polygon\",\"coordinates\":[[[571200.0,...]]]}\nwkb_hex = parcel.asWkb().toHex().data().decode()\nprint(wkb_hex[:24], \"…\")\n",[18,1932,1933,1949,1965,1975],{"__ignoreMap":247},[251,1934,1935,1937,1940,1943,1946],{"class":164,"line":253},[251,1936,391],{"class":317},[251,1938,1939],{"class":260},"(parcel.asWkt(",[251,1941,1942],{"class":317},"2",[251,1944,1945],{"class":260},"))      ",[251,1947,1948],{"class":446},"# Polygon ((571200 5934000, 571260 5934000, ...))\n",[251,1950,1951,1953,1956,1959,1962],{"class":164,"line":270},[251,1952,391],{"class":317},[251,1954,1955],{"class":260},"(parcel.asJson(",[251,1957,1958],{"class":317},"1",[251,1960,1961],{"class":260},"))     ",[251,1963,1964],{"class":446},"# {\"type\":\"Polygon\",\"coordinates\":[[[571200.0,...]]]}\n",[251,1966,1967,1970,1972],{"class":164,"line":277},[251,1968,1969],{"class":260},"wkb_hex ",[251,1971,296],{"class":256},[251,1973,1974],{"class":260}," parcel.asWkb().toHex().data().decode()\n",[251,1976,1977,1979,1982,1984,1986,1989],{"class":164,"line":290},[251,1978,391],{"class":317},[251,1980,1981],{"class":260},"(wkb_hex[:",[251,1983,83],{"class":317},[251,1985,1755],{"class":260},[251,1987,1988],{"class":327},"\"…\"",[251,1990,352],{"class":260},[14,1992,1993,1995,1996,1999,2000,2003,2004,2007,2008,2010,2011,2014],{},[496,1994,498],{}," ",[18,1997,1998],{},"asJson"," writes the geometry's coordinates as they are, without reprojecting; if the layer is not in EPSG:4326 the result is valid JSON but not valid GeoJSON. For a full feature with properties in WGS 84, ",[18,2001,2002],{},"QgsJsonExporter"," with ",[18,2005,2006],{},"setDestinationCrs"," handles both. ",[18,2009,1923],{}," returns a ",[18,2012,2013],{},"QByteArray",", which is why the hex conversion takes three calls.",[216,2016,2018],{"id":2017},"qgis-version-compatibility","QGIS version compatibility",[14,2020,2021,2022,2024,2025,2028,2029,2032,2033,2035,2036,2039,2040,2028,2043,2046,2047,2049],{},"All factories shown work in QGIS 3.x and QGIS 4. ",[18,2023,239],{}," accepts case-insensitive type names and both ",[18,2026,2027],{},"POINT Z (…)"," and ",[18,2030,2031],{},"POINTZ(…)"," forms. ",[18,2034,1562],{}," gained its method and keep-collapsed options in 3.28; the default call shown is portable. On QGIS 4, ",[18,2037,2038],{},"QgsWkbTypes"," enum members are reached as ",[18,2041,2042],{},"Qgis.WkbType",[18,2044,2045],{},"Qgis.GeometryType","; the ",[18,2048,2038],{}," helper functions remain.",[216,2051,2053],{"id":2052},"troubleshooting","Troubleshooting",[221,2055,2056,2068,2074,2091],{},[224,2057,2058,2061,2062,2065,2066,938],{},[496,2059,2060],{},"Every geometry is null."," The WKT uses a comma as decimal separator, or has a prefix such as ",[18,2063,2064],{},"SRID=4326;"," — strip the SRID part before calling ",[18,2067,526],{},[224,2069,2070,2073],{},[496,2071,2072],{},"Points land near 0,0 or in the ocean."," The numbers are latitude, longitude rather than longitude, latitude; swap them when building the points.",[224,2075,2076,2079,2080,2083,2084,1217,2087,2090],{},[496,2077,2078],{},"Z values disappear."," The geometry was built through a ",[18,2081,2082],{},"…XY"," factory or added to a 2D layer; create a ",[18,2085,2086],{},"PointZ",[18,2088,2089],{},"LineStringZ"," layer.",[224,2092,2093,2098,2099,938],{},[496,2094,2095,2097],{},[18,2096,522],{}," returns an empty geometry."," The input is a hex string, not bytes; convert with ",[18,2100,2101],{},"bytes.fromhex",[216,2103,2105],{"id":2104},"conclusion","Conclusion",[14,2107,2108,2109,2028,2111,2113,2114,2116,2117,2119,2120,2122],{},"Use ",[18,2110,526],{},[18,2112,522],{}," for text and binary encodings, OGR or ",[18,2115,919],{}," for GeoJSON, and the typed factories for coordinate lists — ",[18,2118,1224],{}," rather than ",[18,2121,1212],{}," when Z matters. Check for null, matching type and validity at the moment of creation, and export with an explicit precision.",[216,2124,2126],{"id":2125},"frequently-asked-questions","Frequently Asked Questions",[14,2128,2129,2132,2133,2136],{},[496,2130,2131],{},"Does a QgsGeometry know its CRS?","\nNo. It is a bare shape; the CRS belongs to the layer or to a ",[18,2134,2135],{},"QgsCoordinateTransform"," you apply. Keep track of it alongside the geometry.",[14,2138,2139,2146,2147,938],{},[496,2140,2141,2142,2145],{},"How do I parse EWKT like ",[18,2143,2144],{},"SRID=25832;POINT(1 2)","?","\nSplit at the semicolon, use the number to choose the layer CRS, and pass the remainder to ",[18,2148,526],{},[14,2150,2151,2154,2155,779,2158,2028,2161,2164],{},[496,2152,2153],{},"Can I create curved geometries from WKT?","\nYes. ",[18,2156,2157],{},"CIRCULARSTRING",[18,2159,2160],{},"COMPOUNDCURVE",[18,2162,2163],{},"CURVEPOLYGON"," parse into curved geometry types that QGIS draws as true arcs.",[14,2166,2167,2170,2171,938],{},[496,2168,2169],{},"Is shapely faster for bulk parsing?","\nFor millions of WKT strings, often yes; you can convert between shapely and QGIS geometries through WKB, as shown in ",[26,2172,2174],{"href":2173},"\u002Fspatial-data-processing-automation\u002Fpyqgis-and-the-python-data-stack\u002Fconvert-between-qgsgeometry-and-shapely\u002F","converting between QgsGeometry and shapely",[216,2176,2178],{"id":2177},"related","Related",[221,2180,2181,2186,2191,2197,2202],{},[224,2182,2183,2185],{},[26,2184,29],{"href":28}," — the guide this recipe belongs to",[224,2187,2188],{},[26,2189,2190],{"href":927},"Create a Memory Layer in PyQGIS",[224,2192,2193],{},[26,2194,2196],{"href":2195},"\u002Fpyqgis-fundamentals-environment-setup\u002Ffeatures-geometries-and-memory-layers\u002Fconvert-geometry-type-pyqgis\u002F","Convert Geometry Types in PyQGIS",[224,2198,2199],{},[26,2200,2201],{"href":1566},"Fix Invalid Geometries in PyQGIS",[224,2203,2204],{},[26,2205,2206],{"href":1908},"Load a CSV as a Point Layer in PyQGIS",[2208,2209,2210],"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 .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}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);}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",{"title":247,"searchDepth":270,"depth":270,"links":2212},[2213,2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224],{"id":218,"depth":270,"text":219},{"id":232,"depth":270,"text":233},{"id":530,"depth":270,"text":531},{"id":941,"depth":270,"text":942},{"id":1238,"depth":270,"text":1239},{"id":1571,"depth":270,"text":1572},{"id":1913,"depth":270,"text":1914},{"id":2017,"depth":270,"text":2018},{"id":2052,"depth":270,"text":2053},{"id":2104,"depth":270,"text":2105},{"id":2125,"depth":270,"text":2126},{"id":2177,"depth":270,"text":2178},"Turn WKT, WKB, GeoJSON and coordinate lists into QgsGeometry objects — parsing safely, checking for empty and invalid results, handling Z and M values, and writing geometries back out in each format.","md",{"slug":2228,"type":2229,"breadcrumb":2230,"datePublished":2231,"dateModified":2231},"create-geometry-from-wkt-and-geojson-pyqgis","article","Create Geometry from WKT and GeoJSON","2026-10-02","\u002Fpyqgis-fundamentals-environment-setup\u002Ffeatures-geometries-and-memory-layers\u002Fcreate-geometry-from-wkt-and-geojson-pyqgis",{"title":5,"description":2225},"pyqgis-fundamentals-environment-setup\u002Ffeatures-geometries-and-memory-layers\u002Fcreate-geometry-from-wkt-and-geojson-pyqgis\u002Findex","32KXvdh_lDU85V5EUFHRX9B69hDeqQ_IKkk-6m7p1kI",1790966252924]