tag:blogger.com,1999:blog-51091849804228427032024-03-14T09:30:46.397-04:00El blog de José GuerreroEspecialmente sobre Python y PyQGISJosé Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.comBlogger197125tag:blogger.com,1999:blog-5109184980422842703.post-57311146000259974382021-08-30T09:07:00.000-04:002021-08-30T09:07:33.848-04:00Cómo determinar el área de un triángulo 3D en Python<div style="text-align:justify;">
<p>Las estimaciones de áreas 3D pasan por generar puntos triangulados 3D utilizando como base un modelo digital de elevación. Una vez generados los puntos 3D, se puede usar álgebra lineal para determinar de manera rápida el área del triángulo 3D muestrando la componente z de los puntos a partir del ráster. El área 2D sería entonces la proyección del tríangulo 3D en el plano xy.</p><a name='more'></a><p>Antes de la estimación completa de una superficie 3D, se va a crear una función para determinar el área individual de uno sólo de estos triángulos. Las fórmulas y los puntos 3D usados para calibrar la función creada fueron tomados de <a href="https://www.youtube.com/watch?v=MnpaeFPyn1A" target="_blank">este vídeo</a> de youtube. El código completo se encuentra a continuación.</p>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><table><tr><td><pre style="margin: 0; line-height: 125%"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23</pre></td><td><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">import</span> <span style="color: #0e84b5; font-weight: bold">numpy</span> <span style="color: #008800; font-weight: bold">as</span> <span style="color: #0e84b5; font-weight: bold">np</span>
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">triangle3D_area</span>(p1, p2, p3):
<span style="color: #888888"># x1 y1 z1</span>
p1p2 <span style="color: #333333">=</span> [p2[<span style="color: #0000DD; font-weight: bold">0</span>]<span style="color: #333333">-</span>p1[<span style="color: #0000DD; font-weight: bold">0</span>], p2[<span style="color: #0000DD; font-weight: bold">1</span>]<span style="color: #333333">-</span>p1[<span style="color: #0000DD; font-weight: bold">1</span>], p2[<span style="color: #0000DD; font-weight: bold">2</span>]<span style="color: #333333">-</span>p1[<span style="color: #0000DD; font-weight: bold">2</span>]]
<span style="color: #888888"># x2 y2 z2</span>
p1p3 <span style="color: #333333">=</span> [p3[<span style="color: #0000DD; font-weight: bold">0</span>]<span style="color: #333333">-</span>p1[<span style="color: #0000DD; font-weight: bold">0</span>], p3[<span style="color: #0000DD; font-weight: bold">1</span>]<span style="color: #333333">-</span>p1[<span style="color: #0000DD; font-weight: bold">1</span>], p3[<span style="color: #0000DD; font-weight: bold">2</span>]<span style="color: #333333">-</span>p1[<span style="color: #0000DD; font-weight: bold">2</span>]]
<span style="color: #008800; font-weight: bold">print</span>(p1p2)
<span style="color: #008800; font-weight: bold">print</span>(p1p3)
<span style="color: #888888">#y1*z2 - y2*z1, -(x1*z2 -x2*z1), x1*y2 -x2*y1</span>
u <span style="color: #333333">=</span> [p1p2[<span style="color: #0000DD; font-weight: bold">1</span>]<span style="color: #333333">*</span>p1p3[<span style="color: #0000DD; font-weight: bold">2</span>] <span style="color: #333333">-</span> p1p3[<span style="color: #0000DD; font-weight: bold">1</span>]<span style="color: #333333">*</span>p1p2[<span style="color: #0000DD; font-weight: bold">2</span>],
p1p3[<span style="color: #0000DD; font-weight: bold">0</span>]<span style="color: #333333">*</span>p1p2[<span style="color: #0000DD; font-weight: bold">2</span>] <span style="color: #333333">-</span> p1p2[<span style="color: #0000DD; font-weight: bold">0</span>]<span style="color: #333333">*</span>p1p3[<span style="color: #0000DD; font-weight: bold">2</span>] ,
p1p2[<span style="color: #0000DD; font-weight: bold">0</span>]<span style="color: #333333">*</span>p1p3[<span style="color: #0000DD; font-weight: bold">1</span>] <span style="color: #333333">-</span> p1p3[<span style="color: #0000DD; font-weight: bold">0</span>]<span style="color: #333333">*</span>p1p2[<span style="color: #0000DD; font-weight: bold">1</span>]]
<span style="color: #008800; font-weight: bold">return</span> np<span style="color: #333333">.</span>linalg<span style="color: #333333">.</span>norm(u)<span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">2</span>
p1 <span style="color: #333333">=</span> [<span style="color: #333333">-</span><span style="color: #0000DD; font-weight: bold">5</span>, <span style="color: #0000DD; font-weight: bold">5</span>, <span style="color: #333333">-</span><span style="color: #0000DD; font-weight: bold">5</span>]
p2 <span style="color: #333333">=</span> [<span style="color: #0000DD; font-weight: bold">1</span>, <span style="color: #333333">-</span><span style="color: #0000DD; font-weight: bold">6</span>, <span style="color: #0000DD; font-weight: bold">6</span>]
p3 <span style="color: #333333">=</span> [<span style="color: #0000DD; font-weight: bold">2</span>, <span style="color: #333333">-</span><span style="color: #0000DD; font-weight: bold">3</span>, <span style="color: #0000DD; font-weight: bold">4</span>]
<span style="color: #008800; font-weight: bold">print</span>(triangle3D_area(p1, p2, p3))
</pre></td></tr></table></div>
<p>Una vez ejecutado el código anterior en la Python Console de QGIS 3, los resultados intermedios y el valor del área 3D coinciden con los del vídeo; tal como se presenta a continuación.</p>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%">[<span style="color: #0000DD; font-weight: bold">6</span>, <span style="color: #333333">-</span><span style="color: #0000DD; font-weight: bold">11</span>, <span style="color: #0000DD; font-weight: bold">11</span>]
[<span style="color: #0000DD; font-weight: bold">7</span>, <span style="color: #333333">-</span><span style="color: #0000DD; font-weight: bold">8</span>, <span style="color: #0000DD; font-weight: bold">9</span>]
<span style="color: #6600EE; font-weight: bold">19.30673457630782</span>
</pre></div>
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-86981172283937921422021-01-06T08:57:00.001-04:002021-01-06T08:57:51.442-04:00Cómo desplegar un QProgressDialog object con PyQGIS 3<div style="text-align:justify;">
<p>Los objetos del tipo <b>QProgressDialog</b> permiten mostrar en tiempo real el desarrollo de un proceso y observar si éste se está desarrollando con normalidad o se presenta algún tipo de "retraso" que amerita ser corregido. El código a continuación despliega una serie de tres <b>QProgressDialog</b> cuya visualización se hace siempre "On Top" y donde el método 'setWindowModality' está activado con <b>Qt.WindowModal</b>. Si ésto último no se realiza el despliegue de la <b>QProgressDialog</b> parece ejecutarse como si estuviese "congelada".</p><a name='more'></a>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%">m <span style="color: #333333">=</span> <span style="background-color: #fff0f0">""</span>
bar <span style="color: #333333">=</span> QProgressDialog(m, <span style="background-color: #fff0f0">"Cancel"</span>, <span style="color: #0000DD; font-weight: bold">0</span>, <span style="color: #0000DD; font-weight: bold">100</span>)
<span style="color: #008800; font-weight: bold">import</span> <span style="color: #0e84b5; font-weight: bold">time</span>
bar<span style="color: #333333">.</span>setWindowModality(Qt<span style="color: #333333">.</span>WindowModal)
bar<span style="color: #333333">.</span>setWindowFlags(Qt<span style="color: #333333">.</span>WindowStaysOnTopHint)
m <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"Operation 1 in progress"</span>
bar<span style="color: #333333">.</span>setLabelText(m)
<span style="color: #008800; font-weight: bold">for</span> i <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(<span style="color: #0000DD; font-weight: bold">101</span>):
time<span style="color: #333333">.</span>sleep(<span style="color: #6600EE; font-weight: bold">0.05</span>)
bar<span style="color: #333333">.</span>setValue(i)
m <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"Operation 2 in progress"</span>
bar<span style="color: #333333">.</span>setLabelText(m)
<span style="color: #008800; font-weight: bold">for</span> i <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(<span style="color: #0000DD; font-weight: bold">101</span>):
time<span style="color: #333333">.</span>sleep(<span style="color: #6600EE; font-weight: bold">0.05</span>)
bar<span style="color: #333333">.</span>setValue(i)
m <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"Operation 3 in progress"</span>
bar<span style="color: #333333">.</span>setLabelText(m)
<span style="color: #008800; font-weight: bold">for</span> i <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(<span style="color: #0000DD; font-weight: bold">101</span>):
time<span style="color: #333333">.</span>sleep(<span style="color: #6600EE; font-weight: bold">0.05</span>)
bar<span style="color: #333333">.</span>setValue(i)
</pre></div>
<p>Si se ejecuta el código anterior con la línea del método 'setWindowModality' comentada, el comportamiento observado para todas las <b>QProgressDialog</b> es similar al de la imagen siguiente.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyHBkYXxX58FiavL_j6cHEXL3YQaY7p68yzNiSlJtxfUvcRmazh_LyMjNEb-kjO4Xhh48kWV29qyJr0uZ9BP9F5UG3hyvILjoxpyC4TzLSmdNFQxmx54It-Ew4HBMq9zxHY1azwTBmohQ/s299/modality1.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="228" data-original-width="299" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyHBkYXxX58FiavL_j6cHEXL3YQaY7p68yzNiSlJtxfUvcRmazh_LyMjNEb-kjO4Xhh48kWV29qyJr0uZ9BP9F5UG3hyvILjoxpyC4TzLSmdNFQxmx54It-Ew4HBMq9zxHY1azwTBmohQ/s600/modality1.png"/></a></div>
<p>Por otra parte, si descomentamos la línea referida con anterioridad el comportamiento, para la segunda de las <b>QProgressDialog</b>, es como se detalla en la imagen a continuación.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdLVHlumHUGEmjZF3cyLD73rPw-9ttK9IasRwYFJUMBqNq5gxEwShrD4dfikUVJgrke10F_VI9aSkeYqK5nWO17WyQbZOYrl6Bc16p5oGk3i949feBFVb6QtRyi_qSV7prKJQqCY_ZgOE/s318/modality2.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="212" data-original-width="318" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdLVHlumHUGEmjZF3cyLD73rPw-9ttK9IasRwYFJUMBqNq5gxEwShrD4dfikUVJgrke10F_VI9aSkeYqK5nWO17WyQbZOYrl6Bc16p5oGk3i949feBFVb6QtRyi_qSV7prKJQqCY_ZgOE/s600/modality2.png"/></a></div>
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-49497446781436260582020-12-31T09:17:00.000-04:002020-12-31T09:17:43.066-04:00Adaptar un plugin plantilla tipo botón checkeable para desplegar atributos y áreas de features (capas vectoriales) como tooltip en QGIS 3<div style="text-align:justify;">
<p>En un <a href="http://blogdezeka.blogspot.com/2018/12/adaptacion-de-un-plugin-de-qgis-2-qgis.html" target="_blank">post anterior</a> se adaptó un plugin, de QGIS 2 a QGIS 3, para desplegar <b>ráster values</b> como <b>tooltip</b>. En este post se va a adaptar ese comportamiento para desplegar los valores de todos los atributos y el área (en hectáreas) de capas vectoriales. El código completo se expone a continuación y se copió en el <b>template.py</b>; renombrado posteriormente como <b>measure_area.py</b> en la carpeta <b>measurearea</b>. Sin embargo, para que funcione adecuadamente se requieren otras modificaciones que se detallan más adelante.</p><a name='more'></a>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #DD4422">"""</span>
<span style="color: #DD4422">/***************************************************************************</span>
<span style="color: #DD4422"> Test</span>
<span style="color: #DD4422"> A QGIS plugin</span>
<span style="color: #DD4422"> Plugin for testing things</span>
<span style="color: #DD4422"> -------------------</span>
<span style="color: #DD4422"> begin : 2015-01-28</span>
<span style="color: #DD4422"> copyright : (C) 2015-2017 by German Carrillo, GeoTux</span>
<span style="color: #DD4422"> email : gcarrillo@linuxmail.org</span>
<span style="color: #DD4422"> ***************************************************************************/</span>
<span style="color: #DD4422">/***************************************************************************</span>
<span style="color: #DD4422"> * *</span>
<span style="color: #DD4422"> * This program is free software; you can redistribute it and/or modify *</span>
<span style="color: #DD4422"> * it under the terms of the GNU General Public License as published by *</span>
<span style="color: #DD4422"> * the Free Software Foundation; either version 2 of the License, or *</span>
<span style="color: #DD4422"> * (at your option) any later version. *</span>
<span style="color: #DD4422"> * *</span>
<span style="color: #DD4422"> ***************************************************************************/</span>
<span style="color: #DD4422">"""</span>
<span style="color: #008800; font-weight: bold">import</span> <span style="color: #0e84b5; font-weight: bold">os</span>
<span style="color: #888888"># Import the PyQt and QGIS libraries</span>
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">qgis.core</span> <span style="color: #008800; font-weight: bold">import</span> QgsApplication, QgsRasterLayer, QgsRaster, QgsVectorLayer, Qgis, QgsGeometry, QgsWkbTypes
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">qgis.gui</span> <span style="color: #008800; font-weight: bold">import</span> QgsMapToolEmitPoint
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtCore</span> <span style="color: #008800; font-weight: bold">import</span> QObject, QTimer
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtWidgets</span> <span style="color: #008800; font-weight: bold">import</span> ( QMessageBox, QAction, QMenu, QActionGroup,
QWidgetAction, QToolTip)
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtGui</span> <span style="color: #008800; font-weight: bold">import</span> ( QIcon )
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">Test</span>:
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">__init__</span>(<span style="color: #007020">self</span>, iface):
<span style="color: #888888"># Save reference to the QGIS interface</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface <span style="color: #333333">=</span> iface
<span style="color: #007020">self</span><span style="color: #333333">.</span>tooltipRaster <span style="color: #333333">=</span> TooltipAreaPolygonMapTool( <span style="color: #007020">self</span><span style="color: #333333">.</span>iface )
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">initGui</span>(<span style="color: #007020">self</span>):
<span style="color: #888888"># Create action that will start plugin configuration</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>action <span style="color: #333333">=</span> QAction( QIcon( os<span style="color: #333333">.</span>path<span style="color: #333333">.</span>dirname(os<span style="color: #333333">.</span>path<span style="color: #333333">.</span>realpath(__file__)) <span style="color: #333333">+</span>
<span style="background-color: #fff0f0">"/icon_default.png"</span> ), <span style="background-color: #fff0f0">"Measure Feature Areas"</span>, <span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mainWindow() )
<span style="color: #888888"># connect the action to the run method</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>action<span style="color: #333333">.</span>triggered<span style="color: #333333">.</span>connect( <span style="color: #007020">self</span><span style="color: #333333">.</span>run )
<span style="color: #007020">self</span><span style="color: #333333">.</span>action<span style="color: #333333">.</span>setCheckable( <span style="color: #007020">True</span> )
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mapCanvas()<span style="color: #333333">.</span>mapToolSet<span style="color: #333333">.</span>connect( <span style="color: #007020">self</span><span style="color: #333333">.</span>mapToolWasSet )
<span style="color: #888888"># Add toolbar button to the Plugins toolbar</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>addToolBarIcon(<span style="color: #007020">self</span><span style="color: #333333">.</span>action)
<span style="color: #888888"># Add menu item to the Plugins menu</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>addPluginToMenu(<span style="background-color: #fff0f0">"&Tooltip for Raster Values"</span>, <span style="color: #007020">self</span><span style="color: #333333">.</span>action)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">unload</span>(<span style="color: #007020">self</span>):
<span style="color: #888888"># Remove the plugin menu item and icon</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>removePluginMenu( <span style="background-color: #fff0f0">"&Tooltip for Raster Values"</span>, <span style="color: #007020">self</span><span style="color: #333333">.</span>action )
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>removeToolBarIcon(<span style="color: #007020">self</span><span style="color: #333333">.</span>action)
<span style="color: #888888"># run method that performs all the real work</span>
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">run</span>(<span style="color: #007020">self</span>, checked):
<span style="color: #008800; font-weight: bold">if</span> checked:
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mapCanvas()<span style="color: #333333">.</span>setMapTool( <span style="color: #007020">self</span><span style="color: #333333">.</span>tooltipRaster )
<span style="color: #008800; font-weight: bold">else</span>:
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mapCanvas()<span style="color: #333333">.</span>unsetMapTool( <span style="color: #007020">self</span><span style="color: #333333">.</span>tooltipRaster )
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">mapToolWasSet</span>( <span style="color: #007020">self</span>, newTool ):
<span style="color: #008800; font-weight: bold">if</span> <span style="color: #007020">type</span>(newTool) <span style="color: #333333">!=</span> TooltipAreaPolygonMapTool:
<span style="color: #007020">self</span><span style="color: #333333">.</span>action<span style="color: #333333">.</span>setChecked( <span style="color: #007020">False</span> )
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">TooltipAreaPolygonMapTool</span>(QgsMapToolEmitPoint):
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">__init__</span>(<span style="color: #007020">self</span>, iface):
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface <span style="color: #333333">=</span> iface
<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mapCanvas()
QgsMapToolEmitPoint<span style="color: #333333">.</span>__init__(<span style="color: #007020">self</span>, <span style="color: #007020">self</span><span style="color: #333333">.</span>canvas)
<span style="color: #007020">self</span><span style="color: #333333">.</span>timerMapTips <span style="color: #333333">=</span> QTimer( <span style="color: #007020">self</span><span style="color: #333333">.</span>canvas )
<span style="color: #007020">self</span><span style="color: #333333">.</span>timerMapTips<span style="color: #333333">.</span>timeout<span style="color: #333333">.</span>connect(<span style="color: #007020">self</span><span style="color: #333333">.</span>showMapTip)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasPressEvent</span>(<span style="color: #007020">self</span>, e):
point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>toMapCoordinates(<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas<span style="color: #333333">.</span>mouseLastXY())
<span style="color: #008800; font-weight: bold">if</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>canvas<span style="color: #333333">.</span>underMouse():
rLayer <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>activeLayer()
<span style="color: #008800; font-weight: bold">if</span> <span style="color: #007020">type</span>(rLayer) <span style="color: #000000; font-weight: bold">is</span> QgsVectorLayer:
feats_ids <span style="color: #333333">=</span> rLayer<span style="color: #333333">.</span>fields()<span style="color: #333333">.</span>allAttributesList()
names <span style="color: #333333">=</span> [ rLayer<span style="color: #333333">.</span>fields()<span style="color: #333333">.</span>field(<span style="color: #007020">id</span>)<span style="color: #333333">.</span>name() <span style="color: #008800; font-weight: bold">for</span> <span style="color: #007020">id</span> <span style="color: #000000; font-weight: bold">in</span> feats_ids ]
feats <span style="color: #333333">=</span> [ feat <span style="color: #008800; font-weight: bold">for</span> feat <span style="color: #000000; font-weight: bold">in</span> rLayer<span style="color: #333333">.</span>getFeatures() ]
point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>toMapCoordinates(<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas<span style="color: #333333">.</span>mouseLastXY())
text <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"no layer features"</span>
<span style="color: #008800; font-weight: bold">if</span> rLayer<span style="color: #333333">.</span>geometryType() <span style="color: #333333">==</span> QgsWkbTypes<span style="color: #333333">.</span>PolygonGeometry:
<span style="color: #008800; font-weight: bold">for</span> feat <span style="color: #000000; font-weight: bold">in</span> feats:
<span style="color: #008800; font-weight: bold">if</span> QgsGeometry<span style="color: #333333">.</span>fromPointXY(point)<span style="color: #333333">.</span>within(feat<span style="color: #333333">.</span>geometry()):
text <span style="color: #333333">=</span> <span style="background-color: #fff0f0">", "</span><span style="color: #333333">.</span>join([<span style="background-color: #fff0f0">'{}: {}'</span><span style="color: #333333">.</span>format(names[i], r) <span style="color: #008800; font-weight: bold">for</span> i, r <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">enumerate</span>(feat<span style="color: #333333">.</span>attributes()) <span style="color: #008800; font-weight: bold">if</span> r <span style="color: #000000; font-weight: bold">is</span> <span style="color: #000000; font-weight: bold">not</span> <span style="color: #007020">None</span>] )
<span style="color: #008800; font-weight: bold">break</span>
<span style="color: #008800; font-weight: bold">else</span>:
<span style="color: #008800; font-weight: bold">pass</span>
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasReleaseEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #008800; font-weight: bold">pass</span>
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasMoveEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #008800; font-weight: bold">if</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>canvas<span style="color: #333333">.</span>underMouse(): <span style="color: #888888"># Only if mouse is over the map</span>
QToolTip<span style="color: #333333">.</span>hideText()
<span style="color: #007020">self</span><span style="color: #333333">.</span>timerMapTips<span style="color: #333333">.</span>start( <span style="color: #0000DD; font-weight: bold">700</span> ) <span style="color: #888888"># time in milliseconds</span>
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">deactivate</span>(<span style="color: #007020">self</span>):
<span style="color: #007020">self</span><span style="color: #333333">.</span>timerMapTips<span style="color: #333333">.</span>stop()
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">showMapTip</span>( <span style="color: #007020">self</span> ):
<span style="color: #007020">self</span><span style="color: #333333">.</span>timerMapTips<span style="color: #333333">.</span>stop()
<span style="color: #008800; font-weight: bold">if</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>canvas<span style="color: #333333">.</span>underMouse():
rLayer <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>activeLayer()
<span style="color: #008800; font-weight: bold">if</span> <span style="color: #007020">type</span>(rLayer) <span style="color: #000000; font-weight: bold">is</span> QgsVectorLayer:
feats_ids <span style="color: #333333">=</span> rLayer<span style="color: #333333">.</span>fields()<span style="color: #333333">.</span>allAttributesList()
names <span style="color: #333333">=</span> [ rLayer<span style="color: #333333">.</span>fields()<span style="color: #333333">.</span>field(<span style="color: #007020">id</span>)<span style="color: #333333">.</span>name() <span style="color: #008800; font-weight: bold">for</span> <span style="color: #007020">id</span> <span style="color: #000000; font-weight: bold">in</span> feats_ids ]
feats <span style="color: #333333">=</span> [ feat <span style="color: #008800; font-weight: bold">for</span> feat <span style="color: #000000; font-weight: bold">in</span> rLayer<span style="color: #333333">.</span>getFeatures() ]
point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>toMapCoordinates(<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas<span style="color: #333333">.</span>mouseLastXY())
text <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"no layer features"</span>
<span style="color: #008800; font-weight: bold">if</span> rLayer<span style="color: #333333">.</span>geometryType() <span style="color: #333333">==</span> QgsWkbTypes<span style="color: #333333">.</span>PolygonGeometry:
<span style="color: #008800; font-weight: bold">for</span> feat <span style="color: #000000; font-weight: bold">in</span> feats:
<span style="color: #008800; font-weight: bold">if</span> QgsGeometry<span style="color: #333333">.</span>fromPointXY(point)<span style="color: #333333">.</span>within(feat<span style="color: #333333">.</span>geometry()):
text <span style="color: #333333">=</span> <span style="background-color: #fff0f0">", "</span><span style="color: #333333">.</span>join([<span style="background-color: #fff0f0">'{}: {}'</span><span style="color: #333333">.</span>format(names[i], r) <span style="color: #008800; font-weight: bold">for</span> i, r <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">enumerate</span>(feat<span style="color: #333333">.</span>attributes()) <span style="color: #008800; font-weight: bold">if</span> r <span style="color: #000000; font-weight: bold">is</span> <span style="color: #000000; font-weight: bold">not</span> <span style="color: #007020">None</span>] )<span style="color: #333333">+</span> <span style="background-color: #fff0f0">'</span><span style="color: #666666; font-weight: bold; background-color: #fff0f0">\n</span><span style="background-color: #fff0f0">area: '</span> <span style="color: #333333">+</span> <span style="color: #007020">str</span>(feat<span style="color: #333333">.</span>geometry()<span style="color: #333333">.</span>area()<span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">10000</span>) <span style="color: #333333">+</span> <span style="background-color: #fff0f0">' ha'</span>
<span style="color: #008800; font-weight: bold">break</span>
<span style="color: #008800; font-weight: bold">try</span>:
QToolTip<span style="color: #333333">.</span>showText( <span style="color: #007020">self</span><span style="color: #333333">.</span>canvas<span style="color: #333333">.</span>mapToGlobal( <span style="color: #007020">self</span><span style="color: #333333">.</span>canvas<span style="color: #333333">.</span>mouseLastXY() ), text, <span style="color: #007020">self</span><span style="color: #333333">.</span>canvas )
<span style="color: #008800; font-weight: bold">except</span> <span style="color: #FF0000; font-weight: bold">UnboundLocalError</span>:
<span style="color: #008800; font-weight: bold">pass</span>
</pre></div>
<p>La carpeta <b>measurearea</b> se encuentra en la ruta de plugins de QGIS 3. El archivo <b>measure_area.py</b>, que tiene el código anterior, para que se procese de la manera esperada es necesaria la modificación siguiente en el <b>__init__py</b>. </p>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #333333">.</span>
<span style="color: #333333">.</span>
<span style="color: #333333">.</span>
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">classFactory</span>(iface):
<span style="color: #888888"># load Test class from file test.py</span>
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">.measure_area</span> <span style="color: #008800; font-weight: bold">import</span> Test
<span style="color: #008800; font-weight: bold">return</span> Test(iface)
</pre></div>
<p>También necesitamos la modificación siguiente en el <b>metadata.txt</b> para que el nombre del plugin sea procesado como se espera. Una modificación similar también fue realizada en el código fuente (<b>measure_area.py</b>) al inicio del método 'initGui'.</p>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%">; the <span style="color: #007020">next</span> section <span style="color: #000000; font-weight: bold">is</span> mandatory
[general]
name<span style="color: #333333">=</span>Measure Areas plugin
description<span style="color: #333333">=</span>For Measure Features Areas
<span style="color: #333333">.</span>
<span style="color: #333333">.</span>
<span style="color: #333333">.</span>
</pre></div>
<p>Finalmente, se produce un icono personalizado 24x24 (con el mismo nombre) para identificarlo de manera precisa. La ejecución del plugin se observa en la imagen a continuación.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBe_1Sv8SCmQfRppBRBR46E5VYrMygBmlCU-XDmdUY3EUOFvBDbNcDjSSNB1aoiNsuIR4DjmLR5NGGW2RE87loPBVa7bnPPVsPTkrzQz5MuA-41X3eq0q20l31NWP9BEkyVhwakJ3sL5M/s1920/tooltip1.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1172" data-original-width="1920" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBe_1Sv8SCmQfRppBRBR46E5VYrMygBmlCU-XDmdUY3EUOFvBDbNcDjSSNB1aoiNsuIR4DjmLR5NGGW2RE87loPBVa7bnPPVsPTkrzQz5MuA-41X3eq0q20l31NWP9BEkyVhwakJ3sL5M/s600/tooltip1.png"/></a></div>
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-59137013233329515042020-12-29T08:37:00.000-04:002020-12-29T08:37:32.702-04:00Adaptar un plugin plantilla tipo botón checkeable para producir círculos por dragado del Map Canvas en QGIS 3<div style="text-align:justify;">
<p>En el <a href="http://blogdezeka.blogspot.com/2020/12/adaptar-un-plugin-plantilla-tipo-boton.html" target="_blank">post anterior</a> se adaptó un <a href="http://blogdezeka.blogspot.com/2020/12/como-producir-un-plugin-plantilla-tipo.html" target="_blank">plugin plantilla</a>, tipo botón checkeable, para producir rectángulos por dragado del Map Canvas en QGIS 3. Ahora, se va a adaptar la misma plantilla pero para producir círculos por dragado del Map Canvas. El código completo colocado en el archivo <b>template.py</b> se muestra a continuación. Sin embargo, para que funcione adecuadamente se requieren otras modificaciones que se detallan más adelante.</p><a name='more'></a>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #DD4422">"""</span>
<span style="color: #DD4422">/***************************************************************************</span>
<span style="color: #DD4422"> Test</span>
<span style="color: #DD4422"> A QGIS plugin</span>
<span style="color: #DD4422"> Plugin for testing things</span>
<span style="color: #DD4422"> -------------------</span>
<span style="color: #DD4422"> begin : 2015-01-28</span>
<span style="color: #DD4422"> copyright : (C) 2015-2017 by German Carrillo, GeoTux</span>
<span style="color: #DD4422"> email : gcarrillo@linuxmail.org</span>
<span style="color: #DD4422"> ***************************************************************************/</span>
<span style="color: #DD4422">/***************************************************************************</span>
<span style="color: #DD4422"> * *</span>
<span style="color: #DD4422"> * This program is free software; you can redistribute it and/or modify *</span>
<span style="color: #DD4422"> * it under the terms of the GNU General Public License as published by *</span>
<span style="color: #DD4422"> * the Free Software Foundation; either version 2 of the License, or *</span>
<span style="color: #DD4422"> * (at your option) any later version. *</span>
<span style="color: #DD4422"> * *</span>
<span style="color: #DD4422"> ***************************************************************************/</span>
<span style="color: #DD4422">"""</span>
<span style="color: #008800; font-weight: bold">import</span> <span style="color: #0e84b5; font-weight: bold">os</span><span style="color: #333333">,</span> <span style="color: #0e84b5; font-weight: bold">math</span>
<span style="color: #888888"># Import the PyQt and QGIS libraries</span>
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">qgis.core</span> <span style="color: #008800; font-weight: bold">import</span> (QgsApplication, QgsRasterLayer, QgsRaster, QgsPointXY, QgsPoint, QgsCircle,
QgsGeometry, QgsRectangle, QgsProject, QgsVectorLayer, QgsFeature)
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">qgis.gui</span> <span style="color: #008800; font-weight: bold">import</span> QgsMapToolEmitPoint, QgsRubberBand
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtCore</span> <span style="color: #008800; font-weight: bold">import</span> QObject, QTimer, Qt
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtWidgets</span> <span style="color: #008800; font-weight: bold">import</span> ( QMessageBox, QAction, QMenu, QActionGroup,
QWidgetAction, QToolTip)
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtGui</span> <span style="color: #008800; font-weight: bold">import</span> ( QIcon )
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">Test</span>:
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">__init__</span>(<span style="color: #007020">self</span>, iface):
<span style="color: #888888"># Save reference to the QGIS interface</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface <span style="color: #333333">=</span> iface
<span style="color: #007020">self</span><span style="color: #333333">.</span>tooltipRaster <span style="color: #333333">=</span> TooltipRasterMapTool( <span style="color: #007020">self</span><span style="color: #333333">.</span>iface )
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">initGui</span>(<span style="color: #007020">self</span>):
<span style="color: #888888"># Create action that will start plugin configuration</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>action <span style="color: #333333">=</span> QAction( QIcon( os<span style="color: #333333">.</span>path<span style="color: #333333">.</span>dirname(os<span style="color: #333333">.</span>path<span style="color: #333333">.</span>realpath(__file__)) <span style="color: #333333">+</span>
<span style="background-color: #fff0f0">"/icon_default.png"</span> ), <span style="background-color: #fff0f0">"Making Circles"</span>, <span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mainWindow() )
<span style="color: #888888"># connect the action to the run method</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>action<span style="color: #333333">.</span>triggered<span style="color: #333333">.</span>connect( <span style="color: #007020">self</span><span style="color: #333333">.</span>run )
<span style="color: #007020">self</span><span style="color: #333333">.</span>action<span style="color: #333333">.</span>setCheckable( <span style="color: #007020">True</span> )
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mapCanvas()<span style="color: #333333">.</span>mapToolSet<span style="color: #333333">.</span>connect( <span style="color: #007020">self</span><span style="color: #333333">.</span>mapToolWasSet )
<span style="color: #888888"># Add toolbar button to the Plugins toolbar</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>addToolBarIcon(<span style="color: #007020">self</span><span style="color: #333333">.</span>action)
<span style="color: #888888"># Add menu item to the Plugins menu</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>addPluginToMenu(<span style="background-color: #fff0f0">"&Tooltip for Raster Values"</span>, <span style="color: #007020">self</span><span style="color: #333333">.</span>action)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">unload</span>(<span style="color: #007020">self</span>):
<span style="color: #888888"># Remove the plugin menu item and icon</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>removePluginMenu( <span style="background-color: #fff0f0">"&Tooltip for Raster Values"</span>, <span style="color: #007020">self</span><span style="color: #333333">.</span>action )
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>removeToolBarIcon(<span style="color: #007020">self</span><span style="color: #333333">.</span>action)
<span style="color: #888888"># run method that performs all the real work</span>
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">run</span>(<span style="color: #007020">self</span>, checked):
<span style="color: #008800; font-weight: bold">if</span> checked:
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mapCanvas()<span style="color: #333333">.</span>setMapTool( <span style="color: #007020">self</span><span style="color: #333333">.</span>tooltipRaster )
<span style="color: #008800; font-weight: bold">else</span>:
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mapCanvas()<span style="color: #333333">.</span>unsetMapTool( <span style="color: #007020">self</span><span style="color: #333333">.</span>tooltipRaster )
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">mapToolWasSet</span>( <span style="color: #007020">self</span>, newTool ):
<span style="color: #008800; font-weight: bold">if</span> <span style="color: #007020">type</span>(newTool) <span style="color: #333333">!=</span> TooltipRasterMapTool:
<span style="color: #007020">self</span><span style="color: #333333">.</span>action<span style="color: #333333">.</span>setChecked( <span style="color: #007020">False</span> )
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">TooltipRasterMapTool</span>(QgsMapToolEmitPoint):
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">__init__</span>(<span style="color: #007020">self</span>, iface):
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface <span style="color: #333333">=</span> iface
<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mapCanvas()
QgsMapToolEmitPoint<span style="color: #333333">.</span>__init__(<span style="color: #007020">self</span>, <span style="color: #007020">self</span><span style="color: #333333">.</span>canvas)
<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band <span style="color: #333333">=</span> QgsRubberBand(<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas, <span style="color: #007020">True</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>setColor(Qt<span style="color: #333333">.</span>red)
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>setOpacity(<span style="color: #6600EE; font-weight: bold">0.7</span>)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasPressEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>toMapCoordinates(e<span style="color: #333333">.</span>pos())
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>start_point
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasMoveEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #008800; font-weight: bold">if</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>start_point:
end_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>toMapCoordinates(e<span style="color: #333333">.</span>pos())
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>reset()
q <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>get_circ_par(<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point, end_point)
h <span style="color: #333333">=</span> QgsCircle(q[<span style="color: #0000DD; font-weight: bold">0</span>], q[<span style="color: #0000DD; font-weight: bold">1</span>])<span style="color: #333333">.</span>toPolygon()<span style="color: #333333">.</span>asWkt()
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>setToGeometry(QgsGeometry<span style="color: #333333">.</span>fromWkt(h), <span style="color: #007020">None</span>)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasReleaseEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>toMapCoordinates(e<span style="color: #333333">.</span>pos())
r <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>get_circle()
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>reset()
<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
circ_feat <span style="color: #333333">=</span> r
<span style="color: #888888">#definng Status Bar</span>
statusBar <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mainWindow()<span style="color: #333333">.</span>statusBar()
<span style="color: #888888">#selecting elements in Status Bar</span>
elements <span style="color: #333333">=</span> statusBar<span style="color: #333333">.</span>children()
<span style="color: #888888">#selecting widget in Status Bar with ESPG</span>
EPSG <span style="color: #333333">=</span> elements[<span style="color: #0000DD; font-weight: bold">1</span>]<span style="color: #333333">.</span>children()[<span style="color: #0000DD; font-weight: bold">10</span>]
EPSG <span style="color: #333333">=</span> EPSG<span style="color: #333333">.</span>text()<span style="color: #333333">.</span>split(<span style="background-color: #fff0f0">':'</span>)
uri <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"Polygon?crs=epsg:"</span> <span style="color: #333333">+</span> EPSG[<span style="color: #0000DD; font-weight: bold">1</span>] <span style="color: #333333">+</span> <span style="background-color: #fff0f0">"&field=id:integer""&index=yes"</span>
mem_layer <span style="color: #333333">=</span> QgsVectorLayer(uri,
<span style="background-color: #fff0f0">'circle'</span>,
<span style="background-color: #fff0f0">'memory'</span>)
prov <span style="color: #333333">=</span> mem_layer<span style="color: #333333">.</span>dataProvider()
feat <span style="color: #333333">=</span> QgsFeature()
feat<span style="color: #333333">.</span>setAttributes([<span style="color: #0000DD; font-weight: bold">0</span>])
feat<span style="color: #333333">.</span>setGeometry(QgsGeometry<span style="color: #333333">.</span>fromWkt(circ_feat))
prov<span style="color: #333333">.</span>addFeatures([feat])
QgsProject<span style="color: #333333">.</span>instance()<span style="color: #333333">.</span>addMapLayer(mem_layer)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">get_circ_par</span>(<span style="color: #007020">self</span>, startPoint, endPoint):
par <span style="color: #333333">=</span> [QgsPoint(startPoint<span style="color: #333333">.</span>x(), startPoint<span style="color: #333333">.</span>y()),
math<span style="color: #333333">.</span>sqrt((startPoint<span style="color: #333333">.</span>x() <span style="color: #333333">-</span> endPoint<span style="color: #333333">.</span>x())<span style="color: #333333">**</span><span style="color: #0000DD; font-weight: bold">2</span> <span style="color: #333333">+</span> (startPoint<span style="color: #333333">.</span>y() <span style="color: #333333">-</span> endPoint<span style="color: #333333">.</span>y())<span style="color: #333333">**</span><span style="color: #0000DD; font-weight: bold">2</span>)]
<span style="color: #008800; font-weight: bold">return</span> par
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">get_circle</span>(<span style="color: #007020">self</span>):
dist <span style="color: #333333">=</span> math<span style="color: #333333">.</span>sqrt((<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point<span style="color: #333333">.</span>x() <span style="color: #333333">-</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>end_point<span style="color: #333333">.</span>x())<span style="color: #333333">**</span><span style="color: #0000DD; font-weight: bold">2</span> <span style="color: #333333">+</span> (<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point<span style="color: #333333">.</span>y() <span style="color: #333333">-</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>end_point<span style="color: #333333">.</span>y())<span style="color: #333333">**</span><span style="color: #0000DD; font-weight: bold">2</span>)
circ <span style="color: #333333">=</span> QgsCircle(QgsPoint(<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point), dist)<span style="color: #333333">.</span>toPolygon()<span style="color: #333333">.</span>asWkt()
<span style="color: #008800; font-weight: bold">return</span> circ
</pre></div>
<p>La carpeta completa de la plantilla (template) se guarda con el nombre de <b>makingcircles</b> en la ruta de plugins de QGIS 3. El archivo <b>template.py</b> que tiene el código anterior se renombra como <b>making_circles.py</b>. Para que lo procese de la manera esperada se hace la modificación siguiente en el <b>__init__py</b>. </p>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #333333">.</span>
<span style="color: #333333">.</span>
<span style="color: #333333">.</span>
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">classFactory</span>(iface):
<span style="color: #888888"># load Test class from file making_circles.py</span>
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">.making_circles</span> <span style="color: #008800; font-weight: bold">import</span> Test
<span style="color: #008800; font-weight: bold">return</span> Test(iface)
</pre></div>
<p>También necesitamos la modificación siguiente en el <b>metadata.txt</b> para que el nombre del plugin sea procesado como se espera. Una modificación similar también fue realizada en el código fuente (<b>making_circles.py</b>) al inicio del método 'initGui'.</p>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%">; the <span style="color: #007020">next</span> section <span style="color: #000000; font-weight: bold">is</span> mandatory
[general]
name<span style="color: #333333">=</span>Making Circles plugin
description<span style="color: #333333">=</span>For Making Circles
<span style="color: #333333">.</span>
<span style="color: #333333">.</span>
<span style="color: #333333">.</span>
</pre></div>
<p>Finalmente, se produce un icono personalizado 24x24 (con el mismo nombre) para identificarlo de manera precisa. La ejecución del plugin se observa en la imagen a continuación.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijNUmu5J15MaiuxXvjsC8SqRUiKnxxGWtsd7tJ4KADaEYcbwH9EqyzFGtC5RgUMTG7xOzDSDov7W1g_aWbzn7vnzujjxAB9UI76XhSh0TG-79t9_NEhRI2nOGvqkD2HvHhWgTpgrpg7k4/s1920/plugin1.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1150" data-original-width="1920" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijNUmu5J15MaiuxXvjsC8SqRUiKnxxGWtsd7tJ4KADaEYcbwH9EqyzFGtC5RgUMTG7xOzDSDov7W1g_aWbzn7vnzujjxAB9UI76XhSh0TG-79t9_NEhRI2nOGvqkD2HvHhWgTpgrpg7k4/s600/plugin1.png"/></a></div>
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-29953262675253250072020-12-28T09:58:00.000-04:002020-12-28T09:58:21.443-04:00Adaptar un plugin plantilla tipo botón checkeable para producir rectángulos por dragado del Map Canvas en QGIS 3<div style="text-align:justify;">
<p>En el <a href="https://blogdezeka.blogspot.com/2020/12/como-producir-un-plugin-plantilla-tipo.html" target="_blank">post anterior</a> se produjo un plugin plantilla tipo botón checkeable para PyQGIS 3. Ahora lo vamos a adaptar para producir rectángulos por dragado del Map Canvas; tal como se realizó en este <a href="http://blogdezeka.blogspot.com/2020/12/producir-rectangulos-por-dragado-del.html" target="_blank">otro post</a>. A continuación, para tener una plantilla verdadera, se elimina en <b>template.py</b> todo el código que permitía generar las tooltips consideradas en el post anterior y se reserva para tal fin. El código final se presenta a continuación.</p><a name='more'></a>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #DD4422">"""</span>
<span style="color: #DD4422">/***************************************************************************</span>
<span style="color: #DD4422"> Test</span>
<span style="color: #DD4422"> A QGIS plugin</span>
<span style="color: #DD4422"> Plugin for testing things</span>
<span style="color: #DD4422"> -------------------</span>
<span style="color: #DD4422"> begin : 2015-01-28</span>
<span style="color: #DD4422"> copyright : (C) 2015-2017 by German Carrillo, GeoTux</span>
<span style="color: #DD4422"> email : gcarrillo@linuxmail.org</span>
<span style="color: #DD4422"> ***************************************************************************/</span>
<span style="color: #DD4422">/***************************************************************************</span>
<span style="color: #DD4422"> * *</span>
<span style="color: #DD4422"> * This program is free software; you can redistribute it and/or modify *</span>
<span style="color: #DD4422"> * it under the terms of the GNU General Public License as published by *</span>
<span style="color: #DD4422"> * the Free Software Foundation; either version 2 of the License, or *</span>
<span style="color: #DD4422"> * (at your option) any later version. *</span>
<span style="color: #DD4422"> * *</span>
<span style="color: #DD4422"> ***************************************************************************/</span>
<span style="color: #DD4422">"""</span>
<span style="color: #008800; font-weight: bold">import</span> <span style="color: #0e84b5; font-weight: bold">os</span>
<span style="color: #888888"># Import the PyQt and QGIS libraries</span>
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">qgis.core</span> <span style="color: #008800; font-weight: bold">import</span> QgsApplication, QgsRasterLayer, QgsRaster
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">qgis.gui</span> <span style="color: #008800; font-weight: bold">import</span> QgsMapToolEmitPoint
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtCore</span> <span style="color: #008800; font-weight: bold">import</span> QObject, QTimer, Qt
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtWidgets</span> <span style="color: #008800; font-weight: bold">import</span> ( QMessageBox, QAction, QMenu, QActionGroup,
QWidgetAction, QToolTip)
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtGui</span> <span style="color: #008800; font-weight: bold">import</span> ( QIcon )
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">Test</span>:
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">__init__</span>(<span style="color: #007020">self</span>, iface):
<span style="color: #888888"># Save reference to the QGIS interface</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface <span style="color: #333333">=</span> iface
<span style="color: #007020">self</span><span style="color: #333333">.</span>tooltipRaster <span style="color: #333333">=</span> TooltipRasterMapTool( <span style="color: #007020">self</span><span style="color: #333333">.</span>iface )
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">initGui</span>(<span style="color: #007020">self</span>):
<span style="color: #888888"># Create action that will start plugin configuration</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>action <span style="color: #333333">=</span> QAction( QIcon( os<span style="color: #333333">.</span>path<span style="color: #333333">.</span>dirname(os<span style="color: #333333">.</span>path<span style="color: #333333">.</span>realpath(__file__)) <span style="color: #333333">+</span>
<span style="background-color: #fff0f0">"/icon_default.png"</span> ), <span style="background-color: #fff0f0">"Tooltip for Raster Values"</span>, <span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mainWindow() )
<span style="color: #888888"># connect the action to the run method</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>action<span style="color: #333333">.</span>triggered<span style="color: #333333">.</span>connect( <span style="color: #007020">self</span><span style="color: #333333">.</span>run )
<span style="color: #007020">self</span><span style="color: #333333">.</span>action<span style="color: #333333">.</span>setCheckable( <span style="color: #007020">True</span> )
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mapCanvas()<span style="color: #333333">.</span>mapToolSet<span style="color: #333333">.</span>connect( <span style="color: #007020">self</span><span style="color: #333333">.</span>mapToolWasSet )
<span style="color: #888888"># Add toolbar button to the Plugins toolbar</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>addToolBarIcon(<span style="color: #007020">self</span><span style="color: #333333">.</span>action)
<span style="color: #888888"># Add menu item to the Plugins menu</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>addPluginToMenu(<span style="background-color: #fff0f0">"&Tooltip for Raster Values"</span>, <span style="color: #007020">self</span><span style="color: #333333">.</span>action)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">unload</span>(<span style="color: #007020">self</span>):
<span style="color: #888888"># Remove the plugin menu item and icon</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>removePluginMenu( <span style="background-color: #fff0f0">"&Tooltip for Raster Values"</span>, <span style="color: #007020">self</span><span style="color: #333333">.</span>action )
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>removeToolBarIcon(<span style="color: #007020">self</span><span style="color: #333333">.</span>action)
<span style="color: #888888"># run method that performs all the real work</span>
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">run</span>(<span style="color: #007020">self</span>, checked):
<span style="color: #008800; font-weight: bold">if</span> checked:
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mapCanvas()<span style="color: #333333">.</span>setMapTool( <span style="color: #007020">self</span><span style="color: #333333">.</span>tooltipRaster )
<span style="color: #008800; font-weight: bold">else</span>:
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mapCanvas()<span style="color: #333333">.</span>unsetMapTool( <span style="color: #007020">self</span><span style="color: #333333">.</span>tooltipRaster )
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">mapToolWasSet</span>( <span style="color: #007020">self</span>, newTool ):
<span style="color: #008800; font-weight: bold">if</span> <span style="color: #007020">type</span>(newTool) <span style="color: #333333">!=</span> TooltipRasterMapTool:
<span style="color: #007020">self</span><span style="color: #333333">.</span>action<span style="color: #333333">.</span>setChecked( <span style="color: #007020">False</span> )
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">TooltipRasterMapTool</span>(QgsMapToolEmitPoint):
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">__init__</span>(<span style="color: #007020">self</span>, iface):
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface <span style="color: #333333">=</span> iface
<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mapCanvas()
QgsMapToolEmitPoint<span style="color: #333333">.</span>__init__(<span style="color: #007020">self</span>, <span style="color: #007020">self</span><span style="color: #333333">.</span>canvas)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasPressEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #008800; font-weight: bold">pass</span>
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasReleaseEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #008800; font-weight: bold">pass</span>
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasMoveEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #008800; font-weight: bold">pass</span>
</pre></div>
<p>El código total adaptado en <b>template.py</b> se presenta a continuación. Sin embargo, para que funcione adecuadamente se requieren otras modificaciones que se detallan más adelante.</p>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #DD4422">"""</span>
<span style="color: #DD4422">/***************************************************************************</span>
<span style="color: #DD4422"> Test</span>
<span style="color: #DD4422"> A QGIS plugin</span>
<span style="color: #DD4422"> Plugin for testing things</span>
<span style="color: #DD4422"> -------------------</span>
<span style="color: #DD4422"> begin : 2015-01-28</span>
<span style="color: #DD4422"> copyright : (C) 2015-2017 by German Carrillo, GeoTux</span>
<span style="color: #DD4422"> email : gcarrillo@linuxmail.org</span>
<span style="color: #DD4422"> ***************************************************************************/</span>
<span style="color: #DD4422">/***************************************************************************</span>
<span style="color: #DD4422"> * *</span>
<span style="color: #DD4422"> * This program is free software; you can redistribute it and/or modify *</span>
<span style="color: #DD4422"> * it under the terms of the GNU General Public License as published by *</span>
<span style="color: #DD4422"> * the Free Software Foundation; either version 2 of the License, or *</span>
<span style="color: #DD4422"> * (at your option) any later version. *</span>
<span style="color: #DD4422"> * *</span>
<span style="color: #DD4422"> ***************************************************************************/</span>
<span style="color: #DD4422">"""</span>
<span style="color: #008800; font-weight: bold">import</span> <span style="color: #0e84b5; font-weight: bold">os</span>
<span style="color: #888888"># Import the PyQt and QGIS libraries</span>
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">qgis.core</span> <span style="color: #008800; font-weight: bold">import</span> (QgsApplication, QgsRasterLayer, QgsRaster, QgsPointXY,
QgsGeometry, QgsRectangle, QgsProject, QgsVectorLayer, QgsFeature)
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">qgis.gui</span> <span style="color: #008800; font-weight: bold">import</span> QgsMapToolEmitPoint, QgsRubberBand
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtCore</span> <span style="color: #008800; font-weight: bold">import</span> QObject, QTimer, Qt
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtWidgets</span> <span style="color: #008800; font-weight: bold">import</span> ( QMessageBox, QAction, QMenu, QActionGroup,
QWidgetAction, QToolTip)
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtGui</span> <span style="color: #008800; font-weight: bold">import</span> ( QIcon )
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">Test</span>:
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">__init__</span>(<span style="color: #007020">self</span>, iface):
<span style="color: #888888"># Save reference to the QGIS interface</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface <span style="color: #333333">=</span> iface
<span style="color: #007020">self</span><span style="color: #333333">.</span>tooltipRaster <span style="color: #333333">=</span> TooltipRasterMapTool( <span style="color: #007020">self</span><span style="color: #333333">.</span>iface )
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">initGui</span>(<span style="color: #007020">self</span>):
<span style="color: #888888"># Create action that will start plugin configuration</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>action <span style="color: #333333">=</span> QAction( QIcon( os<span style="color: #333333">.</span>path<span style="color: #333333">.</span>dirname(os<span style="color: #333333">.</span>path<span style="color: #333333">.</span>realpath(__file__)) <span style="color: #333333">+</span>
<span style="background-color: #fff0f0">"/icon_default.png"</span> ), <span style="background-color: #fff0f0">"For Making Rectangles"</span>, <span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mainWindow() )
<span style="color: #888888"># connect the action to the run method</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>action<span style="color: #333333">.</span>triggered<span style="color: #333333">.</span>connect( <span style="color: #007020">self</span><span style="color: #333333">.</span>run )
<span style="color: #007020">self</span><span style="color: #333333">.</span>action<span style="color: #333333">.</span>setCheckable( <span style="color: #007020">True</span> )
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mapCanvas()<span style="color: #333333">.</span>mapToolSet<span style="color: #333333">.</span>connect( <span style="color: #007020">self</span><span style="color: #333333">.</span>mapToolWasSet )
<span style="color: #888888"># Add toolbar button to the Plugins toolbar</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>addToolBarIcon(<span style="color: #007020">self</span><span style="color: #333333">.</span>action)
<span style="color: #888888"># Add menu item to the Plugins menu</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>addPluginToMenu(<span style="background-color: #fff0f0">"&Tooltip for Raster Values"</span>, <span style="color: #007020">self</span><span style="color: #333333">.</span>action)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">unload</span>(<span style="color: #007020">self</span>):
<span style="color: #888888"># Remove the plugin menu item and icon</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>removePluginMenu( <span style="background-color: #fff0f0">"&Tooltip for Raster Values"</span>, <span style="color: #007020">self</span><span style="color: #333333">.</span>action )
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>removeToolBarIcon(<span style="color: #007020">self</span><span style="color: #333333">.</span>action)
<span style="color: #888888"># run method that performs all the real work</span>
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">run</span>(<span style="color: #007020">self</span>, checked):
<span style="color: #008800; font-weight: bold">if</span> checked:
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mapCanvas()<span style="color: #333333">.</span>setMapTool( <span style="color: #007020">self</span><span style="color: #333333">.</span>tooltipRaster )
<span style="color: #008800; font-weight: bold">else</span>:
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mapCanvas()<span style="color: #333333">.</span>unsetMapTool( <span style="color: #007020">self</span><span style="color: #333333">.</span>tooltipRaster )
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">mapToolWasSet</span>( <span style="color: #007020">self</span>, newTool ):
<span style="color: #008800; font-weight: bold">if</span> <span style="color: #007020">type</span>(newTool) <span style="color: #333333">!=</span> TooltipRasterMapTool:
<span style="color: #007020">self</span><span style="color: #333333">.</span>action<span style="color: #333333">.</span>setChecked( <span style="color: #007020">False</span> )
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">TooltipRasterMapTool</span>(QgsMapToolEmitPoint):
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">__init__</span>(<span style="color: #007020">self</span>, iface):
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface <span style="color: #333333">=</span> iface
<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mapCanvas()
QgsMapToolEmitPoint<span style="color: #333333">.</span>__init__(<span style="color: #007020">self</span>, <span style="color: #007020">self</span><span style="color: #333333">.</span>canvas)
<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band <span style="color: #333333">=</span> QgsRubberBand(<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas, <span style="color: #007020">True</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>setColor(Qt<span style="color: #333333">.</span>red)
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>setOpacity(<span style="color: #6600EE; font-weight: bold">0.7</span>)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasPressEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>toMapCoordinates(e<span style="color: #333333">.</span>pos())
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>start_point
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasReleaseEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>toMapCoordinates(e<span style="color: #333333">.</span>pos())
r <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>get_rectangle()
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>reset()
<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
rect_feat <span style="color: #333333">=</span> r<span style="color: #333333">.</span>asWktPolygon()
<span style="color: #888888">#definng Status Bar</span>
statusBar <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mainWindow()<span style="color: #333333">.</span>statusBar()
<span style="color: #888888">#selecting elements in Status Bar</span>
elements <span style="color: #333333">=</span> statusBar<span style="color: #333333">.</span>children()
<span style="color: #888888">#selecting widget in Status Bar with ESPG</span>
EPSG <span style="color: #333333">=</span> elements[<span style="color: #0000DD; font-weight: bold">1</span>]<span style="color: #333333">.</span>children()[<span style="color: #0000DD; font-weight: bold">10</span>]
EPSG <span style="color: #333333">=</span> EPSG<span style="color: #333333">.</span>text()<span style="color: #333333">.</span>split(<span style="background-color: #fff0f0">':'</span>)
uri <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"Polygon?crs=epsg:"</span> <span style="color: #333333">+</span> EPSG[<span style="color: #0000DD; font-weight: bold">1</span>] <span style="color: #333333">+</span> <span style="background-color: #fff0f0">"&field=id:integer""&index=yes"</span>
mem_layer <span style="color: #333333">=</span> QgsVectorLayer(uri,
<span style="background-color: #fff0f0">'rectangle'</span>,
<span style="background-color: #fff0f0">'memory'</span>)
prov <span style="color: #333333">=</span> mem_layer<span style="color: #333333">.</span>dataProvider()
feat <span style="color: #333333">=</span> QgsFeature()
feat<span style="color: #333333">.</span>setAttributes([<span style="color: #0000DD; font-weight: bold">0</span>])
feat<span style="color: #333333">.</span>setGeometry(QgsGeometry<span style="color: #333333">.</span>fromWkt(rect_feat))
prov<span style="color: #333333">.</span>addFeatures([feat])
QgsProject<span style="color: #333333">.</span>instance()<span style="color: #333333">.</span>addMapLayer(mem_layer)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">get_rect_points</span>(<span style="color: #007020">self</span>, startPoint, endPoint):
points <span style="color: #333333">=</span> [[QgsPointXY(startPoint<span style="color: #333333">.</span>x(), startPoint<span style="color: #333333">.</span>y()), QgsPointXY(endPoint<span style="color: #333333">.</span>x(), startPoint<span style="color: #333333">.</span>y()), QgsPointXY(endPoint<span style="color: #333333">.</span>x(), endPoint<span style="color: #333333">.</span>y()), QgsPointXY(startPoint<span style="color: #333333">.</span>x(), endPoint<span style="color: #333333">.</span>y())]]
<span style="color: #008800; font-weight: bold">return</span> points
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">get_rectangle</span>(<span style="color: #007020">self</span>):
rect <span style="color: #333333">=</span> QgsRectangle(<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point, <span style="color: #007020">self</span><span style="color: #333333">.</span>end_point)
<span style="color: #008800; font-weight: bold">return</span> rect
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasMoveEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #008800; font-weight: bold">if</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>start_point:
end_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>toMapCoordinates(e<span style="color: #333333">.</span>pos())
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>reset()
p <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>get_rect_points(<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point, end_point)
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>setToGeometry(QgsGeometry<span style="color: #333333">.</span>fromPolygonXY(p), <span style="color: #007020">None</span>)
</pre></div>
<p>La carpeta completa de la plantilla (template) se guarda con el nombre de <b>makingrectangle</b> en la ruta de plugins de QGIS 3. El archivo <b>template.py</b> que tiene el código anterior se renombra como <b>making_rectangles.py</b>. Para que lo procese de la manera esperada se hace la modificación siguiente en el <b>__init__py</b>. </p>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #333333">.</span>
<span style="color: #333333">.</span>
<span style="color: #333333">.</span>
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">classFactory</span>(iface):
<span style="color: #888888"># load Test class from file test.py</span>
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">.making_rectangles</span> <span style="color: #008800; font-weight: bold">import</span> Test
<span style="color: #008800; font-weight: bold">return</span> Test(iface)
</pre></div>
<p>También necesitamos la modificación siguiente en el <b>metadata.txt</b> para que el nombre del plugin sea procesado como se espera. Una modificación similar también fue realizada en el código fuente al inicio del método 'initGui'.</p>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%">; the <span style="color: #007020">next</span> section <span style="color: #000000; font-weight: bold">is</span> mandatory
[general]
name<span style="color: #333333">=</span>Making Rectangles plugin
description<span style="color: #333333">=</span>For Making Rectangles<span style="color: #333333">.</span>
<span style="color: #333333">.</span>
<span style="color: #333333">.</span>
</pre></div>
<p>Finalmente, se produce un icono personalizado (con el mismo nombre) para identificarlo de manera precisa. La ejecución del plugin se observa en la imagen a continuación.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdID732JFIH6V3oSjdLVMSyKmwM9sM81t941gKoVY5bAHtPUCxYVB_cZlye6eVJG9pXw0VCsgg68xSJHqWY3utv4thDQbDOP6XSMPCZJ7PFOpZHP0x1zOQfNW-biVMcADXdZJyABcWlhA/s1920/plugin5.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1150" data-original-width="1920" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdID732JFIH6V3oSjdLVMSyKmwM9sM81t941gKoVY5bAHtPUCxYVB_cZlye6eVJG9pXw0VCsgg68xSJHqWY3utv4thDQbDOP6XSMPCZJ7PFOpZHP0x1zOQfNW-biVMcADXdZJyABcWlhA/s600/plugin5.png"/></a></div>
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-52126928856462131082020-12-27T21:15:00.000-04:002020-12-27T21:15:13.268-04:00Cómo producir un plugin plantilla tipo botón checkeable para PyQGIS 3<div style="text-align:justify;">
<p>En <a href="https://gis.stackexchange.com/questions/245280/display-raster-value-as-a-tooltip/245398#245398" target="_blank">esta respuesta</a> de <b>gis.stackexchange.com</b> se propone un plugin tipo botón checkeable con la antigua versión de QGIS 2 y que permite desplegar valores de ráster como tooltips. El comportamiento de este tipo de plugins no está en la oferta de Plugin Builder 3 por lo cual sería útil tenerlo disponible como plantilla. La importancia de este tipo de plugins radica en que sólo nos interesa que al hacer click en él se prepare para iniciar una acción y no se despliegue ningún tipo adicional de <b>QDialog</b>.</p><a name='more'></a>
<p>El plugin se denomina <b>test-tooltip_raster_values</b> y se puede bajar de <a href="https://github.com/gacarrillor/test/tree/tooltip_raster_values" target="_blank">este link</a>. Una vez bajado, el plugin se descomprime y la carpeta se nombra como <b>template</b> y se coloca en el directorio de plugins de QGIS 3. </p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOpopKqbjUMc0wvYvMczroqvkMl2V6aqZKtwiPiINtO025DfoebbxWqwMFw7VU7Tf5F0Gi8KJDkSBg1AwDTmjjH-08sqakFjR8YDe0ILNQvFP8QfkF7UiwKzKRq9CWQV3k3qvBfpiCVOg/s1024/plugin1.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="494" data-original-width="1024" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOpopKqbjUMc0wvYvMczroqvkMl2V6aqZKtwiPiINtO025DfoebbxWqwMFw7VU7Tf5F0Gi8KJDkSBg1AwDTmjjH-08sqakFjR8YDe0ILNQvFP8QfkF7UiwKzKRq9CWQV3k3qvBfpiCVOg/s600/plugin1.png"/></a></div>
<p>El archivo <b>test.py</b> se renombra como <b>template.py</b>; tal como se observa en la imagen siguiente:</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXlyXwQjh2esSZ8F7AELiioVn8wrAfUz7ZYHMwviWH5iMYM3q7dfr_Wk-vA6Z_-uBHzLKno2iwkeR3WLV5MNNRRUN8HxjNtBYlZ-qJkXmCg9xGjoy9e8KFHiw06jxCWFdPn1klyEAcBmk/s1024/plugin2.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="494" data-original-width="1024" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXlyXwQjh2esSZ8F7AELiioVn8wrAfUz7ZYHMwviWH5iMYM3q7dfr_Wk-vA6Z_-uBHzLKno2iwkeR3WLV5MNNRRUN8HxjNtBYlZ-qJkXmCg9xGjoy9e8KFHiw06jxCWFdPn1klyEAcBmk/s600/plugin2.png"/></a></div>
<p>Sin embargo, para que funcione adecuadamente, la penúltima línea del archivo __init__.py debe ser modificado en 'classFactory' como se detalla a continuación.</p>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #333333">.</span>
<span style="color: #333333">.</span>
<span style="color: #333333">.</span>
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">classFactory</span>(iface):
<span style="color: #888888"># load Test class from file test.py</span>
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">.template</span> <span style="color: #008800; font-weight: bold">import</span> Test
<span style="color: #008800; font-weight: bold">return</span> Test(iface)
</pre></div>
<p>No obstante, hay otras modificaciones que también deben hacerse. Las primeras de ellas están en el archivo <b>metadata.txt</b>; tal como se expone a continuación.</p>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #333333">.</span>
<span style="color: #333333">.</span>
<span style="color: #333333">.</span>
name<span style="color: #333333">=</span>template plugin
<span style="color: #333333">.</span>
<span style="color: #333333">.</span>
<span style="color: #333333">.</span>
qgisMinimumVersion<span style="color: #333333">=</span><span style="color: #6600EE; font-weight: bold">3.0</span>
<span style="color: #333333">.</span>
<span style="color: #333333">.</span>
<span style="color: #333333">.</span>
</pre></div>
<p>Las siguientes modifican las librerías PyQt4 a PyQt5 necesarias en QGIS 3 (SIGNAL ya no es necesaria en este caso). </p>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #333333">.</span>
<span style="color: #333333">.</span>
<span style="color: #333333">.</span>
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtCore</span> <span style="color: #008800; font-weight: bold">import</span> QObject, QTimer, Qt
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtWidgets</span> <span style="color: #008800; font-weight: bold">import</span> ( QMessageBox, QAction, QMenu, QActionGroup,
QWidgetAction, QToolTip)
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtGui</span> <span style="color: #008800; font-weight: bold">import</span> ( QIcon )
<span style="color: #333333">.</span>
<span style="color: #333333">.</span>
<span style="color: #333333">.</span>
</pre></div>
<p>Una vez hechas la modificaciones anteriores se inicia QGIS 3 y en <b>Plugins -> Manage and Install Plugins</b> se activa tal como aparece en la imagen siguiente.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRI1ZKLTShSrVjfq2LQ-oOCMJyiUbgRTIaMbX2d1HzNamiroVa7CEbHbMiKrKT_TH5MIo4SyUJ40TyZqbJlVR3Oj3FSCWJ21lqIyXU9LqQG906vBI97C7rO_Dmq1AgWMrCdp9ZXkCqoKg/s1920/plugin3.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1172" data-original-width="1920" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRI1ZKLTShSrVjfq2LQ-oOCMJyiUbgRTIaMbX2d1HzNamiroVa7CEbHbMiKrKT_TH5MIo4SyUJ40TyZqbJlVR3Oj3FSCWJ21lqIyXU9LqQG906vBI97C7rO_Dmq1AgWMrCdp9ZXkCqoKg/s600/plugin3.png"/></a></div>
<p>Ahora es sólo necesario comprobar que funciona adecuadamente. Para ello, hacemos click en el icono del plugin y con un ráster cargado colocamos el cursor sobre cualquier punto del mismo. En la imagen a continuación se puede observar que el tooltip se despliega de la manera esperada reflejando el valor del píxel en ese punto.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBSH0Cbc_sZbyLre_IQQ4b8tEizLjufGRwsODoe_Sw7jGxFc9NCP13F_atDA6vCBQHfrnuZr_3e5RfhiZ9c8wREpYw8STZbrdD3k9NxLX7TlumgIUgqWLdOeIPF09DuVFj97FhhOn4-1E/s1920/plugin4.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1173" data-original-width="1920" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBSH0Cbc_sZbyLre_IQQ4b8tEizLjufGRwsODoe_Sw7jGxFc9NCP13F_atDA6vCBQHfrnuZr_3e5RfhiZ9c8wREpYw8STZbrdD3k9NxLX7TlumgIUgqWLdOeIPF09DuVFj97FhhOn4-1E/s600/plugin4.png"/></a></div>
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-46150019986689718262020-12-25T19:25:00.000-04:002020-12-25T19:25:19.852-04:00Producir polígonos por dragado del Map Canvas con PyQGIS 3<div style="text-align:justify;">
<p>En posts anteriores (<a href="http://blogdezeka.blogspot.com/2020/12/producir-rectangulos-por-dragado-del.html" target="_blank">1</a>, <a href="http://blogdezeka.blogspot.com/2020/12/producir-circulos-por-dragado-del-map.html" target="_blank">2</a>) se introdujo la producción de rectángulos y círculos por dragado del Map Canvas con PyQgis 3. En el actual generalizamos el código para que este abarque polígonos regulares de más de tres lados (en el __init__ de la clase se define el número de lados).</p><a name='more'></a>
<p>El código se detalla a continuación para polígonos de 5 lados:</p>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><table><tr><td><pre style="margin: 0; line-height: 125%">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76</pre></td><td><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">import</span> <span style="color: #0e84b5; font-weight: bold">numpy</span> <span style="color: #008800; font-weight: bold">as</span> <span style="color: #0e84b5; font-weight: bold">np</span>
<span style="color: #008800; font-weight: bold">import</span> <span style="color: #0e84b5; font-weight: bold">math</span>
map_canvas <span style="color: #333333">=</span> iface<span style="color: #333333">.</span>mapCanvas()
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">dragPolygon</span>(QgsMapToolEmitPoint):
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">__init__</span>(<span style="color: #007020">self</span>, canvas):
<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas <span style="color: #333333">=</span> canvas
QgsMapToolEmitPoint<span style="color: #333333">.</span>__init__(<span style="color: #007020">self</span>, <span style="color: #007020">self</span><span style="color: #333333">.</span>canvas)
<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band <span style="color: #333333">=</span> QgsRubberBand(<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas, <span style="color: #007020">True</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>setColor(Qt<span style="color: #333333">.</span>red)
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>setOpacity(<span style="color: #6600EE; font-weight: bold">0.7</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>polygonSides <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">5</span>
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasPressEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>toMapCoordinates(e<span style="color: #333333">.</span>pos())
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>start_point
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasMoveEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #008800; font-weight: bold">if</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>start_point:
end_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>toMapCoordinates(e<span style="color: #333333">.</span>pos())
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>reset()
z <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>get_pol_par(<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point, end_point, <span style="color: #007020">self</span><span style="color: #333333">.</span>polygonSides)<span style="color: #333333">.</span>asWkt()
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>setToGeometry(QgsGeometry<span style="color: #333333">.</span>fromWkt(z), <span style="color: #007020">None</span>)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasReleaseEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>toMapCoordinates(e<span style="color: #333333">.</span>pos())
p <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>get_pol(<span style="color: #007020">self</span><span style="color: #333333">.</span>polygonSides)
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>reset()
<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
pol_feat <span style="color: #333333">=</span> p
<span style="color: #888888">#definng Status Bar</span>
statusBar <span style="color: #333333">=</span> iface<span style="color: #333333">.</span>mainWindow()<span style="color: #333333">.</span>statusBar()
<span style="color: #888888">#selecting elements in Status Bar</span>
elements <span style="color: #333333">=</span> statusBar<span style="color: #333333">.</span>children()
<span style="color: #888888">#selecting widget in Status Bar with ESPG</span>
EPSG <span style="color: #333333">=</span> elements[<span style="color: #0000DD; font-weight: bold">1</span>]<span style="color: #333333">.</span>children()[<span style="color: #0000DD; font-weight: bold">10</span>]
EPSG <span style="color: #333333">=</span> EPSG<span style="color: #333333">.</span>text()<span style="color: #333333">.</span>split(<span style="background-color: #fff0f0">':'</span>)
uri <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"Polygon?crs=epsg:"</span> <span style="color: #333333">+</span> EPSG[<span style="color: #0000DD; font-weight: bold">1</span>] <span style="color: #333333">+</span> <span style="background-color: #fff0f0">"&field=id:integer""&index=yes"</span>
mem_layer <span style="color: #333333">=</span> QgsVectorLayer(uri,
<span style="background-color: #fff0f0">'polygon'</span>,
<span style="background-color: #fff0f0">'memory'</span>)
prov <span style="color: #333333">=</span> mem_layer<span style="color: #333333">.</span>dataProvider()
feat <span style="color: #333333">=</span> QgsFeature()
feat<span style="color: #333333">.</span>setAttributes([<span style="color: #0000DD; font-weight: bold">0</span>])
feat<span style="color: #333333">.</span>setGeometry(QgsGeometry<span style="color: #333333">.</span>fromWkt(pol_feat))
prov<span style="color: #333333">.</span>addFeatures([feat])
QgsProject<span style="color: #333333">.</span>instance()<span style="color: #333333">.</span>addMapLayer(mem_layer)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">get_pol_par</span>(<span style="color: #007020">self</span>, startPoint, endPoint, polygonSides):
diameter <span style="color: #333333">=</span> math<span style="color: #333333">.</span>sqrt((startPoint<span style="color: #333333">.</span>x() <span style="color: #333333">-</span> endPoint<span style="color: #333333">.</span>x())<span style="color: #333333">**</span><span style="color: #0000DD; font-weight: bold">2</span> <span style="color: #333333">+</span> (startPoint<span style="color: #333333">.</span>y() <span style="color: #333333">-</span> endPoint<span style="color: #333333">.</span>y())<span style="color: #333333">**</span><span style="color: #0000DD; font-weight: bold">2</span>)
point <span style="color: #333333">=</span> QgsPointXY(startPoint)
geom <span style="color: #333333">=</span> QgsGeometry<span style="color: #333333">.</span>fromPolygonXY([[ QgsPointXY(point<span style="color: #333333">.</span>x() <span style="color: #333333">+</span> np<span style="color: #333333">.</span>sin(angle)<span style="color: #333333">*</span>diameter, point<span style="color: #333333">.</span>y() <span style="color: #333333">+</span> np<span style="color: #333333">.</span>cos(angle)<span style="color: #333333">*</span>diameter)
<span style="color: #008800; font-weight: bold">for</span> angle <span style="color: #000000; font-weight: bold">in</span> np<span style="color: #333333">.</span>linspace(<span style="color: #0000DD; font-weight: bold">0</span>, <span style="color: #0000DD; font-weight: bold">2</span><span style="color: #333333">*</span>np<span style="color: #333333">.</span>pi, polygonSides, endpoint <span style="color: #333333">=</span> <span style="color: #007020">False</span>) ]])
<span style="color: #008800; font-weight: bold">return</span> geom
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">get_pol</span>(<span style="color: #007020">self</span>, polygonSides):
diameter <span style="color: #333333">=</span> math<span style="color: #333333">.</span>sqrt((<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point<span style="color: #333333">.</span>x() <span style="color: #333333">-</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>end_point<span style="color: #333333">.</span>x())<span style="color: #333333">**</span><span style="color: #0000DD; font-weight: bold">2</span> <span style="color: #333333">+</span> (<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point<span style="color: #333333">.</span>y() <span style="color: #333333">-</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>end_point<span style="color: #333333">.</span>y())<span style="color: #333333">**</span><span style="color: #0000DD; font-weight: bold">2</span>)
point <span style="color: #333333">=</span> QgsPointXY(<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point)
geom <span style="color: #333333">=</span> QgsGeometry<span style="color: #333333">.</span>fromPolygonXY([[ QgsPointXY(point<span style="color: #333333">.</span>x() <span style="color: #333333">+</span> np<span style="color: #333333">.</span>sin(angle)<span style="color: #333333">*</span>diameter, point<span style="color: #333333">.</span>y() <span style="color: #333333">+</span> np<span style="color: #333333">.</span>cos(angle)<span style="color: #333333">*</span>diameter)
<span style="color: #008800; font-weight: bold">for</span> angle <span style="color: #000000; font-weight: bold">in</span> np<span style="color: #333333">.</span>linspace(<span style="color: #0000DD; font-weight: bold">0</span>, <span style="color: #0000DD; font-weight: bold">2</span><span style="color: #333333">*</span>np<span style="color: #333333">.</span>pi, polygonSides, endpoint <span style="color: #333333">=</span> <span style="color: #007020">False</span>) ]])
<span style="color: #008800; font-weight: bold">return</span> geom<span style="color: #333333">.</span>asWkt()
T <span style="color: #333333">=</span> dragPolygon(map_canvas)
map_canvas<span style="color: #333333">.</span>setMapTool(T)
<span style="color: #888888">#T.deactivated.connect(lambda: print('Tool deactivated'))</span>
</pre></td></tr></table></div>
<p>La ejecución del código anterior en la Python Console de QGIS producirá la rubber band de la imagen siguiente cuando se draga el ratón desde un punto cercano al centro del ráster.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisrFx8V8-7i5wY_QrKSUWjOZzwTDkBQSCijBIi9GurXM5SloL2sYaddz_3sYrCKOxHaaDWCf2CLUYBdqgn4CTyWoUybw4ISbcxCs4PAXu6OOuCdJIhyu8EKnFWBZdJEcAd8xv-kpPMt8Q/s1920/drag1.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1173" data-original-width="1920" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisrFx8V8-7i5wY_QrKSUWjOZzwTDkBQSCijBIi9GurXM5SloL2sYaddz_3sYrCKOxHaaDWCf2CLUYBdqgn4CTyWoUybw4ISbcxCs4PAXu6OOuCdJIhyu8EKnFWBZdJEcAd8xv-kpPMt8Q/s600/drag1.png"/></a></div>
<p>Cuando se liberá el cursor, el rasgo con forma pentagonal se posiciona en la misma zona que corresponde a la última rubber band que se produce de manera interactiva durante el dragado con el mouse. Es lo que se observa en la imagen siguiente.</p
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgvdRCNMWu9fb7Q8bW_KSyvUDoLK2anwQC9texOG0SkhBBd3qinyuEdwD73r03EnOmvZEeH2tUGGjxGH7zghg2pm0QIzP4Sg_P_izpBmdwL6UkleqfzXx3eyiPTnxJiQOV7135KjXMe4s/s1920/drag2.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1150" data-original-width="1920" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgvdRCNMWu9fb7Q8bW_KSyvUDoLK2anwQC9texOG0SkhBBd3qinyuEdwD73r03EnOmvZEeH2tUGGjxGH7zghg2pm0QIzP4Sg_P_izpBmdwL6UkleqfzXx3eyiPTnxJiQOV7135KjXMe4s/s600/drag2.png"/></a></div>
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-44441257775346483902020-12-23T22:26:00.000-04:002020-12-23T22:26:40.252-04:00Producir círculos por dragado del Map Canvas con PyQGIS 3<div style="text-align:justify;">
<p>En el <a href="http://blogdezeka.blogspot.com/2020/12/producir-rectangulos-por-dragado-del.html" target="_blank">post anterior</a> se consideró la produción de rectángulos por dragado del Map Canvas con PyQGIS 3. La geometría de los rectángulos se colocaba de manera interactiva en las rubber bands durante el dragado de los mismos y, una vez liberado el cursor, la geometría del rectángulo final se pasaba como feature a la memory layer correspondiente.</p><a name='more'></a>
<p>En este post se modifica el código del post anterior para que las rubber bands y la memory layer consideren ahora una geometría circular empleando la clase <b>QgsCircle</b>. El código modificado se presenta a continuación.</p>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><table><tr><td><pre style="margin: 0; line-height: 125%">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70</pre></td><td><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">import</span> <span style="color: #0e84b5; font-weight: bold">math</span>
map_canvas <span style="color: #333333">=</span> iface<span style="color: #333333">.</span>mapCanvas()
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">dragCircle</span>(QgsMapToolEmitPoint):
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">__init__</span>(<span style="color: #007020">self</span>, canvas):
<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas <span style="color: #333333">=</span> canvas
QgsMapToolEmitPoint<span style="color: #333333">.</span>__init__(<span style="color: #007020">self</span>, <span style="color: #007020">self</span><span style="color: #333333">.</span>canvas)
<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band <span style="color: #333333">=</span> QgsRubberBand(<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas, <span style="color: #007020">True</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>setColor(Qt<span style="color: #333333">.</span>red)
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>setOpacity(<span style="color: #6600EE; font-weight: bold">0.7</span>)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasPressEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>toMapCoordinates(e<span style="color: #333333">.</span>pos())
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>start_point
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasMoveEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #008800; font-weight: bold">if</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>start_point:
end_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>toMapCoordinates(e<span style="color: #333333">.</span>pos())
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>reset()
q <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>get_circ_par(<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point, end_point)
h <span style="color: #333333">=</span> QgsCircle(q[<span style="color: #0000DD; font-weight: bold">0</span>], q[<span style="color: #0000DD; font-weight: bold">1</span>])<span style="color: #333333">.</span>toPolygon()<span style="color: #333333">.</span>asWkt()
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>setToGeometry(QgsGeometry<span style="color: #333333">.</span>fromWkt(h), <span style="color: #007020">None</span>)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasReleaseEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>toMapCoordinates(e<span style="color: #333333">.</span>pos())
r <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>get_circle()
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>reset()
<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
circ_feat <span style="color: #333333">=</span> r
<span style="color: #888888">#definng Status Bar</span>
statusBar <span style="color: #333333">=</span> iface<span style="color: #333333">.</span>mainWindow()<span style="color: #333333">.</span>statusBar()
<span style="color: #888888">#selecting elements in Status Bar</span>
elements <span style="color: #333333">=</span> statusBar<span style="color: #333333">.</span>children()
<span style="color: #888888">#selecting widget in Status Bar with ESPG</span>
EPSG <span style="color: #333333">=</span> elements[<span style="color: #0000DD; font-weight: bold">1</span>]<span style="color: #333333">.</span>children()[<span style="color: #0000DD; font-weight: bold">10</span>]
EPSG <span style="color: #333333">=</span> EPSG<span style="color: #333333">.</span>text()<span style="color: #333333">.</span>split(<span style="background-color: #fff0f0">':'</span>)
uri <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"Polygon?crs=epsg:"</span> <span style="color: #333333">+</span> EPSG[<span style="color: #0000DD; font-weight: bold">1</span>] <span style="color: #333333">+</span> <span style="background-color: #fff0f0">"&field=id:integer""&index=yes"</span>
mem_layer <span style="color: #333333">=</span> QgsVectorLayer(uri,
<span style="background-color: #fff0f0">'circle'</span>,
<span style="background-color: #fff0f0">'memory'</span>)
prov <span style="color: #333333">=</span> mem_layer<span style="color: #333333">.</span>dataProvider()
feat <span style="color: #333333">=</span> QgsFeature()
feat<span style="color: #333333">.</span>setAttributes([<span style="color: #0000DD; font-weight: bold">0</span>])
feat<span style="color: #333333">.</span>setGeometry(QgsGeometry<span style="color: #333333">.</span>fromWkt(circ_feat))
prov<span style="color: #333333">.</span>addFeatures([feat])
QgsProject<span style="color: #333333">.</span>instance()<span style="color: #333333">.</span>addMapLayer(mem_layer)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">get_circ_par</span>(<span style="color: #007020">self</span>, startPoint, endPoint):
par <span style="color: #333333">=</span> [QgsPoint(startPoint<span style="color: #333333">.</span>x(), startPoint<span style="color: #333333">.</span>y()),
math<span style="color: #333333">.</span>sqrt((startPoint<span style="color: #333333">.</span>x() <span style="color: #333333">-</span> endPoint<span style="color: #333333">.</span>x())<span style="color: #333333">**</span><span style="color: #0000DD; font-weight: bold">2</span> <span style="color: #333333">+</span> (startPoint<span style="color: #333333">.</span>y() <span style="color: #333333">-</span> endPoint<span style="color: #333333">.</span>y())<span style="color: #333333">**</span><span style="color: #0000DD; font-weight: bold">2</span>)]
<span style="color: #008800; font-weight: bold">return</span> par
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">get_circle</span>(<span style="color: #007020">self</span>):
dist <span style="color: #333333">=</span> math<span style="color: #333333">.</span>sqrt((<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point<span style="color: #333333">.</span>x() <span style="color: #333333">-</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>end_point<span style="color: #333333">.</span>x())<span style="color: #333333">**</span><span style="color: #0000DD; font-weight: bold">2</span> <span style="color: #333333">+</span> (<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point<span style="color: #333333">.</span>y() <span style="color: #333333">-</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>end_point<span style="color: #333333">.</span>y())<span style="color: #333333">**</span><span style="color: #0000DD; font-weight: bold">2</span>)
circ <span style="color: #333333">=</span> QgsCircle(QgsPoint(<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point), dist)<span style="color: #333333">.</span>toPolygon()<span style="color: #333333">.</span>asWkt()
<span style="color: #008800; font-weight: bold">return</span> circ
T <span style="color: #333333">=</span> dragCircle(map_canvas)
map_canvas<span style="color: #333333">.</span>setMapTool(T)
<span style="color: #888888">#T.deactivated.connect(lambda: print('Tool deactivated'))</span>
</pre></td></tr></table></div>
<p>Ejecutamos el código anterior en la Python Console de QGIS con una capa ráster previamente cargada. El dragado con el ratón se hizo desde un punto ubicado ligeramente por encima y hacia la izquierda del centro del ráster. La rubber band producida durante el dragado se observa a continuación.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4ULHJ5l6XYmo_beXjLDw8UwPFJvFjF1eYGmNyjoGzw9fGS1dNl_yxyDG1UWX0IBIKQc9U0R6K8Cpv_E9LP7tCDmOoswqujrmlVXSe26NqqtULZo4MYj1rYne_RDcnnYlLYt_UWiBW7lk/s1920/circle1.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1173" data-original-width="1920" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4ULHJ5l6XYmo_beXjLDw8UwPFJvFjF1eYGmNyjoGzw9fGS1dNl_yxyDG1UWX0IBIKQc9U0R6K8Cpv_E9LP7tCDmOoswqujrmlVXSe26NqqtULZo4MYj1rYne_RDcnnYlLYt_UWiBW7lk/s600/circle1.png"/></a>
<p>Una vez que se libera el cursor del ratón el feature se produce, tal como se esperaba, en la misma zona que corresponde a la rubber band final. Es lo que se visualiza en la imagen siguiente.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi__ct3zZAL956FU2O1JVnjHn1PAxwC2ZWx5Rbkc0B-EdowjfhrUO5xbdy4stv_d9DLXSNxl4qzUVvbJYZzU6eSsJ5SHnA_xpCcdqgJoyRWaW5QhlFVSkC8HKivqc4LYJA-xgVz21xuVbI/s1920/circle2.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1150" data-original-width="1920" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi__ct3zZAL956FU2O1JVnjHn1PAxwC2ZWx5Rbkc0B-EdowjfhrUO5xbdy4stv_d9DLXSNxl4qzUVvbJYZzU6eSsJ5SHnA_xpCcdqgJoyRWaW5QhlFVSkC8HKivqc4LYJA-xgVz21xuVbI/s600/circle2.png"/></a></div>
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-87078469211235382652020-12-22T08:31:00.000-04:002020-12-22T08:31:22.749-04:00Producir rectángulos por dragado del Map Canvas con PyQGIS 3<div style="text-align:justify;">Modificando el código de la respuesta que se encuentra en <a href="https://gis.stackexchange.com/questions/382558/capture-coordinates-of-a-rectangle-drawn-on-the-canvas" target="_blank">este link</a> es posible construir capas vectoriales tipo polígono, con forma rectángular, como memory layers. El código se presenta a continuación:
<p></p><a name='more'></a>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><table><tr><td><pre style="margin: 0; line-height: 125%">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65</pre></td><td><pre style="margin: 0; line-height: 125%">map_canvas <span style="color: #333333">=</span> iface<span style="color: #333333">.</span>mapCanvas()
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">dragRectangle</span>(QgsMapToolEmitPoint):
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">__init__</span>(<span style="color: #007020">self</span>, canvas):
<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas <span style="color: #333333">=</span> canvas
QgsMapToolEmitPoint<span style="color: #333333">.</span>__init__(<span style="color: #007020">self</span>, <span style="color: #007020">self</span><span style="color: #333333">.</span>canvas)
<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band <span style="color: #333333">=</span> QgsRubberBand(<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas, <span style="color: #007020">True</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>setColor(Qt<span style="color: #333333">.</span>red)
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>setOpacity(<span style="color: #6600EE; font-weight: bold">0.7</span>)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasPressEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>toMapCoordinates(e<span style="color: #333333">.</span>pos())
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>start_point
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasMoveEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #008800; font-weight: bold">if</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>start_point:
end_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>toMapCoordinates(e<span style="color: #333333">.</span>pos())
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>reset()
p <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>get_rect_points(<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point, end_point)
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>setToGeometry(QgsGeometry<span style="color: #333333">.</span>fromPolygonXY(p), <span style="color: #007020">None</span>)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">canvasReleaseEvent</span>(<span style="color: #007020">self</span>, e):
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>toMapCoordinates(e<span style="color: #333333">.</span>pos())
r <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>get_rectangle()
<span style="color: #007020">self</span><span style="color: #333333">.</span>rubber_band<span style="color: #333333">.</span>reset()
<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>end_point <span style="color: #333333">=</span> <span style="color: #007020">None</span>
rect_feat <span style="color: #333333">=</span> r<span style="color: #333333">.</span>asWktPolygon()
<span style="color: #888888">#definng Status Bar</span>
statusBar <span style="color: #333333">=</span> iface<span style="color: #333333">.</span>mainWindow()<span style="color: #333333">.</span>statusBar()
<span style="color: #888888">#selecting elements in Status Bar</span>
elements <span style="color: #333333">=</span> statusBar<span style="color: #333333">.</span>children()
<span style="color: #888888">#selecting widget in Status Bar with ESPG</span>
EPSG <span style="color: #333333">=</span> elements[<span style="color: #0000DD; font-weight: bold">1</span>]<span style="color: #333333">.</span>children()[<span style="color: #0000DD; font-weight: bold">10</span>]
EPSG <span style="color: #333333">=</span> EPSG<span style="color: #333333">.</span>text()<span style="color: #333333">.</span>split(<span style="background-color: #fff0f0">':'</span>)
uri <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"Polygon?crs=epsg:"</span> <span style="color: #333333">+</span> EPSG[<span style="color: #0000DD; font-weight: bold">1</span>] <span style="color: #333333">+</span> <span style="background-color: #fff0f0">"&field=id:integer""&index=yes"</span>
mem_layer <span style="color: #333333">=</span> QgsVectorLayer(uri,
<span style="background-color: #fff0f0">'rectangle'</span>,
<span style="background-color: #fff0f0">'memory'</span>)
prov <span style="color: #333333">=</span> mem_layer<span style="color: #333333">.</span>dataProvider()
feat <span style="color: #333333">=</span> QgsFeature()
feat<span style="color: #333333">.</span>setAttributes([<span style="color: #0000DD; font-weight: bold">0</span>])
feat<span style="color: #333333">.</span>setGeometry(QgsGeometry<span style="color: #333333">.</span>fromWkt(rect_feat))
prov<span style="color: #333333">.</span>addFeatures([feat])
QgsProject<span style="color: #333333">.</span>instance()<span style="color: #333333">.</span>addMapLayer(mem_layer)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">get_rect_points</span>(<span style="color: #007020">self</span>, startPoint, endPoint):
points <span style="color: #333333">=</span> [[QgsPointXY(startPoint<span style="color: #333333">.</span>x(), startPoint<span style="color: #333333">.</span>y()), QgsPointXY(endPoint<span style="color: #333333">.</span>x(), startPoint<span style="color: #333333">.</span>y()), QgsPointXY(endPoint<span style="color: #333333">.</span>x(), endPoint<span style="color: #333333">.</span>y()), QgsPointXY(startPoint<span style="color: #333333">.</span>x(), endPoint<span style="color: #333333">.</span>y())]]
<span style="color: #008800; font-weight: bold">return</span> points
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">get_rectangle</span>(<span style="color: #007020">self</span>):
rect <span style="color: #333333">=</span> QgsRectangle(<span style="color: #007020">self</span><span style="color: #333333">.</span>start_point, <span style="color: #007020">self</span><span style="color: #333333">.</span>end_point)
<span style="color: #008800; font-weight: bold">return</span> rect
T <span style="color: #333333">=</span> dragRectangle(map_canvas)
map_canvas<span style="color: #333333">.</span>setMapTool(T)
<span style="color: #888888">#T.deactivated.connect(lambda: print('Tool deactivated'))</span>
</pre></td></tr></table></div>
<p>Después de ejecutado el código en la Python Console de QGIS 3, el cursor toma forma de cruz señalando que es posible dragar el Map Canvas para producir una capa vectorial con forma de rectángulo. En la imagen siguiente se observa la superficie dragada en el Map Canvas.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVaKZrIKXSdHvWE68ayXFgbE0tvQZ7jrVCRMXOcQzQmFEWz4fLqeYk9TapRccJKf_rzjvyeGBa77giShucgT8Rd_UJYMbqP7x7XMbHYR1njUSdURPl8KtQ2OhksZL0HKWFPAoyNWRrQ54/s1920/dragado1.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1173" data-original-width="1920" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVaKZrIKXSdHvWE68ayXFgbE0tvQZ7jrVCRMXOcQzQmFEWz4fLqeYk9TapRccJKf_rzjvyeGBa77giShucgT8Rd_UJYMbqP7x7XMbHYR1njUSdURPl8KtQ2OhksZL0HKWFPAoyNWRrQ54/s600/dragado1.png"/></a></div>
<p>Una vez que se suelta el cursor se produce en breves instantes la capa vectorial esperada. El CRS de la misma es el que por defecto presentan los proyectos que no contienen capa alguna (EPSG:4326). Por esta razón la proporcion es diferente al de la imagen anterior.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPAbEBZEpPw1yjN6O0iVIv0hqJeYH5SSICyjgguBVV_PhjLAB2gHOu0OXk2etfvl2HVvpxRFnX7Cw-qGWAQecFGWCrQZblu7MR6riyAwpA3jzYEr22zY7_Hh8S18asxZZ5c82srtsluLA/s1920/dragado2.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1176" data-original-width="1920" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPAbEBZEpPw1yjN6O0iVIv0hqJeYH5SSICyjgguBVV_PhjLAB2gHOu0OXk2etfvl2HVvpxRFnX7Cw-qGWAQecFGWCrQZblu7MR6riyAwpA3jzYEr22zY7_Hh8S18asxZZ5c82srtsluLA/s600/dragado2.png"/></a></div>
<p>Para verificar que funciona de la manera esperada vamos a cargar una capa ráster con EPSG:32612 y dragamos en una superficie arbitraria sobre la misma; tal como se observa en la imagen siguiente.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGDDRY3FWHvMtN1nx1eZhlFq4_SJmevPxYYTaSSwOvf8_5crTIcRRv7BVB4MNYQPvHk6QrslcfC7KyezaxtqEPPveNiNYbs8b-UUobn7yYMDceWEa6gJTK1JnoQTjCP-0znV1sSQs_L-k/s1920/dragado3.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1175" data-original-width="1920" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGDDRY3FWHvMtN1nx1eZhlFq4_SJmevPxYYTaSSwOvf8_5crTIcRRv7BVB4MNYQPvHk6QrslcfC7KyezaxtqEPPveNiNYbs8b-UUobn7yYMDceWEa6gJTK1JnoQTjCP-0znV1sSQs_L-k/s600/dragado3.png"/></a></div>
<p>Una vez que se libera el cursor la capa vectorial, tal como se esperaba, se produce sobre la misma superfice dragada de la imagen anterior.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT8jowpmknR9onjJXqEtPd8x_nEMaZHSiNn2sZasehTWS4lnl6iWBV8at4oHgHMAMeQWG8ykA7BtWbOyXJqJ-TdXrzkUeAjvtnaakvtMrCUw57UBw4GpjVjF3dAkaPvVAs-P8971JXSxc/s1920/dragado4.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1150" data-original-width="1920" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT8jowpmknR9onjJXqEtPd8x_nEMaZHSiNn2sZasehTWS4lnl6iWBV8at4oHgHMAMeQWG8ykA7BtWbOyXJqJ-TdXrzkUeAjvtnaakvtMrCUw57UBw4GpjVjF3dAkaPvVAs-P8971JXSxc/s600/dragado4.png"/></a></div>
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-4716185600891594602020-12-21T22:05:00.002-04:002020-12-21T22:08:30.163-04:00Cómo obtener la proyección a partir de la Status Bar de QGIS 3 mediante PyQGIS?<div style="text-align:justify;">La proyección es un elemento importante a la hora de producir capas vectoriales o ráster porque hará que estas se desplieguen de la manera adecuada desde un punto de vista geográfico. Cuando se abre QGIS, con capas o sin ellas, en la Status Bar se observa la proyección con código EPSG en la parte inferior derecha. La Status Bar en QGIS 3 (<b>PyQt5.QtWidgets.QStatusBar</b>) es un objeto de la ventana principal (<b>PyQt5.QtWidgets.QMainWindow</b>) que se obtiene a partir de los métodos 'mainWindow()' y 'statusBar()' de las clases <b>QgisInterface</b> y <b>PyQt5.QtWidgets.QMainWindow</b> respectivamente
<p>La serie de comandos siguiente, ejecutados en la Python Console de QGIS, permitirá definir y acceder a los metodos de la clase correspondiente a la Status Bar.</p><a name='more'></a>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #333333">>>></span>statusBar <span style="color: #333333">=</span> iface<span style="color: #333333">.</span>mainWindow()<span style="color: #333333">.</span>statusBar()
<span style="color: #333333">>>></span>statusBar
<span style="color: #333333"><</span>PyQt5<span style="color: #333333">.</span>QtWidgets<span style="color: #333333">.</span>QStatusBar <span style="color: #007020">object</span> at <span style="color: #005588; font-weight: bold">0x7f2ff0729a68</span><span style="color: #333333">></span>
</pre></div>
<p>El objeto del tipo <b>QStatusBar</b> presenta el método 'children' que permite producir una lista con todos los elementos involucrados; tal como se observa a continuación.</p>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #333333">>>></span>elements <span style="color: #333333">=</span> statusBar<span style="color: #333333">.</span>children()
<span style="color: #333333">>>></span>elements
[<span style="color: #333333"><</span>PyQt5<span style="color: #333333">.</span>QtWidgets<span style="color: #333333">.</span>QSizeGrip <span style="color: #007020">object</span> at <span style="color: #005588; font-weight: bold">0x7fe3e56f6ca8</span><span style="color: #333333">></span>, <span style="color: #333333"><</span>PyQt5<span style="color: #333333">.</span>QtWidgets<span style="color: #333333">.</span>QWidget <span style="color: #007020">object</span> at <span style="color: #005588; font-weight: bold">0x7fe3e56f6d38</span><span style="color: #333333">></span>, <span style="color: #333333"><</span>PyQt5<span style="color: #333333">.</span>QtWidgets<span style="color: #333333">.</span>QHBoxLayout <span style="color: #007020">object</span> at <span style="color: #005588; font-weight: bold">0x7fe3e56f6dc8</span><span style="color: #333333">></span>]
</pre></div>
<p>El segundo elemento (elements[1]) es del tipo <b>QWidgets</b> el cual también presenta el método 'children' y contiene a su vez los items de la Status Bar. El décimo de ellos corresponde a un objeto del tipo <b>QToolButton</b> que incluye el código EPSG requerido.</p>
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #333333">>>></span>elements[<span style="color: #0000DD; font-weight: bold">1</span>]<span style="color: #333333">.</span>children()
[<span style="color: #333333"><</span>PyQt5<span style="color: #333333">.</span>QtWidgets<span style="color: #333333">.</span>QHBoxLayout <span style="color: #007020">object</span> at <span style="color: #005588; font-weight: bold">0x7fe3e56ff9d8</span><span style="color: #333333">></span>, <span style="color: #333333"><</span>PyQt5<span style="color: #333333">.</span>QtWidgets<span style="color: #333333">.</span>QLineEdit <span style="color: #007020">object</span> at <span style="color: #005588; font-weight: bold">0x7fe3e56ffa68</span><span style="color: #333333">></span>, <span style="color: #333333"><</span>PyQt5<span style="color: #333333">.</span>QtWidgets<span style="color: #333333">.</span>QProgressBar <span style="color: #007020">object</span> at <span style="color: #005588; font-weight: bold">0x7fe3e56ffaf8</span><span style="color: #333333">></span>, <span style="color: #333333"><</span>PyQt5<span style="color: #333333">.</span>QtWidgets<span style="color: #333333">.</span>QToolButton <span style="color: #007020">object</span> at <span style="color: #005588; font-weight: bold">0x7fe3e56ffb88</span><span style="color: #333333">></span>, <span style="color: #333333"><</span>PyQt5<span style="color: #333333">.</span>QtWidgets<span style="color: #333333">.</span>QWidget <span style="color: #007020">object</span> at <span style="color: #005588; font-weight: bold">0x7fe3e56ffc18</span><span style="color: #333333">></span>, <span style="color: #333333"><</span>PyQt5<span style="color: #333333">.</span>QtWidgets<span style="color: #333333">.</span>QWidget <span style="color: #007020">object</span> at <span style="color: #005588; font-weight: bold">0x7fe3e56ffca8</span><span style="color: #333333">></span>, <span style="color: #333333"><</span>PyQt5<span style="color: #333333">.</span>QtWidgets<span style="color: #333333">.</span>QWidget <span style="color: #007020">object</span> at <span style="color: #005588; font-weight: bold">0x7fe3e56ffd38</span><span style="color: #333333">></span>, <span style="color: #333333"><</span>PyQt5<span style="color: #333333">.</span>QtWidgets<span style="color: #333333">.</span>QLabel <span style="color: #007020">object</span> at <span style="color: #005588; font-weight: bold">0x7fe3e56ffdc8</span><span style="color: #333333">></span>, <span style="color: #333333"><</span>qgis<span style="color: #333333">.</span>_gui<span style="color: #333333">.</span>QgsDoubleSpinBox <span style="color: #007020">object</span> at <span style="color: #005588; font-weight: bold">0x7fe3e56ffe58</span><span style="color: #333333">></span>, <span style="color: #333333"><</span>PyQt5<span style="color: #333333">.</span>QtWidgets<span style="color: #333333">.</span>QCheckBox <span style="color: #007020">object</span> at <span style="color: #005588; font-weight: bold">0x7fe3e56ffee8</span><span style="color: #333333">></span>, <span style="color: #333333"><</span>PyQt5<span style="color: #333333">.</span>QtWidgets<span style="color: #333333">.</span>QToolButton <span style="color: #007020">object</span> at <span style="color: #005588; font-weight: bold">0x7fe3e56fff78</span><span style="color: #333333">></span>, <span style="color: #333333"><</span>PyQt5<span style="color: #333333">.</span>QtWidgets<span style="color: #333333">.</span>QToolButton <span style="color: #007020">object</span> at <span style="color: #005588; font-weight: bold">0x7fe3e5700048</span><span style="color: #333333">></span>, <span style="color: #333333"><</span>PyQt5<span style="color: #333333">.</span>QtWidgets<span style="color: #333333">.</span>QWidget <span style="color: #007020">object</span> at <span style="color: #005588; font-weight: bold">0x7fe3e57000d8</span><span style="color: #333333">></span>]
<span style="color: #333333">>>></span>elements[<span style="color: #0000DD; font-weight: bold">1</span>]<span style="color: #333333">.</span>children()[<span style="color: #0000DD; font-weight: bold">10</span>]
<span style="color: #333333"><</span>PyQt5<span style="color: #333333">.</span>QtWidgets<span style="color: #333333">.</span>QToolButton <span style="color: #007020">object</span> at <span style="color: #005588; font-weight: bold">0x7fe3e56fff78</span><span style="color: #333333">></span>
<span style="color: #333333">>>></span>elements[<span style="color: #0000DD; font-weight: bold">1</span>]<span style="color: #333333">.</span>children()[<span style="color: #0000DD; font-weight: bold">10</span>]<span style="color: #333333">.</span>text()
<span style="background-color: #fff0f0">'EPSG:4326'</span>
</pre></div>
<p>La importancia de acceder a este código en la Status Bar radica en que no hace falta la referencia a las capas cargadas en el Map Canvas o en la Map Legend sino que directamente accedemos al CRS del proyecto por default. En el próximo post se visualizará la utilidad de este hecho.</p>
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-64234329386950539742020-08-03T10:18:00.000-04:002020-08-03T10:18:50.826-04:00Cómo producir rejillas (grid) triangulares mediante PyQGIS 3<div style="text-align:justify;"><p>En posts pasados (<a href="http://blogdezeka.blogspot.com/2020/08/como-producir-rejillas-grid-hexagonales.html">1</a>,<a href="http://blogdezeka.blogspot.com/2020/08/cortando-una-rejilla-grid-hexagonal.html">2</a>) se consideró la manera de producir rejillas hexagonales mediante PyQGIS 3 y en este le toca el turno a las triangulares. Aunque pueda parecer extraño, a menor número de lados mayor complejidad.</p><a name='more'></a>En las hexagonales, la “distancia buffer” era igual al lado del polígono; pero esto no se cumple en las triangulares. Es lo primero que hay que resolver. Por otra parte, en la secuencia en una fila, la alternacia de triangulos exige que unos esten rotados 60 grados para que encajen; por lo que hay que implementar ésto en el código. Con relación al ajuste entre las diferentes filas, éste puede hacerse por desplazamiento. Sin embargo, esto produce una zona algo compleja en la cual las intersecciones con el área de corte produce puntos en lugar de polígonos. Esto hay que preverlo en el código para evitar errores al seleccionar los features.<br />
<br />
El código completo se presenta a continuación para producir un rejilla triangular de 8 filas por 20 columnas que comienza en el punto (355472.451507, 4474003.3953491896) y con un EPSG:32612. El punto final de corte se determina automáticamente con base al número de filas y columnas.<br />
<br />
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><table><tr><td><pre style="margin: 0; line-height: 125%"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89</pre></td><td><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">import</span> <span style="color: #0e84b5; font-weight: bold">numpy</span> <span style="color: #008800; font-weight: bold">as</span> <span style="color: #0e84b5; font-weight: bold">np</span>
sideLength <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">1000</span>
bufferLength <span style="color: #333333">=</span> sideLength<span style="color: #333333">/</span>(<span style="color: #0000DD; font-weight: bold">2</span><span style="color: #333333">*</span>np<span style="color: #333333">.</span>sin(np<span style="color: #333333">.</span>pi<span style="color: #333333">*</span><span style="color: #0000DD; font-weight: bold">60</span><span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">180</span>))
polygonSides <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">3</span>
p_init <span style="color: #333333">=</span> QgsPointXY(<span style="color: #6600EE; font-weight: bold">355472.451507</span>, <span style="color: #6600EE; font-weight: bold">4474003.3953491896</span>)
p1 <span style="color: #333333">=</span> QgsPointXY(p_init<span style="color: #333333">.</span>x()<span style="color: #333333">-</span>sideLength<span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">2</span>, p_init<span style="color: #333333">.</span>y()<span style="color: #333333">-</span>bufferLength)
points <span style="color: #333333">=</span> []
inc_x <span style="color: #333333">=</span> sideLength<span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">2</span>
inc_y <span style="color: #333333">=</span> (sideLength<span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">2</span>)<span style="color: #333333">*</span>np<span style="color: #333333">.</span>tan(np<span style="color: #333333">.</span>pi<span style="color: #333333">*</span><span style="color: #0000DD; font-weight: bold">30</span><span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">180</span>)
x <span style="color: #333333">=</span> p1<span style="color: #333333">.</span>x() <span style="color: #333333">+</span> inc_x
y <span style="color: #333333">=</span> p1<span style="color: #333333">.</span>y()
rows <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">8</span>
cols <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">20</span>
<span style="color: #008800; font-weight: bold">if</span> cols<span style="color: #333333">%</span><span style="color: #0000DD; font-weight: bold">2</span> <span style="color: #333333">==</span> <span style="color: #0000DD; font-weight: bold">0</span>:
coef <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">1</span>
<span style="color: #008800; font-weight: bold">else</span>:
coef <span style="color: #333333">=</span> <span style="color: #6600EE; font-weight: bold">1.5</span>
cols <span style="color: #333333">+=</span> <span style="color: #0000DD; font-weight: bold">1</span>
p_final <span style="color: #333333">=</span> QgsPointXY(p_init<span style="color: #333333">.</span>x() <span style="color: #333333">+</span> (cols<span style="color: #333333">+</span><span style="color: #0000DD; font-weight: bold">2</span>)<span style="color: #333333">*</span>sideLength<span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">2</span><span style="color: #333333">-</span>coef<span style="color: #333333">*</span>sideLength, p_init<span style="color: #333333">.</span>y() <span style="color: #333333">-</span> rows<span style="color: #333333">*</span>sideLength<span style="color: #333333">*</span>np<span style="color: #333333">.</span>cos(np<span style="color: #333333">.</span>pi<span style="color: #333333">*</span><span style="color: #0000DD; font-weight: bold">30</span><span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">180</span>) )
<span style="color: #008800; font-weight: bold">for</span> i <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(rows):
ver2 <span style="color: #333333">=</span> i<span style="color: #333333">%</span><span style="color: #0000DD; font-weight: bold">2</span>
<span style="color: #008800; font-weight: bold">for</span> j <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(cols<span style="color: #333333">+</span><span style="color: #0000DD; font-weight: bold">2</span>):
ver1 <span style="color: #333333">=</span> j<span style="color: #333333">%</span><span style="color: #0000DD; font-weight: bold">2</span>
point <span style="color: #333333">=</span> QgsPointXY(x, y)
points<span style="color: #333333">.</span>append(point)
x <span style="color: #333333">+=</span> inc_x
<span style="color: #008800; font-weight: bold">if</span> ver1 <span style="color: #333333">==</span> <span style="color: #0000DD; font-weight: bold">0</span>:
y <span style="color: #333333">+=</span> inc_y
<span style="color: #008800; font-weight: bold">else</span>:
y <span style="color: #333333">-=</span> inc_y
y <span style="color: #333333">-=</span> sideLength<span style="color: #333333">*</span>np<span style="color: #333333">.</span>cos(np<span style="color: #333333">.</span>pi<span style="color: #333333">*</span><span style="color: #0000DD; font-weight: bold">30</span><span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">180</span>)
<span style="color: #008800; font-weight: bold">if</span> ver2 <span style="color: #333333">==</span> <span style="color: #0000DD; font-weight: bold">0</span>:
h <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">0</span>
<span style="color: #008800; font-weight: bold">else</span>:
h <span style="color: #333333">=</span> inc_x
x <span style="color: #333333">=</span> p1<span style="color: #333333">.</span>x() <span style="color: #333333">+</span> h
epsg <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">32612</span>
uri <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"Polygon?crs=epsg:"</span> <span style="color: #333333">+</span> <span style="color: #007020">str</span>(epsg) <span style="color: #333333">+</span> <span style="background-color: #fff0f0">"&field=id:integer""&index=yes"</span>
mem_layer <span style="color: #333333">=</span> QgsVectorLayer(uri,
<span style="background-color: #fff0f0">'grid'</span>,
<span style="background-color: #fff0f0">'memory'</span>)
prov <span style="color: #333333">=</span> mem_layer<span style="color: #333333">.</span>dataProvider()
extent <span style="color: #333333">=</span> QgsRectangle(p_init, p_final)
geom_rect <span style="color: #333333">=</span> QgsGeometry<span style="color: #333333">.</span>fromRect(extent)
k<span style="color: #333333">=</span><span style="color: #0000DD; font-weight: bold">0</span>
<span style="color: #008800; font-weight: bold">for</span> i, point <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">enumerate</span>(points):
ver <span style="color: #333333">=</span> i<span style="color: #333333">%</span><span style="color: #0000DD; font-weight: bold">2</span>
geom <span style="color: #333333">=</span> QgsGeometry<span style="color: #333333">.</span>fromPolygonXY([[ QgsPointXY(point[<span style="color: #0000DD; font-weight: bold">0</span>] <span style="color: #333333">+</span> np<span style="color: #333333">.</span>sin(angle)<span style="color: #333333">*</span>bufferLength, point[<span style="color: #0000DD; font-weight: bold">1</span>] <span style="color: #333333">+</span> np<span style="color: #333333">.</span>cos(angle)<span style="color: #333333">*</span>bufferLength)
<span style="color: #008800; font-weight: bold">for</span> angle <span style="color: #000000; font-weight: bold">in</span> np<span style="color: #333333">.</span>linspace(<span style="color: #0000DD; font-weight: bold">0</span>, <span style="color: #0000DD; font-weight: bold">2</span><span style="color: #333333">*</span>np<span style="color: #333333">.</span>pi, polygonSides <span style="color: #333333">+</span> <span style="color: #0000DD; font-weight: bold">1</span>, endpoint <span style="color: #333333">=</span> <span style="color: #007020">True</span>) ]])
<span style="color: #008800; font-weight: bold">if</span> ver <span style="color: #333333">!=</span> <span style="color: #0000DD; font-weight: bold">0</span>:
geom<span style="color: #333333">.</span>rotate(<span style="color: #0000DD; font-weight: bold">60</span>,point)
<span style="color: #008800; font-weight: bold">if</span> geom<span style="color: #333333">.</span>intersects(geom_rect):
outFeat <span style="color: #333333">=</span> QgsFeature()
new_geom <span style="color: #333333">=</span> geom<span style="color: #333333">.</span>intersection(geom_rect)
<span style="color: #008800; font-weight: bold">if</span> new_geom<span style="color: #333333">.</span>wkbType() <span style="color: #333333">==</span> QgsWkbTypes<span style="color: #333333">.</span>Polygon:
outFeat<span style="color: #333333">.</span>setGeometry(new_geom)
outFeat<span style="color: #333333">.</span>setAttributes([k])
prov<span style="color: #333333">.</span>addFeatures([outFeat])
k <span style="color: #333333">+=</span> <span style="color: #0000DD; font-weight: bold">1</span>
QgsProject<span style="color: #333333">.</span>instance()<span style="color: #333333">.</span>addMapLayer(mem_layer)
</pre></td></tr></table></div><br />
Después de ejecutado en la Python Console de QGIS 3, se obtiene:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQsR-CEmUdUwicFwQlfVrOGpWzROOfu-y3yFs_5L22KtOJ8u3z_lGmDCVvhekNSMlWLnbUzQrKv2SulQ36GK7UYnT62fCsiPs4PLg6xjH9SMveQMOdx95wuvg38PeL2XDeG1_QipwZ0yY/s1600/triang_grid1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQsR-CEmUdUwicFwQlfVrOGpWzROOfu-y3yFs_5L22KtOJ8u3z_lGmDCVvhekNSMlWLnbUzQrKv2SulQ36GK7UYnT62fCsiPs4PLg6xjH9SMveQMOdx95wuvg38PeL2XDeG1_QipwZ0yY/s640/triang_grid1.png" width="640" height="384" data-original-width="1600" data-original-height="959" /></a></div><br />
<br />
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-55552618420352218022020-08-02T21:40:00.000-04:002020-08-02T21:42:59.576-04:00Cortando una rejilla (grid) hexagonal creada con PyQGIS 3<div style="text-align:justify;"><p>En el <a href="http://blogdezeka.blogspot.com/2020/08/como-producir-rejillas-grid-hexagonales.html">post anterior</a> se consideró la creación de una rejilla hexagonal. Esta contenía unos “salientes” laterales y en las partes superior e inferior de la rejilla. Además, el punto de referencia usado para su confección luce desplazado por la necesidad de encajar las filas de la manera adecuada.</p><a name='more'></a>Las modificaciones al código, además de aquellas que requieren necesariamente las nuevas clases implementadas en QGIS 3, se necesita ubicar el punto de inicio y final del corte para crear una geometría asociada a la clase <b>QgsRectangle</b>. Esta geometría se intersectará con la correspondiente a cada feature en el mismo loop de creación de la memory layer.<br />
<br />
El código completo se incluye a continuación:<br />
<br />
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><table><tr><td><pre style="margin: 0; line-height: 125%">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63</pre></td><td><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">import</span> <span style="color: #0e84b5; font-weight: bold">numpy</span> <span style="color: #008800; font-weight: bold">as</span> <span style="color: #0e84b5; font-weight: bold">np</span>
bufferLength <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">1000</span>
polygonSides <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">6</span>
inc_x <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">2</span> <span style="color: #333333">*</span> bufferLength <span style="color: #333333">*</span> np<span style="color: #333333">.</span>cos(np<span style="color: #333333">.</span>pi<span style="color: #333333">*</span><span style="color: #0000DD; font-weight: bold">30</span><span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">180</span>)
inc_y <span style="color: #333333">=</span> inc_x <span style="color: #333333">*</span> np<span style="color: #333333">.</span>cos(np<span style="color: #333333">.</span>pi<span style="color: #333333">*</span><span style="color: #0000DD; font-weight: bold">30</span><span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">180</span>)
p_init <span style="color: #333333">=</span> QgsPointXY(<span style="color: #6600EE; font-weight: bold">354972.451507</span>, <span style="color: #6600EE; font-weight: bold">4473926.04508</span>)
p1 <span style="color: #333333">=</span> QgsPointXY(p_init<span style="color: #333333">.</span>x(), p_init<span style="color: #333333">.</span>y() <span style="color: #333333">-</span> bufferLength<span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">2</span>)
points <span style="color: #333333">=</span> []
x <span style="color: #333333">=</span> p1<span style="color: #333333">.</span>x() <span style="color: #333333">+</span> inc_x<span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">2</span>
y <span style="color: #333333">=</span> p1<span style="color: #333333">.</span>y()
rows <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">8</span>
cols <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">10</span>
p_final <span style="color: #333333">=</span> QgsPointXY(p_init<span style="color: #333333">.</span>x() <span style="color: #333333">+</span> cols<span style="color: #333333">*</span>inc_x <span style="color: #333333">-</span> inc_x<span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">2</span>, p_init<span style="color: #333333">.</span>y() <span style="color: #333333">-</span> (rows<span style="color: #333333">-</span><span style="color: #0000DD; font-weight: bold">1</span>)<span style="color: #333333">*</span>inc_y <span style="color: #333333">-</span> bufferLength)
<span style="color: #008800; font-weight: bold">for</span> i <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(rows):
<span style="color: #008800; font-weight: bold">for</span> j <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(cols):
point <span style="color: #333333">=</span> QgsPointXY(x, y)
points<span style="color: #333333">.</span>append(point)
x <span style="color: #333333">+=</span> inc_x
y <span style="color: #333333">-=</span> inc_y
ver <span style="color: #333333">=</span> i<span style="color: #333333">%</span><span style="color: #0000DD; font-weight: bold">2</span>
<span style="color: #008800; font-weight: bold">if</span> ver <span style="color: #333333">==</span><span style="color: #0000DD; font-weight: bold">0</span>:
h <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">0</span>
<span style="color: #008800; font-weight: bold">else</span>:
h <span style="color: #333333">=</span> inc_x<span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">2</span>
x <span style="color: #333333">=</span> p1<span style="color: #333333">.</span>x() <span style="color: #333333">+</span> h
epsg <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">32612</span>
uri <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"Polygon?crs=epsg:"</span> <span style="color: #333333">+</span> <span style="color: #007020">str</span>(epsg) <span style="color: #333333">+</span> <span style="background-color: #fff0f0">"&field=id:integer""&index=yes"</span>
mem_layer <span style="color: #333333">=</span> QgsVectorLayer(uri,
<span style="background-color: #fff0f0">'hexgrid'</span>,
<span style="background-color: #fff0f0">'memory'</span>)
prov <span style="color: #333333">=</span> mem_layer<span style="color: #333333">.</span>dataProvider()
extent <span style="color: #333333">=</span> QgsRectangle(p_init, p_final)
geom_rect <span style="color: #333333">=</span> QgsGeometry<span style="color: #333333">.</span>fromRect(extent)
<span style="color: #008800; font-weight: bold">for</span> i, point <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">enumerate</span>(points):
outFeat <span style="color: #333333">=</span> QgsFeature()
geom <span style="color: #333333">=</span> QgsGeometry<span style="color: #333333">.</span>fromPolygonXY([[ QgsPointXY(point[<span style="color: #0000DD; font-weight: bold">0</span>] <span style="color: #333333">+</span> np<span style="color: #333333">.</span>sin(angle)<span style="color: #333333">*</span>bufferLength, point[<span style="color: #0000DD; font-weight: bold">1</span>] <span style="color: #333333">+</span> np<span style="color: #333333">.</span>cos(angle)<span style="color: #333333">*</span>bufferLength)
<span style="color: #008800; font-weight: bold">for</span> angle <span style="color: #000000; font-weight: bold">in</span> np<span style="color: #333333">.</span>linspace(<span style="color: #0000DD; font-weight: bold">0</span>, <span style="color: #0000DD; font-weight: bold">2</span><span style="color: #333333">*</span>np<span style="color: #333333">.</span>pi, polygonSides <span style="color: #333333">+</span> <span style="color: #0000DD; font-weight: bold">1</span>, endpoint <span style="color: #333333">=</span> <span style="color: #007020">True</span>) ]])
new_geom <span style="color: #333333">=</span> geom<span style="color: #333333">.</span>intersection(geom_rect)
outFeat<span style="color: #333333">.</span>setGeometry(new_geom)
outFeat<span style="color: #333333">.</span>setAttributes([i])
prov<span style="color: #333333">.</span>addFeatures([outFeat])
QgsProject<span style="color: #333333">.</span>instance()<span style="color: #333333">.</span>addMapLayer(mem_layer)
</pre></td></tr>
</table></div><br />
Después de ejecutado en la Python Console de QGIS se obtiene lo siguiente:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWmpzzDyWlI6zzVnZ1RdDWyzHMZYhUH-g12G10CPDdZncf79orX-hpBfrCW_kIDaE8Ef6NhmAQy-bBvKHMqOPwlNg6DQaB3_pORqZ9uwjRJ2cIZxkBfGp4_NCRaGvkvpZ_dCywJs4Qxsc/s1600/grid2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWmpzzDyWlI6zzVnZ1RdDWyzHMZYhUH-g12G10CPDdZncf79orX-hpBfrCW_kIDaE8Ef6NhmAQy-bBvKHMqOPwlNg6DQaB3_pORqZ9uwjRJ2cIZxkBfGp4_NCRaGvkvpZ_dCywJs4Qxsc/s640/grid2.png" width="640" height="384" data-original-width="1600" data-original-height="959" /></a></div><br />
En la imagen anterior, sólo como referencia, se incluyen los puntos inicial y final de corte. Por otra parte, la lista ‘points’ contiene todos los centroides de los hexágonos antes del corte. Si se desea, se puede conformar una memory layer de puntos con ellos.<br />
<br />
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-84166210310849059552020-08-01T00:06:00.001-04:002020-08-02T21:30:34.865-04:00Cómo producir rejillas (grid) hexagonales mediante PyQGIS 3<div style="text-align: justify;"><p>En un <a href="https://joseguerreroa.wordpress.com/2016/11/17/como-producir-rejillas-grid-hexagonales-mediante-pyqgis/">post anterior</a> se introdujo un código para producir rejillas hexagonales mediante la versión previa de PyQGIS, es decir, con Python 2. Aunque las diferencias no son muchas, puede ser abrumador tratar de hacerlo funcionar si no nos familiarizamos previamente con las nuevas clases de PyQGIS 3.</p><a name='more'></a>A diferencia de las rejillas cuadradas, el punto de comienzo (punto de referencia del primer hexágono) en las filas de los hexagonos debe ser movido, según la fila, para que se ajusten adecuadamente con la de abajo. Los desplazamientos horizontal y vertical han sido determinados con base en consideraciones geométricas de los polígonos hexagonales.<br />
<br />
El código completo, para generar una rejilla hexagonal (lado 1000 m) con 8 filas y 10 columnas (EPSG:32612), se incluye a continuación. El punto de referencia fue (354972.451507, 4473426.04508). <br />
<br />
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><table><tr><td><pre style="margin: 0; line-height: 125%">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52</pre></td><td><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">import</span> <span style="color: #0e84b5; font-weight: bold">numpy</span> <span style="color: #008800; font-weight: bold">as</span> <span style="color: #0e84b5; font-weight: bold">np</span>
bufferLength <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">1000</span>
polygonSides <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">6</span>
inc_x <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">2</span> <span style="color: #333333">*</span> bufferLength <span style="color: #333333">*</span> np<span style="color: #333333">.</span>cos(np<span style="color: #333333">.</span>pi<span style="color: #333333">*</span><span style="color: #0000DD; font-weight: bold">30</span><span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">180</span>)
inc_y <span style="color: #333333">=</span> inc_x <span style="color: #333333">*</span> np<span style="color: #333333">.</span>cos(np<span style="color: #333333">.</span>pi<span style="color: #333333">*</span><span style="color: #0000DD; font-weight: bold">30</span><span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">180</span>)
p1 <span style="color: #333333">=</span> QgsPointXY(<span style="color: #6600EE; font-weight: bold">354972.451507</span>, <span style="color: #6600EE; font-weight: bold">4473426.04508</span>)
points <span style="color: #333333">=</span> []
x <span style="color: #333333">=</span> p1<span style="color: #333333">.</span>x() <span style="color: #333333">+</span> inc_x<span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">2</span>
y <span style="color: #333333">=</span> p1<span style="color: #333333">.</span>y()
rows <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">8</span>
cols <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">10</span>
<span style="color: #008800; font-weight: bold">for</span> i <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(rows):
<span style="color: #008800; font-weight: bold">for</span> j <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(cols):
point <span style="color: #333333">=</span> QgsPointXY(x, y)
points<span style="color: #333333">.</span>append(point)
x <span style="color: #333333">+=</span> inc_x
y <span style="color: #333333">-=</span> inc_y
ver <span style="color: #333333">=</span> i<span style="color: #333333">%</span><span style="color: #0000DD; font-weight: bold">2</span>
<span style="color: #008800; font-weight: bold">if</span> ver <span style="color: #333333">==</span><span style="color: #0000DD; font-weight: bold">0</span>:
h <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">0</span>
<span style="color: #008800; font-weight: bold">else</span>:
h <span style="color: #333333">=</span> inc_x<span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">2</span>
x <span style="color: #333333">=</span> p1<span style="color: #333333">.</span>x() <span style="color: #333333">+</span> h
epsg <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">32612</span>
uri <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"Polygon?crs=epsg:"</span> <span style="color: #333333">+</span> <span style="color: #007020">str</span>(epsg) <span style="color: #333333">+</span> <span style="background-color: #fff0f0">"&field=id:integer""&index=yes"</span>
mem_layer <span style="color: #333333">=</span> QgsVectorLayer(uri,
<span style="background-color: #fff0f0">'hexgrid'</span>,
<span style="background-color: #fff0f0">'memory'</span>)
prov <span style="color: #333333">=</span> mem_layer<span style="color: #333333">.</span>dataProvider()
<span style="color: #008800; font-weight: bold">for</span> i, point <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">enumerate</span>(points):
outFeat <span style="color: #333333">=</span> QgsFeature()
outFeat<span style="color: #333333">.</span>setGeometry(QgsGeometry<span style="color: #333333">.</span>fromPolygonXY([[ QgsPointXY(point[<span style="color: #0000DD; font-weight: bold">0</span>] <span style="color: #333333">+</span> np<span style="color: #333333">.</span>sin(angle)<span style="color: #333333">*</span>bufferLength, point[<span style="color: #0000DD; font-weight: bold">1</span>] <span style="color: #333333">+</span> np<span style="color: #333333">.</span>cos(angle)<span style="color: #333333">*</span>bufferLength)
<span style="color: #008800; font-weight: bold">for</span> angle <span style="color: #000000; font-weight: bold">in</span> np<span style="color: #333333">.</span>linspace(<span style="color: #0000DD; font-weight: bold">0</span>, <span style="color: #0000DD; font-weight: bold">2</span><span style="color: #333333">*</span>np<span style="color: #333333">.</span>pi, polygonSides <span style="color: #333333">+</span> <span style="color: #0000DD; font-weight: bold">1</span>, endpoint <span style="color: #333333">=</span> <span style="color: #007020">True</span>) ]]))
outFeat<span style="color: #333333">.</span>setAttributes([i])
prov<span style="color: #333333">.</span>addFeatures([outFeat])
QgsProject<span style="color: #333333">.</span>instance()<span style="color: #333333">.</span>addMapLayer(mem_layer)
</pre></td></tr>
</table></div><br />
Después de ejecutado en la Python Console de Qgis se obtiene lo siguiente:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLSwPTj4UySaePM-yaWRIeNGiQOSlY_JrXCqCutLyErSWFCTe_t7jutAsTdkgkHTXDkiE65b9Ybbp5itSbJI4vnJLJn6MzGSfPiM5twYkYtajkVKoc-i7Bx1wfRPlqbkXj7GZG_vKzlZ0/s1600/grid1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLSwPTj4UySaePM-yaWRIeNGiQOSlY_JrXCqCutLyErSWFCTe_t7jutAsTdkgkHTXDkiE65b9Ybbp5itSbJI4vnJLJn6MzGSfPiM5twYkYtajkVKoc-i7Bx1wfRPlqbkXj7GZG_vKzlZ0/s640/grid1.png" width="640" height="384" data-original-width="1600" data-original-height="959" /></a></div><br />
En el Map Canvas de QGIS 3 se observa el punto de referencia (en rojo) usado para generar la rejilla. Sólo falta hacer más prolijo el resultado cortando la memory layer generada para evitar los trozos “salientes” por fila y columna. Además, es necesario indicar el punto de comienzo de la rejilla en lugar del punto de referencia del primer hexágono; temas del próximo post.<br />
<br />
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-58567600040945873672020-06-14T22:45:00.000-04:002020-06-14T22:45:43.461-04:00Conectando multipolígonos con líneas utilizando la distancia más corta como parámetro con PyQGIS 3<div style="text-align:justify;"><p>El ejemplo que se refiere a continuación permite conectar multipolígonos con líneas utilizando la distancia más corta como parámetro con PyQGIS 3. Es la adaptación de <a href="http://blogdezeka.blogspot.com/2020/02/conectando-multipoligonos-con-lineas.html">un código</a> que se realizó con anterioridad con PyQGIS 2. El código con PyQGIS 3 se presenta a continuación:</p><a name='more'></a><!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><table><tr><td><pre style="margin: 0; line-height: 125%"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45</pre></td><td><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">import</span> <span style="color: #0e84b5; font-weight: bold">itertools</span>
layer <span style="color: #333333">=</span> iface<span style="color: #333333">.</span>activeLayer()
feats <span style="color: #333333">=</span> [ feat <span style="color: #008800; font-weight: bold">for</span> feat <span style="color: #000000; font-weight: bold">in</span> layer<span style="color: #333333">.</span>getFeatures() ]
comb <span style="color: #333333">=</span> <span style="color: #007020">range</span>(<span style="color: #007020">len</span>(feats))
lines <span style="color: #333333">=</span> []
<span style="color: #008800; font-weight: bold">for</span> i, j <span style="color: #000000; font-weight: bold">in</span> itertools<span style="color: #333333">.</span>combinations(comb, <span style="color: #0000DD; font-weight: bold">2</span>):
d <span style="color: #333333">=</span> feats[i]<span style="color: #333333">.</span>geometry()<span style="color: #333333">.</span>distance(feats[j]<span style="color: #333333">.</span>geometry())
<span style="color: #008800; font-weight: bold">if</span> d <span style="color: #333333"><</span> <span style="color: #0000DD; font-weight: bold">14</span>:
vertices1 <span style="color: #333333">=</span> [ vertex <span style="color: #008800; font-weight: bold">for</span> vertex <span style="color: #000000; font-weight: bold">in</span> feats[i]<span style="color: #333333">.</span>geometry()<span style="color: #333333">.</span>vertices() ]
vertices2 <span style="color: #333333">=</span> [ vertex <span style="color: #008800; font-weight: bold">for</span> vertex <span style="color: #000000; font-weight: bold">in</span> feats[j]<span style="color: #333333">.</span>geometry()<span style="color: #333333">.</span>vertices() ]
dist <span style="color: #333333">=</span> []
<span style="color: #008800; font-weight: bold">for</span> k <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(<span style="color: #007020">len</span>(vertices1)):
<span style="color: #008800; font-weight: bold">for</span> l <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(<span style="color: #007020">len</span>(vertices2)):
dist<span style="color: #333333">.</span>append([k,l, vertices1[k]<span style="color: #333333">.</span>distance(vertices2[l])])
res <span style="color: #333333">=</span> [[i<span style="color: #333333">.</span>index(<span style="color: #007020">min</span>(i)), <span style="color: #007020">min</span>(i)] <span style="color: #008800; font-weight: bold">for</span> i <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">zip</span>(<span style="color: #333333">*</span>dist)][<span style="color: #0000DD; font-weight: bold">2</span>]
lines<span style="color: #333333">.</span>append([vertices1[dist[res[<span style="color: #0000DD; font-weight: bold">0</span>]][<span style="color: #0000DD; font-weight: bold">0</span>]], vertices2[dist[res[<span style="color: #0000DD; font-weight: bold">0</span>]][<span style="color: #0000DD; font-weight: bold">1</span>]]])
epsg <span style="color: #333333">=</span> layer<span style="color: #333333">.</span>crs()<span style="color: #333333">.</span>postgisSrid()
uri <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"LineString?crs=epsg:"</span> <span style="color: #333333">+</span> <span style="color: #007020">str</span>(epsg) <span style="color: #333333">+</span> <span style="background-color: #fff0f0">"&field=id:integer""&index=yes"</span>
mem_layer <span style="color: #333333">=</span> QgsVectorLayer(uri,
<span style="background-color: #fff0f0">'shortest_distances'</span>,
<span style="background-color: #fff0f0">'memory'</span>)
prov <span style="color: #333333">=</span> mem_layer<span style="color: #333333">.</span>dataProvider()
feats <span style="color: #333333">=</span> [ QgsFeature() <span style="color: #008800; font-weight: bold">for</span> i <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(<span style="color: #007020">len</span>(lines)) ]
<span style="color: #008800; font-weight: bold">for</span> i, feat <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">enumerate</span>(feats):
feat<span style="color: #333333">.</span>setAttributes([i])
feat<span style="color: #333333">.</span>setGeometry(QgsGeometry<span style="color: #333333">.</span>fromPolyline(lines[i]))
prov<span style="color: #333333">.</span>addFeatures(feats)
QgsProject<span style="color: #333333">.</span>instance()<span style="color: #333333">.</span>addMapLayer(mem_layer)
</pre></td></tr></table></div><br />
Después de ejecutado en la Python Console de QGIS 3 se obtiene, tal como se esperaba, el resultado siguiente:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFtlWclA5nww4G2oMEdiIkhrc7Rli3fLJCNPqBW8LVwY8sawSJhVXHCZv9rHbr7MiscMfZMgxRhcKnLFnPrL6XzfvV5KxLgtpvpAi1CWlL14mfXmJ1HmsllLjbim8Lsp_KuIuL5IuaMQ8/s1600/unir_polygons1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFtlWclA5nww4G2oMEdiIkhrc7Rli3fLJCNPqBW8LVwY8sawSJhVXHCZv9rHbr7MiscMfZMgxRhcKnLFnPrL6XzfvV5KxLgtpvpAi1CWlL14mfXmJ1HmsllLjbim8Lsp_KuIuL5IuaMQ8/s640/unir_polygons1.png" width="640" height="381" data-original-width="1600" data-original-height="953" /></a></div><br />
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-59298191079970494872020-06-13T00:04:00.002-04:002020-06-13T09:06:46.946-04:00Dividiendo polígonos irregulares en dos partes con diferentes proporciones y con diferente orientación de la línea de corte con PyQGIS<div style="text-align:justify;"><p>Un requerimiento común en las opciones de geoproceso es la división de polígonos irregulares en diferentes proporciones y con diferente orientación de la línea de corte. Aunque parece difícil, la opción más sencilla para realizar ésto es mediante la bounding box del polígono rotado por el ángulo correspondiente a la línea de corte para la proporción deseada.</p><a name='more'></a>Supongamos que queremos dividir un polígono en dos partes; una de ellas representa el 35 % del área total y la otra el 65 % restante. Además, hay que considerar la orientación de la línea de corte, por ejemplo, 45 grados en sentido horario.<br />
<br />
El algoritmo a emplear considera entonces la bounding box del polígono rotado con la orientación de -45 grados (los ángulos negativos corresponden a la orientación horaria en PyQGIS) y realiza el corte de la porción occidental del polígono con la proporción requerida con base en el área total de éste. Las diferencias se van corrigiendo moviendo la línea de corte de oeste a este y de este a oeste hasta lograr convergencia con base en una tolerancia < 1x10<sup>-5</sup> % con base en el área total. Un procedimiento similar es realizado con la porción oriental y las dos partes resultantes se combinan en una memory layer con los dos rasgos correspondientes. Es lo que refleja el código que se presenta a continuación: <br />
<br />
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><table><tr><td><pre style="margin: 0; line-height: 125%"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140</pre></td><td><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">import</span> <span style="color: #0e84b5; font-weight: bold">math</span>
registry <span style="color: #333333">=</span> QgsProject<span style="color: #333333">.</span>instance()
<span style="color: #888888">#layer = registry.mapLayersByName('polygon1')</span>
layer <span style="color: #333333">=</span> registry<span style="color: #333333">.</span>mapLayersByName(<span style="background-color: #fff0f0">'polygon2'</span>)
angle <span style="color: #333333">=</span> <span style="color: #333333">-</span><span style="color: #0000DD; font-weight: bold">45</span>
feats <span style="color: #333333">=</span> [ feat <span style="color: #008800; font-weight: bold">for</span> feat <span style="color: #000000; font-weight: bold">in</span> layer[<span style="color: #0000DD; font-weight: bold">0</span>]<span style="color: #333333">.</span>getFeatures() ]
pol_geom <span style="color: #333333">=</span> feats[<span style="color: #0000DD; font-weight: bold">0</span>]<span style="color: #333333">.</span>geometry()
area <span style="color: #333333">=</span> pol_geom<span style="color: #333333">.</span>area()
area2 <span style="color: #333333">=</span> pol_geom<span style="color: #333333">.</span>area()
pt <span style="color: #333333">=</span> pol_geom<span style="color: #333333">.</span>centroid()<span style="color: #333333">.</span>asPoint()
pol_geom<span style="color: #333333">.</span>rotate(angle, pt)
bbox <span style="color: #333333">=</span> pol_geom<span style="color: #333333">.</span>boundingBox()
pol <span style="color: #333333">=</span> bbox<span style="color: #333333">.</span>asWktPolygon()
xmin <span style="color: #333333">=</span> bbox<span style="color: #333333">.</span>xMinimum()
xmax <span style="color: #333333">=</span> bbox<span style="color: #333333">.</span>xMaximum()
ymin <span style="color: #333333">=</span> bbox<span style="color: #333333">.</span>yMinimum()
ymax <span style="color: #333333">=</span> bbox<span style="color: #333333">.</span>yMaximum()
xmean <span style="color: #333333">=</span> (xmin <span style="color: #333333">+</span> xmax)<span style="color: #333333">/</span><span style="color: #6600EE; font-weight: bold">2.</span>
xmean2 <span style="color: #333333">=</span> (xmin <span style="color: #333333">+</span> xmax)<span style="color: #333333">/</span><span style="color: #6600EE; font-weight: bold">2.</span>
width <span style="color: #333333">=</span> bbox<span style="color: #333333">.</span>width()
increment2 <span style="color: #333333">=</span> width<span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">20</span>
xold2 <span style="color: #333333">=</span> xmean2
new_area2 <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">0</span>
old_area2 <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">0</span>
width <span style="color: #333333">=</span> bbox<span style="color: #333333">.</span>width()
increment <span style="color: #333333">=</span> width<span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">20</span>
xold <span style="color: #333333">=</span> xmean
n <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">1</span>
new_area <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">0</span>
old_area <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">0</span>
int1 <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">0</span>
int2 <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">0</span>
<span style="color: #008800; font-weight: bold">while</span>(n <span style="color: #333333">></span> <span style="color: #0000DD; font-weight: bold">0</span>):
left_half <span style="color: #333333">=</span> QgsRectangle(xmin, ymin, xmean, ymax)<span style="color: #333333">.</span>asWktPolygon()
left_half_geom <span style="color: #333333">=</span> QgsGeometry<span style="color: #333333">.</span>fromWkt(left_half)
half_intersect <span style="color: #333333">=</span> left_half_geom<span style="color: #333333">.</span>intersection(pol_geom)
half_intersect_area <span style="color: #333333">=</span> half_intersect<span style="color: #333333">.</span>area()
right_half <span style="color: #333333">=</span> QgsRectangle(xmean2, ymin, xmax, ymax)<span style="color: #333333">.</span>asWktPolygon()
right_half_geom <span style="color: #333333">=</span> QgsGeometry<span style="color: #333333">.</span>fromWkt(right_half)
half_intersect2 <span style="color: #333333">=</span> right_half_geom<span style="color: #333333">.</span>intersection(pol_geom)
half_intersect_area2 <span style="color: #333333">=</span> half_intersect2<span style="color: #333333">.</span>area()
<span style="color: #008800; font-weight: bold">if</span> n <span style="color: #333333">==</span> <span style="color: #0000DD; font-weight: bold">500</span>:
<span style="color: #008800; font-weight: bold">break</span>
<span style="color: #008800; font-weight: bold">if</span> int1 <span style="color: #333333">==</span> <span style="color: #0000DD; font-weight: bold">1</span> <span style="color: #000000; font-weight: bold">and</span> int2 <span style="color: #333333">==</span> <span style="color: #0000DD; font-weight: bold">1</span>:
<span style="color: #008800; font-weight: bold">break</span>
fact <span style="color: #333333">=</span> <span style="color: #6600EE; font-weight: bold">0.35</span>
fact2 <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">1</span> <span style="color: #333333">-</span> fact
<span style="color: #008800; font-weight: bold">if</span> area<span style="color: #333333">*</span>fact <span style="color: #333333">></span> half_intersect_area <span style="color: #000000; font-weight: bold">and</span> int1 <span style="color: #333333">==</span> <span style="color: #0000DD; font-weight: bold">0</span>:
xold <span style="color: #333333">=</span> xmean
xmean <span style="color: #333333">+=</span> increment
old_area <span style="color: #333333">=</span> half_intersect_area
var <span style="color: #333333">=</span> new_area<span style="color: #333333">-</span>old_area
<span style="color: #008800; font-weight: bold">if</span> area<span style="color: #333333">*</span>fact <span style="color: #333333"><</span> half_intersect_area <span style="color: #000000; font-weight: bold">and</span> int1 <span style="color: #333333">==</span> <span style="color: #0000DD; font-weight: bold">0</span>:
xmean <span style="color: #333333">=</span> xold
increment <span style="color: #333333">=</span> increment<span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">2</span>
new_area <span style="color: #333333">=</span> half_intersect_area
var <span style="color: #333333">=</span> new_area<span style="color: #333333">-</span>old_area
<span style="color: #008800; font-weight: bold">if</span> new_area<span style="color: #333333">-</span>old_area <span style="color: #333333"><</span> <span style="color: #6600EE; font-weight: bold">1e-5</span>:
int1 <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">1</span>
<span style="color: #008800; font-weight: bold">if</span> int1 <span style="color: #333333">==</span> <span style="color: #0000DD; font-weight: bold">1</span>:
<span style="color: #008800; font-weight: bold">print</span>(<span style="background-color: #fff0f0">"error1"</span>, new_area<span style="color: #333333">-</span>old_area)
<span style="color: #008800; font-weight: bold">if</span> n <span style="color: #333333">==</span> <span style="color: #0000DD; font-weight: bold">1</span> <span style="color: #000000; font-weight: bold">and</span> var <span style="color: #333333">></span> <span style="color: #0000DD; font-weight: bold">0</span> <span style="color: #000000; font-weight: bold">and</span> int1 <span style="color: #333333">==</span> <span style="color: #0000DD; font-weight: bold">0</span>:
xmean <span style="color: #333333">=</span> xmin <span style="color: #333333">+</span> increment
<span style="color: #008800; font-weight: bold">if</span> area2<span style="color: #333333">*</span>fact2 <span style="color: #333333">></span> half_intersect_area2 <span style="color: #000000; font-weight: bold">and</span> int2 <span style="color: #333333">==</span> <span style="color: #0000DD; font-weight: bold">0</span>:
xold2 <span style="color: #333333">=</span> xmean2
xmean2 <span style="color: #333333">-=</span> increment2
old_area2 <span style="color: #333333">=</span> half_intersect_area2
var2 <span style="color: #333333">=</span> new_area2<span style="color: #333333">-</span>old_area2
<span style="color: #008800; font-weight: bold">if</span> area2<span style="color: #333333">*</span>fact2 <span style="color: #333333"><</span> half_intersect_area2 <span style="color: #000000; font-weight: bold">and</span> int2 <span style="color: #333333">==</span> <span style="color: #0000DD; font-weight: bold">0</span>:
xmean2 <span style="color: #333333">=</span> xold2
increment2 <span style="color: #333333">=</span> increment2<span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">2</span>
new_area2 <span style="color: #333333">=</span> half_intersect_area2
var2 <span style="color: #333333">=</span> new_area2<span style="color: #333333">-</span>old_area2
<span style="color: #008800; font-weight: bold">if</span> new_area2<span style="color: #333333">-</span>old_area2 <span style="color: #333333"><</span> <span style="color: #6600EE; font-weight: bold">1e-5</span>:
int2 <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">1</span>
<span style="color: #008800; font-weight: bold">if</span> int2 <span style="color: #333333">==</span> <span style="color: #0000DD; font-weight: bold">1</span>:
<span style="color: #008800; font-weight: bold">print</span>(<span style="background-color: #fff0f0">"error2"</span>, new_area2<span style="color: #333333">-</span>old_area2)
<span style="color: #008800; font-weight: bold">if</span> n <span style="color: #333333">==</span> <span style="color: #0000DD; font-weight: bold">1</span> <span style="color: #000000; font-weight: bold">and</span> var2 <span style="color: #333333">></span> <span style="color: #0000DD; font-weight: bold">0</span> <span style="color: #000000; font-weight: bold">and</span> int2 <span style="color: #333333">==</span> <span style="color: #0000DD; font-weight: bold">0</span>:
xmean2 <span style="color: #333333">=</span> xmax <span style="color: #333333">-</span> increment2
n <span style="color: #333333">+=</span> <span style="color: #0000DD; font-weight: bold">1</span>
geoms <span style="color: #333333">=</span> []
new_geom <span style="color: #333333">=</span> QgsGeometry<span style="color: #333333">.</span>fromWkt(half_intersect<span style="color: #333333">.</span>asWkt())
new_geom<span style="color: #333333">.</span>rotate(<span style="color: #333333">-</span>angle, pt)
geoms<span style="color: #333333">.</span>append(new_geom)
new_geom2 <span style="color: #333333">=</span> QgsGeometry<span style="color: #333333">.</span>fromWkt(half_intersect2<span style="color: #333333">.</span>asWkt())
new_geom2<span style="color: #333333">.</span>rotate(<span style="color: #333333">-</span>angle, pt)
geoms<span style="color: #333333">.</span>append(new_geom2)
epsg <span style="color: #333333">=</span> layer[<span style="color: #0000DD; font-weight: bold">0</span>]<span style="color: #333333">.</span>crs()<span style="color: #333333">.</span>postgisSrid()
uri <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"Polygon?crs=epsg:"</span> <span style="color: #333333">+</span> <span style="color: #007020">str</span>(epsg) <span style="color: #333333">+</span> <span style="background-color: #fff0f0">"&field=id:integer""&index=yes"</span>
mem_layer <span style="color: #333333">=</span> QgsVectorLayer(uri,
<span style="background-color: #fff0f0">'divided_polygon'</span>,
<span style="background-color: #fff0f0">'memory'</span>)
prov <span style="color: #333333">=</span> mem_layer<span style="color: #333333">.</span>dataProvider()
feats <span style="color: #333333">=</span> [ QgsFeature() <span style="color: #008800; font-weight: bold">for</span> i <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(<span style="color: #007020">len</span>(geoms)) ]
<span style="color: #008800; font-weight: bold">for</span> i, feat <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">enumerate</span>(feats):
feat<span style="color: #333333">.</span>setAttributes([i])
feat<span style="color: #333333">.</span>setGeometry(geoms[i])
prov<span style="color: #333333">.</span>addFeatures(feats)
registry<span style="color: #333333">.</span>addMapLayer(mem_layer)
</pre></td></tr>
</table></div><br />
Después de ejecutado el código anterior en la Python Console de QGIS el polígono original muestra el resultado a continuación. Ha sido dividido en dos partes. La occidental representa el 35 % del área total y la oriental el 65 %. La orientación de la línea de corte corresponde a 45 grados; tal como se esperaba. <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKcuSK5az46tEZvOsW6orpfZFWIrzY8c5dAjpUiDeoLHgDgKon_Vvu7YPOTGgQneb2PdMJL7I6sSItbAbGQhYfoSkVOupwZJe_IUKGwvrtraV-j4DhyphenhyphenNiib0S1Ecc0oYK-efyilq4wyJU/s1600/divided1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKcuSK5az46tEZvOsW6orpfZFWIrzY8c5dAjpUiDeoLHgDgKon_Vvu7YPOTGgQneb2PdMJL7I6sSItbAbGQhYfoSkVOupwZJe_IUKGwvrtraV-j4DhyphenhyphenNiib0S1Ecc0oYK-efyilq4wyJU/s640/divided1.png" width="640" height="381" data-original-width="1600" data-original-height="953" /></a></div><br />
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-8428437050828476632020-02-27T09:50:00.000-04:002020-02-27T09:50:40.547-04:00Conectando multipolígonos con líneas utilizando la distancia más corta como parámetro con PyQGIS 2<div style="text-align:justify;"><p>A pesar de que QGIS 2 ya no tiene mantenimiento en versiones de esta rama, todavía existen usuarios que se niegan a actualizar a QGIS 3 para no tener que adaptar el código ya desarrollado para que funcione en QGIS 3. El ejemplo que se refiere a continuación permite conectar multipolígonos con líneas utilizando la distancia más corta como parámetro con PyQGIS 2. Difiere en varias líneas de código del que se desarrolló también para PyQGIS 3 con el mismo fin (que se incluirá, Dios mediante, en un post futuro). Se presenta a continuación:</p><a name='more'></a><!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><table><tr><td><pre style="margin: 0; line-height: 125%"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46</pre></td><td><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">import</span> <span style="color: #0e84b5; font-weight: bold">itertools</span>
layer <span style="color: #333333">=</span> iface<span style="color: #333333">.</span>activeLayer()
feats <span style="color: #333333">=</span> [ feat <span style="color: #008800; font-weight: bold">for</span> feat <span style="color: #000000; font-weight: bold">in</span> layer<span style="color: #333333">.</span>getFeatures() ]
comb <span style="color: #333333">=</span> <span style="color: #007020">range</span>(<span style="color: #007020">len</span>(feats))
lines <span style="color: #333333">=</span> []
<span style="color: #008800; font-weight: bold">for</span> i, j <span style="color: #000000; font-weight: bold">in</span> itertools<span style="color: #333333">.</span>combinations(comb, <span style="color: #0000DD; font-weight: bold">2</span>):
d <span style="color: #333333">=</span> feats[i]<span style="color: #333333">.</span>geometry()<span style="color: #333333">.</span>distance(feats[j]<span style="color: #333333">.</span>geometry())
<span style="color: #008800; font-weight: bold">if</span> d <span style="color: #333333"><</span> <span style="color: #0000DD; font-weight: bold">14</span>:
<span style="color: #008800; font-weight: bold">print</span>(d)
vertices1 <span style="color: #333333">=</span> feats[i]<span style="color: #333333">.</span>geometry()<span style="color: #333333">.</span>asPolygon()[<span style="color: #0000DD; font-weight: bold">0</span>]
vertices2 <span style="color: #333333">=</span> feats[j]<span style="color: #333333">.</span>geometry()<span style="color: #333333">.</span>asPolygon()[<span style="color: #0000DD; font-weight: bold">0</span>]
dist <span style="color: #333333">=</span> []
<span style="color: #008800; font-weight: bold">for</span> k <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(<span style="color: #007020">len</span>(vertices1)):
<span style="color: #008800; font-weight: bold">for</span> l <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(<span style="color: #007020">len</span>(vertices2)):
dist<span style="color: #333333">.</span>append([k,l, QgsPoint(vertices1[k])<span style="color: #333333">.</span>distance(QgsPoint(vertices2[l]))])
res <span style="color: #333333">=</span> [[i<span style="color: #333333">.</span>index(<span style="color: #007020">min</span>(i)), <span style="color: #007020">min</span>(i)] <span style="color: #008800; font-weight: bold">for</span> i <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">zip</span>(<span style="color: #333333">*</span>dist)][<span style="color: #0000DD; font-weight: bold">2</span>]
lines<span style="color: #333333">.</span>append([vertices1[dist[res[<span style="color: #0000DD; font-weight: bold">0</span>]][<span style="color: #0000DD; font-weight: bold">0</span>]], vertices2[dist[res[<span style="color: #0000DD; font-weight: bold">0</span>]][<span style="color: #0000DD; font-weight: bold">1</span>]]])
epsg <span style="color: #333333">=</span> layer<span style="color: #333333">.</span>crs()<span style="color: #333333">.</span>postgisSrid()
uri <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"LineString?crs=epsg:"</span> <span style="color: #333333">+</span> <span style="color: #007020">str</span>(epsg) <span style="color: #333333">+</span> <span style="background-color: #fff0f0">"&field=id:integer""&index=yes"</span>
mem_layer <span style="color: #333333">=</span> QgsVectorLayer(uri,
<span style="background-color: #fff0f0">'shortest_distances'</span>,
<span style="background-color: #fff0f0">'memory'</span>)
prov <span style="color: #333333">=</span> mem_layer<span style="color: #333333">.</span>dataProvider()
feats <span style="color: #333333">=</span> [ QgsFeature() <span style="color: #008800; font-weight: bold">for</span> i <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(<span style="color: #007020">len</span>(lines)) ]
<span style="color: #008800; font-weight: bold">for</span> i, feat <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">enumerate</span>(feats):
feat<span style="color: #333333">.</span>setAttributes([i])
feat<span style="color: #333333">.</span>setGeometry(QgsGeometry<span style="color: #333333">.</span>fromPolyline(lines[i]))
prov<span style="color: #333333">.</span>addFeatures(feats)
QgsMapLayerRegistry<span style="color: #333333">.</span>instance()<span style="color: #333333">.</span>addMapLayer(mem_layer)
</pre></td></tr></table></div><br />
La distancia umbral es de 14 metros y se probó con la capa vectorial que se presenta en la imagen siguiente; donde también se observan las líneas generadas con la ejecución del script anterior en la Python Console de QGIS 2.18.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyI9qEZ35EQK5IR8AIflG9TSlyFQC5up41IQ1jh7KNotyjDrvzjrhIRFotgyrvPfo7nRx1R2zYweMt-dRcKImxPj7JjFBDghQi1VB2RMokXjFbciRjE9fUTx66arjgQdn4h1wpEmtr6LI/s1600/distance2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyI9qEZ35EQK5IR8AIflG9TSlyFQC5up41IQ1jh7KNotyjDrvzjrhIRFotgyrvPfo7nRx1R2zYweMt-dRcKImxPj7JjFBDghQi1VB2RMokXjFbciRjE9fUTx66arjgQdn4h1wpEmtr6LI/s640/distance2.png" width="640" height="385" data-original-width="1600" data-original-height="962" /></a></div><br />
<br />
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-83645502497053701142020-01-27T17:43:00.001-04:002020-01-27T17:43:55.340-04:00Clase plantilla con QDialog que contiene función para producir polilíneas a partir de rasgos adyacentes seleccionados <div style="text-align:justify;"><p>En posts anteriores (<a href="https://joseguerreroa.wordpress.com/2015/11/02/plugin-de-qgis-para-determinar-fronteras-como-multipolilineas/">1</a>, <a href="https://joseguerreroa.wordpress.com/2015/10/16/interseccion-de-rasgos-features-adyacentes-de-poligonos-en-pyqgis/">2</a>) se consideró la intersección de rasgos (features) adyacentes de polígonos seleccionados en PyQGIS para crear un plugin de QGIS 2 que permitiera generar las fronteras comunes como multipolilíneas. En éste se adaptó el código allí propuesto para que pudiese funcionar en QGIS 3 y generar un <b>QDialog</b>, con sus elementos Qt equivalentes, en una clase personalizada que se ejecuta desde la Python Console.</p><a name='more'></a>Se descubrió, además, que el referido código no funcionaba adecuadamente con los polígonos de los estados Arizona, Colorado, Nuevo México y Utah de USA, porque contiene un punto de unión cuádruple que genera dos puntos (no polilíneas) para la selección de dos rásgos adyacentes. Aunque se corrigió la falta de funcionalidad no se añadió como excepción. <br />
<br />
El código producido se incluye a continuación:<br />
<br />
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><table><tr><td><pre style="margin: 0; line-height: 125%"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102</pre></td><td><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtCore</span> <span style="color: #008800; font-weight: bold">import</span> Qt
<span style="color: #008800; font-weight: bold">import</span> <span style="color: #0e84b5; font-weight: bold">itertools</span>
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">Dlg</span>(QDialog):
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">__init__</span>(<span style="color: #007020">self</span>):
QDialog<span style="color: #333333">.</span>__init__(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout <span style="color: #333333">=</span> QGridLayout(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>label1 <span style="color: #333333">=</span> QLabel(<span style="background-color: #fff0f0">'Select polygon layer: '</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>wcb <span style="color: #333333">=</span> QgsMapLayerComboBox()
<span style="color: #007020">self</span><span style="color: #333333">.</span>wcb<span style="color: #333333">.</span>setFixedWidth(<span style="color: #0000DD; font-weight: bold">200</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>btn1 <span style="color: #333333">=</span> QPushButton(<span style="background-color: #fff0f0">'OK'</span>, <span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>btn1<span style="color: #333333">.</span>setFixedWidth(<span style="color: #0000DD; font-weight: bold">50</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>label1, <span style="color: #0000DD; font-weight: bold">0</span>, <span style="color: #0000DD; font-weight: bold">0</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>wcb, <span style="color: #0000DD; font-weight: bold">0</span>, <span style="color: #0000DD; font-weight: bold">1</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>btn1, <span style="color: #0000DD; font-weight: bold">1</span>, <span style="color: #0000DD; font-weight: bold">1</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>btn1<span style="color: #333333">.</span>clicked<span style="color: #333333">.</span>connect(<span style="color: #007020">self</span><span style="color: #333333">.</span>borders_features)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">borders_features</span>(<span style="color: #007020">self</span>):
layer <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>wcb<span style="color: #333333">.</span>currentLayer()
<span style="color: #008800; font-weight: bold">try</span>:
features <span style="color: #333333">=</span> layer<span style="color: #333333">.</span>selectedFeatures()
<span style="color: #007020">list</span> <span style="color: #333333">=</span> <span style="color: #007020">range</span>(<span style="color: #007020">len</span>(features))
types <span style="color: #333333">=</span> [ features[i]<span style="color: #333333">.</span>geometry()<span style="color: #333333">.</span>intersection(features[j]<span style="color: #333333">.</span>geometry())<span style="color: #333333">.</span>type()
<span style="color: #008800; font-weight: bold">for</span> i,j <span style="color: #000000; font-weight: bold">in</span> itertools<span style="color: #333333">.</span>combinations(<span style="color: #007020">list</span>, <span style="color: #0000DD; font-weight: bold">2</span>)
<span style="color: #008800; font-weight: bold">if</span> features[i]<span style="color: #333333">.</span>geometry()<span style="color: #333333">.</span>intersects(features[j]<span style="color: #333333">.</span>geometry()) ]
intersections <span style="color: #333333">=</span> [ features[i]<span style="color: #333333">.</span>geometry()<span style="color: #333333">.</span>intersection(features[j]<span style="color: #333333">.</span>geometry())<span style="color: #333333">.</span>asWkt()
<span style="color: #008800; font-weight: bold">for</span> i,j <span style="color: #000000; font-weight: bold">in</span> itertools<span style="color: #333333">.</span>combinations(<span style="color: #007020">list</span>, <span style="color: #0000DD; font-weight: bold">2</span>)
<span style="color: #008800; font-weight: bold">if</span> features[i]<span style="color: #333333">.</span>geometry()<span style="color: #333333">.</span>intersects(features[j]<span style="color: #333333">.</span>geometry()) ]
n <span style="color: #333333">=</span> <span style="color: #007020">len</span>(intersections)
<span style="color: #008800; font-weight: bold">if</span> n <span style="color: #333333">==</span> <span style="color: #0000DD; font-weight: bold">0</span>:
iface<span style="color: #333333">.</span>messageBar()<span style="color: #333333">.</span>pushMessage(<span style="background-color: #fff0f0">"Warning: "</span>,
<span style="background-color: #fff0f0">"There is not adjacent selected features"</span>,
Qgis<span style="color: #333333">.</span>Warning, <span style="color: #0000DD; font-weight: bold">5</span>)
<span style="color: #008800; font-weight: bold">return</span>
<span style="color: #888888">#creating a memory layer for multilinestring</span>
crs <span style="color: #333333">=</span> layer<span style="color: #333333">.</span>crs()
epsg <span style="color: #333333">=</span> crs<span style="color: #333333">.</span>postgisSrid()
<span style="color: #008800; font-weight: bold">if</span> crs<span style="color: #333333">.</span>isGeographic() <span style="color: #000000; font-weight: bold">is</span> <span style="color: #007020">False</span>:
string <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"length_m"</span>
<span style="color: #008800; font-weight: bold">else</span>:
string <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"length_km"</span>
uri <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"MultiLineString?crs=epsg:"</span> <span style="color: #333333">+</span> <span style="color: #007020">str</span>(epsg) <span style="color: #333333">+</span> <span style="background-color: #fff0f0">"&field=id:integer&field="</span> <span style="color: #333333">+</span> string <span style="color: #333333">+</span> <span style="background-color: #fff0f0">":double""&index=yes"</span>
mem_layer <span style="color: #333333">=</span> QgsVectorLayer(uri,
<span style="background-color: #fff0f0">"multipolyline"</span>,
<span style="background-color: #fff0f0">"memory"</span>)
QgsProject<span style="color: #333333">.</span>instance()<span style="color: #333333">.</span>addMapLayer(mem_layer)
mem_layer<span style="color: #333333">.</span>startEditing()
<span style="color: #888888">#Set features</span>
feature <span style="color: #333333">=</span> [QgsFeature() <span style="color: #008800; font-weight: bold">for</span> i <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(n)]
k <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">0</span>
dao <span style="color: #333333">=</span> QgsDistanceArea()
dao<span style="color: #333333">.</span>setEllipsoid(<span style="background-color: #fff0f0">'WGS84'</span>)
<span style="color: #008800; font-weight: bold">for</span> i <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(n):
<span style="color: #008800; font-weight: bold">if</span> types[i] <span style="color: #333333">==</span> <span style="color: #0000DD; font-weight: bold">1</span>:
<span style="color: #888888">#set geometry</span>
geom <span style="color: #333333">=</span> QgsGeometry<span style="color: #333333">.</span>fromWkt(intersections[i])
<span style="color: #008800; font-weight: bold">if</span> crs<span style="color: #333333">.</span>isGeographic() <span style="color: #000000; font-weight: bold">is</span> <span style="color: #007020">False</span>:
l <span style="color: #333333">=</span> geom<span style="color: #333333">.</span>length()
<span style="color: #008800; font-weight: bold">else</span>:
l <span style="color: #333333">=</span> dao<span style="color: #333333">.</span>measureLength(geom)<span style="color: #333333">/</span><span style="color: #0000DD; font-weight: bold">1000</span>
feature[i]<span style="color: #333333">.</span>setGeometry(geom)
<span style="color: #888888">#set attributes values</span>
feature[i]<span style="color: #333333">.</span>setAttributes([k, l])
mem_layer<span style="color: #333333">.</span>addFeature(feature[i])
k <span style="color: #333333">+=</span> <span style="color: #0000DD; font-weight: bold">1</span>
<span style="color: #888888">#stop editing and save changes</span>
mem_layer<span style="color: #333333">.</span>commitChanges()
<span style="color: #008800; font-weight: bold">except</span> <span style="color: #FF0000; font-weight: bold">AttributeError</span>:
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>messageBar()<span style="color: #333333">.</span>pushMessage(<span style="background-color: #fff0f0">"Warning: "</span>,
<span style="background-color: #fff0f0">"There is not adjacent selected features"</span>,
Qgis<span style="color: #333333">.</span>Warning, <span style="color: #0000DD; font-weight: bold">5</span>)
<span style="color: #008800; font-weight: bold">return</span>
w <span style="color: #333333">=</span> Dlg()
w<span style="color: #333333">.</span>setWindowTitle(<span style="background-color: #fff0f0">'Borders Features'</span>)
w<span style="color: #333333">.</span>setWindowFlags(Qt<span style="color: #333333">.</span>WindowStaysOnTopHint)
w<span style="color: #333333">.</span>move(<span style="color: #0000DD; font-weight: bold">300</span>,<span style="color: #0000DD; font-weight: bold">200</span>)
w<span style="color: #333333">.</span>show()
</pre></td></tr></table></div><br />
Se probó con el shapefile ya mencionado seleccionando los cuatro estados; tal como se aprecia en la imagen siguiente:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSYSaPhf7RMiw_QykDsxG7DA1Bdr28l5FWlONkaKsKDgEcf-I4JvRSh7y7O1rk12apFjhUhD05MSItOIEOdKmBM0LIa5Z_7a7tp5tXilpajzg-RQBzliEsVmUVzerKggxwBaPkYByfHPg/s1600/features1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSYSaPhf7RMiw_QykDsxG7DA1Bdr28l5FWlONkaKsKDgEcf-I4JvRSh7y7O1rk12apFjhUhD05MSItOIEOdKmBM0LIa5Z_7a7tp5tXilpajzg-RQBzliEsVmUVzerKggxwBaPkYByfHPg/s640/features1.png" width="640" height="390" data-original-width="1600" data-original-height="975" /></a></div><br />
Después de ejecutado el código anterior en la Python Console de QGIS, se puede observar en la imagen a continuación las cuatro líneas producidas. La tabla de atributos incluye adicionalmente la longitud, en kilómetros, de éstas.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5gi_7ZoduLTyVwr9bt1ZwZ-rqiQ1Ot9r4-r0sTjex5FY-lJdbANMxLd4MKimaWhnQwneZE7aYicDUQiyosr8iRyv3ioWUa1LOGScnHrm3JofLeAK6erVQypjjjY9eiP1yvoiDNRjDHIo/s1600/features2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5gi_7ZoduLTyVwr9bt1ZwZ-rqiQ1Ot9r4-r0sTjex5FY-lJdbANMxLd4MKimaWhnQwneZE7aYicDUQiyosr8iRyv3ioWUa1LOGScnHrm3JofLeAK6erVQypjjjY9eiP1yvoiDNRjDHIo/s640/features2.png" width="640" height="390" data-original-width="1600" data-original-height="974" /></a></div><br />
<br />
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-67667137670125563212020-01-25T11:14:00.000-04:002020-01-25T11:14:10.485-04:00Cómo producir buffers, alrededor de puntos, con diferente número de lados en PyQGIS 3<div style="text-align:justify;"><p>En un <a href="https://joseguerreroa.wordpress.com/2016/11/16/como-producir-buffers-alrededor-de-puntos-con-diferentes-numeros-de-lados-en-pyqgis/">post anterior</a> se consideró la producción de buffers, alrededor de puntos, con diferente número de lados en la antigua versión de QGIS. En éste toca modificar el script allí propuesto para que pueda funcionar con PyQGIS 3. Las modificaciones incluyen un sólo punto con proyección EPSG 32612 y una distancia buffer de 1000 metros. Los métodos de clase ahora empleados y que han cambiado con respecto a la versión anterior corresponden a <b>QgsGeometry</b>, <b>QgsPointXY</b> y <b>QgsQgsProject</b>. El script propuesto se encuentra a continuación:</p><a name='more'></a><!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><table><tr><td><pre style="margin: 0; line-height: 125%"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29</pre></td><td><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">import</span> <span style="color: #0e84b5; font-weight: bold">numpy</span> <span style="color: #008800; font-weight: bold">as</span> <span style="color: #0e84b5; font-weight: bold">np</span>
bufferLength <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">1000</span>
polygonSides <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">5</span>
pt <span style="color: #333333">=</span> QgsPointXY(<span style="color: #6600EE; font-weight: bold">364067.6920850627</span>, <span style="color: #6600EE; font-weight: bold">4426289.212155256</span>)
points <span style="color: #333333">=</span> [ pt ]
epsg <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">32612</span>
uri <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"Polygon?crs=epsg:"</span> <span style="color: #333333">+</span> <span style="color: #007020">str</span>(epsg) <span style="color: #333333">+</span> <span style="background-color: #fff0f0">"&field=id:integer""&index=yes"</span>
mem_layer <span style="color: #333333">=</span> QgsVectorLayer(uri,
<span style="background-color: #fff0f0">'buffer'</span>,
<span style="background-color: #fff0f0">'memory'</span>)
prov <span style="color: #333333">=</span> mem_layer<span style="color: #333333">.</span>dataProvider()
<span style="color: #008800; font-weight: bold">for</span> i, point <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">enumerate</span>(points):
outFeat <span style="color: #333333">=</span> QgsFeature()
outFeat<span style="color: #333333">.</span>setGeometry(QgsGeometry<span style="color: #333333">.</span>fromPolygonXY([[ QgsPointXY(point[<span style="color: #0000DD; font-weight: bold">0</span>] <span style="color: #333333">+</span> np<span style="color: #333333">.</span>sin(angle)<span style="color: #333333">*</span>bufferLength, point[<span style="color: #0000DD; font-weight: bold">1</span>] <span style="color: #333333">+</span> np<span style="color: #333333">.</span>cos(angle)<span style="color: #333333">*</span>bufferLength)
<span style="color: #008800; font-weight: bold">for</span> angle <span style="color: #000000; font-weight: bold">in</span> np<span style="color: #333333">.</span>linspace(<span style="color: #0000DD; font-weight: bold">0</span>, <span style="color: #0000DD; font-weight: bold">2</span><span style="color: #333333">*</span>np<span style="color: #333333">.</span>pi, polygonSides, endpoint <span style="color: #333333">=</span> <span style="color: #007020">False</span>) ]]))
outFeat<span style="color: #333333">.</span>setAttributes([i])
prov<span style="color: #333333">.</span>addFeatures([outFeat])
QgsProject<span style="color: #333333">.</span>instance()<span style="color: #333333">.</span>addMapLayer(mem_layer)
</pre></td></tr></table></div><br />
Después de ejecutado en la Python Console de QGIS, el resultado se observa en la imagen siguiente:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8jubzcnv6KgF8l-uh-AaiR9H6-A6kbAYnSTweabRjik7prmEMJc6q-0Yw-okwyartNIx29GESsk9N0szE1f4NtNiYF_8tKTWPBsxOs56tySfOtGoz41n5p0nBU_o5LTAbKHxRPGdAc7A/s1600/buffer1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8jubzcnv6KgF8l-uh-AaiR9H6-A6kbAYnSTweabRjik7prmEMJc6q-0Yw-okwyartNIx29GESsk9N0szE1f4NtNiYF_8tKTWPBsxOs56tySfOtGoz41n5p0nBU_o5LTAbKHxRPGdAc7A/s640/buffer1.png" width="640" height="381" data-original-width="1600" data-original-height="953" /></a></div><br />
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-24340860760476306902020-01-21T08:57:00.001-04:002020-01-21T08:57:57.943-04:00Clase plantilla con QDialog para usar segundo tab de un QTabWidget como contenedor de un QTableWidget para desplegar nombres de campos de capas vectoriales en QGIS 3<div style="text-align:justify;"><p>En el <a href="https://blogdezeka.blogspot.com/2020/01/clase-plantilla-con-qdialog-para-usar.html">post anterior</a> se propuso una clase plantilla con <b>QDialog</b> para usar objetos del tipo <b>QTabWidget</b> como contenedores de <b>QTableWidget</b> en QGIS 3. Se usó el primer tab para desplegar una tabla con n filas y 2 columnas; donde n corresponde al número de capas (vectoriales o ráster) que se encuentran visualizadas en el Map Canvas.</p><a name='more'></a>En este post se va a usar el segundo tab para desplegar otra tabla que contiene el nombre de los campos de los archivos vectoriales. Como el número de campos no necesariamente coincidirán entre ellos, se produce una matriz con un número de columnas que corresponde al máximo del número de campos presentes en un vectorial. El string ' ' será introducido en las celdas de aquellos vectoriales con menor cantidad de campos. Además, una función se encargará de compensar las variaciones del número de capas vectoriales que se presente en el Map Canvas. El código desarrollado se presenta a continuación: <br />
<br />
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><table><tr><td><pre style="margin: 0; line-height: 125%"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162</pre></td><td><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtCore</span> <span style="color: #008800; font-weight: bold">import</span> Qt
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">Dlg</span>(QDialog):
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">__init__</span>(<span style="color: #007020">self</span>):
QDialog<span style="color: #333333">.</span>__init__(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout <span style="color: #333333">=</span> QGridLayout(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>tabs <span style="color: #333333">=</span> QTabWidget()
<span style="color: #007020">self</span><span style="color: #333333">.</span>tab1 <span style="color: #333333">=</span> QWidget()
<span style="color: #007020">self</span><span style="color: #333333">.</span>tab2 <span style="color: #333333">=</span> QWidget()
<span style="color: #007020">self</span><span style="color: #333333">.</span>tab3 <span style="color: #333333">=</span> QWidget()
<span style="color: #007020">self</span><span style="color: #333333">.</span>tabs<span style="color: #333333">.</span>addTab(<span style="color: #007020">self</span><span style="color: #333333">.</span>tab1,<span style="background-color: #fff0f0">"Tab1"</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>tabs<span style="color: #333333">.</span>addTab(<span style="color: #007020">self</span><span style="color: #333333">.</span>tab2,<span style="background-color: #fff0f0">"Tab2"</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>tabs<span style="color: #333333">.</span>addTab(<span style="color: #007020">self</span><span style="color: #333333">.</span>tab3,<span style="background-color: #fff0f0">"Tab3"</span>)
canvas <span style="color: #333333">=</span> iface<span style="color: #333333">.</span>mapCanvas()
layers <span style="color: #333333">=</span> canvas<span style="color: #333333">.</span>layers()
vlayers <span style="color: #333333">=</span> [ layer <span style="color: #008800; font-weight: bold">for</span> layer <span style="color: #000000; font-weight: bold">in</span> layers <span style="color: #008800; font-weight: bold">if</span> layer<span style="color: #333333">.</span>type() <span style="color: #333333">==</span> QgsMapLayer<span style="color: #333333">.</span>VectorLayer ]
length <span style="color: #333333">=</span> []
fields <span style="color: #333333">=</span> []
<span style="color: #008800; font-weight: bold">for</span> layer <span style="color: #000000; font-weight: bold">in</span> vlayers:
nf <span style="color: #333333">=</span> layer<span style="color: #333333">.</span>fields()<span style="color: #333333">.</span>names()
fields<span style="color: #333333">.</span>append(nf)
n <span style="color: #333333">=</span> <span style="color: #007020">len</span>(nf)
length<span style="color: #333333">.</span>append(n)
<span style="color: #008800; font-weight: bold">try</span>:
n_t2_col <span style="color: #333333">=</span> (<span style="color: #007020">max</span>(length))
<span style="color: #008800; font-weight: bold">except</span> <span style="color: #FF0000; font-weight: bold">ValueError</span>:
n_t2_col <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">1</span>
<span style="color: #008800; font-weight: bold">if</span> n_t2_col <span style="color: #333333">!=</span> <span style="color: #0000DD; font-weight: bold">0</span>:
data_f <span style="color: #333333">=</span> fields
<span style="color: #008800; font-weight: bold">for</span> i, f <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">enumerate</span>(fields):
diff <span style="color: #333333">=</span> n_t2_col <span style="color: #333333">-</span> <span style="color: #007020">len</span>(f)
<span style="color: #008800; font-weight: bold">for</span> j <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(diff):
f<span style="color: #333333">.</span>append(<span style="background-color: #fff0f0">""</span>)
<span style="color: #008800; font-weight: bold">else</span>:
data_f <span style="color: #333333">=</span> [[<span style="background-color: #fff0f0">''</span>]]
data <span style="color: #333333">=</span> [ [] <span style="color: #008800; font-weight: bold">for</span> i <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(<span style="color: #007020">len</span>(layers)) ]
<span style="color: #008800; font-weight: bold">for</span> i, layer <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">enumerate</span>(layers):
<span style="color: #008800; font-weight: bold">for</span> j <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(<span style="color: #0000DD; font-weight: bold">2</span>):
data[i]<span style="color: #333333">.</span>append(layer<span style="color: #333333">.</span>name())
<span style="color: #008800; font-weight: bold">if</span> layer<span style="color: #333333">.</span>type() <span style="color: #333333">==</span> QgsMapLayer<span style="color: #333333">.</span>VectorLayer:
data[i]<span style="color: #333333">.</span>append(<span style="background-color: #fff0f0">'vector layer'</span>)
<span style="color: #008800; font-weight: bold">break</span>
<span style="color: #008800; font-weight: bold">if</span> layer<span style="color: #333333">.</span>type() <span style="color: #333333">==</span> QgsMapLayer<span style="color: #333333">.</span>RasterLayer:
data[i]<span style="color: #333333">.</span>append(<span style="background-color: #fff0f0">'raster layer'</span>)
<span style="color: #008800; font-weight: bold">break</span>
nb_row <span style="color: #333333">=</span> <span style="color: #007020">len</span>(data)
nb_col <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">2</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>tab1<span style="color: #333333">.</span>layout <span style="color: #333333">=</span> QVBoxLayout(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>table1 <span style="color: #333333">=</span> QTableWidget()
<span style="color: #007020">self</span><span style="color: #333333">.</span>table1<span style="color: #333333">.</span>setRowCount(nb_row)
<span style="color: #007020">self</span><span style="color: #333333">.</span>table1<span style="color: #333333">.</span>setColumnCount(nb_col)
<span style="color: #007020">self</span><span style="color: #333333">.</span>table1<span style="color: #333333">.</span>setHorizontalHeaderLabels([<span style="background-color: #fff0f0">'Layer'</span>, <span style="background-color: #fff0f0">'Layer type'</span>])
<span style="color: #007020">self</span><span style="color: #333333">.</span>tab2<span style="color: #333333">.</span>layout <span style="color: #333333">=</span> QVBoxLayout(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>table2 <span style="color: #333333">=</span> QTableWidget()
<span style="color: #007020">self</span><span style="color: #333333">.</span>table2<span style="color: #333333">.</span>setRowCount(nb_row)
<span style="color: #007020">self</span><span style="color: #333333">.</span>table2<span style="color: #333333">.</span>setColumnCount(n_t2_col)
<span style="color: #008800; font-weight: bold">for</span> row <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span> (nb_row):
<span style="color: #008800; font-weight: bold">for</span> col <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(nb_col):
item <span style="color: #333333">=</span> QTableWidgetItem(<span style="color: #007020">str</span>(data[row][col]))
<span style="color: #007020">self</span><span style="color: #333333">.</span>table1<span style="color: #333333">.</span>setItem(row, col, item)
<span style="color: #008800; font-weight: bold">for</span> row <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span> (nb_row):
<span style="color: #008800; font-weight: bold">for</span> col <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(n_t2_col):
item <span style="color: #333333">=</span> QTableWidgetItem(<span style="color: #007020">str</span>(data_f[row][col]))
<span style="color: #007020">self</span><span style="color: #333333">.</span>table2<span style="color: #333333">.</span>setItem(row, col, item)
<span style="color: #007020">self</span><span style="color: #333333">.</span>tab1<span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>table1)
<span style="color: #007020">self</span><span style="color: #333333">.</span>tab1<span style="color: #333333">.</span>setLayout(<span style="color: #007020">self</span><span style="color: #333333">.</span>tab1<span style="color: #333333">.</span>layout)
<span style="color: #007020">self</span><span style="color: #333333">.</span>tab2<span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>table2)
<span style="color: #007020">self</span><span style="color: #333333">.</span>tab2<span style="color: #333333">.</span>setLayout(<span style="color: #007020">self</span><span style="color: #333333">.</span>tab2<span style="color: #333333">.</span>layout)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>tabs, <span style="color: #0000DD; font-weight: bold">0</span>, <span style="color: #0000DD; font-weight: bold">0</span>)
iface<span style="color: #333333">.</span>mapCanvas()<span style="color: #333333">.</span>layersChanged<span style="color: #333333">.</span>connect(<span style="color: #007020">self</span><span style="color: #333333">.</span>change_layers)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">change_layers</span>(<span style="color: #007020">self</span>):
canvas <span style="color: #333333">=</span> iface<span style="color: #333333">.</span>mapCanvas()
layers <span style="color: #333333">=</span> canvas<span style="color: #333333">.</span>layers()
vlayers <span style="color: #333333">=</span> [ layer <span style="color: #008800; font-weight: bold">for</span> layer <span style="color: #000000; font-weight: bold">in</span> layers <span style="color: #008800; font-weight: bold">if</span> layer<span style="color: #333333">.</span>type() <span style="color: #333333">==</span> QgsMapLayer<span style="color: #333333">.</span>VectorLayer ]
length <span style="color: #333333">=</span> []
fields <span style="color: #333333">=</span> []
<span style="color: #008800; font-weight: bold">for</span> layer <span style="color: #000000; font-weight: bold">in</span> vlayers:
nf <span style="color: #333333">=</span> layer<span style="color: #333333">.</span>fields()<span style="color: #333333">.</span>names()
fields<span style="color: #333333">.</span>append(nf)
n <span style="color: #333333">=</span> <span style="color: #007020">len</span>(nf)
length<span style="color: #333333">.</span>append(n)
<span style="color: #008800; font-weight: bold">try</span>:
n_t2_col <span style="color: #333333">=</span> (<span style="color: #007020">max</span>(length))
<span style="color: #008800; font-weight: bold">except</span> <span style="color: #FF0000; font-weight: bold">ValueError</span>:
n_t2_col <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">1</span>
<span style="color: #008800; font-weight: bold">if</span> n_t2_col <span style="color: #333333">!=</span> <span style="color: #0000DD; font-weight: bold">0</span>:
data_f <span style="color: #333333">=</span> fields
<span style="color: #008800; font-weight: bold">for</span> i, f <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">enumerate</span>(fields):
diff <span style="color: #333333">=</span> n_t2_col <span style="color: #333333">-</span> <span style="color: #007020">len</span>(f)
<span style="color: #008800; font-weight: bold">for</span> j <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(diff):
f<span style="color: #333333">.</span>append(<span style="background-color: #fff0f0">""</span>)
<span style="color: #008800; font-weight: bold">else</span>:
data_f <span style="color: #333333">=</span> [[<span style="background-color: #fff0f0">''</span>]]
data <span style="color: #333333">=</span> [ [] <span style="color: #008800; font-weight: bold">for</span> i <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(<span style="color: #007020">len</span>(layers)) ]
<span style="color: #008800; font-weight: bold">for</span> i, layer <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">enumerate</span>(layers):
<span style="color: #008800; font-weight: bold">for</span> j <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(<span style="color: #0000DD; font-weight: bold">2</span>):
data[i]<span style="color: #333333">.</span>append(layer<span style="color: #333333">.</span>name())
<span style="color: #008800; font-weight: bold">if</span> layer<span style="color: #333333">.</span>type() <span style="color: #333333">==</span> QgsMapLayer<span style="color: #333333">.</span>VectorLayer:
data[i]<span style="color: #333333">.</span>append(<span style="background-color: #fff0f0">'vector layer'</span>)
<span style="color: #008800; font-weight: bold">break</span>
<span style="color: #008800; font-weight: bold">if</span> layer<span style="color: #333333">.</span>type() <span style="color: #333333">==</span> QgsMapLayer<span style="color: #333333">.</span>RasterLayer:
data[i]<span style="color: #333333">.</span>append(<span style="background-color: #fff0f0">'raster layer'</span>)
<span style="color: #008800; font-weight: bold">break</span>
nb_row <span style="color: #333333">=</span> <span style="color: #007020">len</span>(data)
nb_col <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">2</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>table1<span style="color: #333333">.</span>setHorizontalHeaderLabels([<span style="background-color: #fff0f0">'Layer'</span>, <span style="background-color: #fff0f0">'Layer type'</span>])
<span style="color: #007020">self</span><span style="color: #333333">.</span>table1<span style="color: #333333">.</span>setRowCount(nb_row)
<span style="color: #007020">self</span><span style="color: #333333">.</span>table1<span style="color: #333333">.</span>setColumnCount(nb_col)
<span style="color: #007020">self</span><span style="color: #333333">.</span>table2<span style="color: #333333">.</span>setRowCount(nb_row)
<span style="color: #007020">self</span><span style="color: #333333">.</span>table2<span style="color: #333333">.</span>setColumnCount(n_t2_col)
<span style="color: #008800; font-weight: bold">for</span> row <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span> (nb_row):
<span style="color: #008800; font-weight: bold">for</span> col <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(nb_col):
item <span style="color: #333333">=</span> QTableWidgetItem(<span style="color: #007020">str</span>(data[row][col]))
<span style="color: #007020">self</span><span style="color: #333333">.</span>table1<span style="color: #333333">.</span>setItem(row, col, item)
<span style="color: #008800; font-weight: bold">for</span> row <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span> (nb_row):
<span style="color: #008800; font-weight: bold">for</span> col <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(n_t2_col):
item <span style="color: #333333">=</span> QTableWidgetItem(<span style="color: #007020">str</span>(data_f[row][col]))
<span style="color: #007020">self</span><span style="color: #333333">.</span>table2<span style="color: #333333">.</span>setItem(row, col, item)
w <span style="color: #333333">=</span> Dlg()
w<span style="color: #333333">.</span>resize(<span style="color: #0000DD; font-weight: bold">350</span>,<span style="color: #0000DD; font-weight: bold">300</span>)
w<span style="color: #333333">.</span>setWindowTitle(<span style="background-color: #fff0f0">'Example with QTableWidget'</span>)
w<span style="color: #333333">.</span>setWindowFlags(Qt<span style="color: #333333">.</span>WindowStaysOnTopHint)
w<span style="color: #333333">.</span>show()
</pre></td></tr>
</table></div><br />
En la imagen siguiente se observa la ejecución del código anterior en la Python Console con tres capas vectoriales. La tabla desplegada en el segundo tab corresponde a lo esperado.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUTQoyMj4GSPZbTcGnhyly0W74xop11bXWb2Jv32fMnefY625uc4sPdwOG-npxUMpmGFo2520bxtkjYqTASjc2LKxQFD1mVvoOUs4X-HUIz97MyoEA4oDdrO70rrCmlfgMIACPcNQiAVE/s1600/table1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUTQoyMj4GSPZbTcGnhyly0W74xop11bXWb2Jv32fMnefY625uc4sPdwOG-npxUMpmGFo2520bxtkjYqTASjc2LKxQFD1mVvoOUs4X-HUIz97MyoEA4oDdrO70rrCmlfgMIACPcNQiAVE/s640/table1.png" width="640" height="390" data-original-width="1600" data-original-height="974" /></a></div><br />
Cuando se desmarcan dos de las capas vectoriales el comportamiento reflejado en la imagen a continuación también se corresponde con lo esperado. <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiV2hiIOjKNlEmb8rGaTRLo88xWbQ0rINLupmCl9S8g4E8zXRFlB-ZZ2yENWwtNCm7sARyHnlCRPtZc0-LukEZBhHOuH6Te53vT3LhVtCcLpZN5C4SKFmv4LfkBwJJmKtEgds3JEXk_MtM/s1600/table2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiV2hiIOjKNlEmb8rGaTRLo88xWbQ0rINLupmCl9S8g4E8zXRFlB-ZZ2yENWwtNCm7sARyHnlCRPtZc0-LukEZBhHOuH6Te53vT3LhVtCcLpZN5C4SKFmv4LfkBwJJmKtEgds3JEXk_MtM/s640/table2.png" width="640" height="390" data-original-width="1600" data-original-height="974" /></a></div><br />
Finalmente, si se desmarcan todas las capas desaparece toda la información sobre ellas. No obstante, el proceso es reversible si se vuelven a marcar todas las capas aunque no se detalle en ninguna imagen.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib7_Bqy3dwkeqbwTKbMn2DMyL4cVA0nnBsAFly1vzR1wRxXijITVVTAR7u7bO6HeoSq5N9u7bs1zcQ2_koIwqLXTXQoRIwEkTGPpokuwI3vocE3EJmbmxa2II3yVYMgnu2t1yD1LgkJmY/s1600/table3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib7_Bqy3dwkeqbwTKbMn2DMyL4cVA0nnBsAFly1vzR1wRxXijITVVTAR7u7bO6HeoSq5N9u7bs1zcQ2_koIwqLXTXQoRIwEkTGPpokuwI3vocE3EJmbmxa2II3yVYMgnu2t1yD1LgkJmY/s640/table3.png" width="640" height="389" data-original-width="1600" data-original-height="972" /></a></div><br />
<br />
</div><br />
José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-40731225640115858222020-01-19T19:04:00.000-04:002020-01-19T19:04:36.563-04:00Clase plantilla con QDialog para usar objetos del tipo QTabWidget como contenedores de QTableWidget en QGIS 3<div style="text-align:justify;"><p>En el <a href="https://blogdezeka.blogspot.com/2020/01/clase-plantilla-con-qdialog-para-crear_18.html">post anterior</a> se propuso una clase plantilla con <b>QDialog</b> para crear objetos del tipo <b>QTabWidget</b> en QGIS 3. En éste se va a usar el primer tab como contenedor de un objeto <b>QTableWidget</b>. La tabla se va a desplegar con n filas y 2 columnas; donde n corresponde al número de capas (vectoriales o ráster) que se encuentran visualizadas en el Map Canvas. La primera columna ('Layer') desplegará el nombre de la capa y la segunda ('Layer type') el tipo de capa (vectorial o ráster). Si el número de capas varía una función conectará automáticamente para dar cuenta de estos cambios.</p><a name='more'></a>El código propuesto se expone a continuación:<br />
<br />
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><table><tr><td><pre style="margin: 0; line-height: 125%"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87</pre></td><td><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtCore</span> <span style="color: #008800; font-weight: bold">import</span> Qt
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">Dlg</span>(QDialog):
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">__init__</span>(<span style="color: #007020">self</span>):
QDialog<span style="color: #333333">.</span>__init__(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout <span style="color: #333333">=</span> QGridLayout(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>tabs <span style="color: #333333">=</span> QTabWidget()
<span style="color: #007020">self</span><span style="color: #333333">.</span>tab1 <span style="color: #333333">=</span> QWidget()
<span style="color: #007020">self</span><span style="color: #333333">.</span>tab2 <span style="color: #333333">=</span> QWidget()
<span style="color: #007020">self</span><span style="color: #333333">.</span>tab3 <span style="color: #333333">=</span> QWidget()
<span style="color: #007020">self</span><span style="color: #333333">.</span>tabs<span style="color: #333333">.</span>addTab(<span style="color: #007020">self</span><span style="color: #333333">.</span>tab1,<span style="background-color: #fff0f0">"Tab1"</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>tabs<span style="color: #333333">.</span>addTab(<span style="color: #007020">self</span><span style="color: #333333">.</span>tab2,<span style="background-color: #fff0f0">"Tab2"</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>tabs<span style="color: #333333">.</span>addTab(<span style="color: #007020">self</span><span style="color: #333333">.</span>tab3,<span style="background-color: #fff0f0">"Tab3"</span>)
canvas <span style="color: #333333">=</span> iface<span style="color: #333333">.</span>mapCanvas()
layers <span style="color: #333333">=</span> canvas<span style="color: #333333">.</span>layers()
data <span style="color: #333333">=</span> [ [] <span style="color: #008800; font-weight: bold">for</span> i <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(<span style="color: #007020">len</span>(layers)) ]
<span style="color: #008800; font-weight: bold">for</span> i, layer <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">enumerate</span>(layers):
<span style="color: #008800; font-weight: bold">for</span> j <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(<span style="color: #0000DD; font-weight: bold">2</span>):
data[i]<span style="color: #333333">.</span>append(layer<span style="color: #333333">.</span>name())
<span style="color: #008800; font-weight: bold">if</span> layer<span style="color: #333333">.</span>type() <span style="color: #333333">==</span> QgsMapLayer<span style="color: #333333">.</span>VectorLayer:
data[i]<span style="color: #333333">.</span>append(<span style="background-color: #fff0f0">'vector layer'</span>)
<span style="color: #008800; font-weight: bold">break</span>
<span style="color: #008800; font-weight: bold">if</span> layer<span style="color: #333333">.</span>type() <span style="color: #333333">==</span> QgsMapLayer<span style="color: #333333">.</span>RasterLayer:
data[i]<span style="color: #333333">.</span>append(<span style="background-color: #fff0f0">'raster layer'</span>)
<span style="color: #008800; font-weight: bold">break</span>
nb_row <span style="color: #333333">=</span> <span style="color: #007020">len</span>(data)
nb_col <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">2</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>tab1<span style="color: #333333">.</span>layout <span style="color: #333333">=</span> QVBoxLayout(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>table <span style="color: #333333">=</span> QTableWidget()
<span style="color: #007020">self</span><span style="color: #333333">.</span>table<span style="color: #333333">.</span>setRowCount(nb_row)
<span style="color: #007020">self</span><span style="color: #333333">.</span>table<span style="color: #333333">.</span>setColumnCount(nb_col)
<span style="color: #007020">self</span><span style="color: #333333">.</span>table<span style="color: #333333">.</span>setHorizontalHeaderLabels([<span style="background-color: #fff0f0">'Layer'</span>, <span style="background-color: #fff0f0">'Layer type'</span>])
<span style="color: #008800; font-weight: bold">for</span> row <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span> (nb_row):
<span style="color: #008800; font-weight: bold">for</span> col <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(nb_col):
item <span style="color: #333333">=</span> QTableWidgetItem(<span style="color: #007020">str</span>(data[row][col]))
<span style="color: #007020">self</span><span style="color: #333333">.</span>table<span style="color: #333333">.</span>setItem(row, col, item)
<span style="color: #007020">self</span><span style="color: #333333">.</span>tab1<span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>table)
<span style="color: #007020">self</span><span style="color: #333333">.</span>tab1<span style="color: #333333">.</span>setLayout(<span style="color: #007020">self</span><span style="color: #333333">.</span>tab1<span style="color: #333333">.</span>layout)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>tabs, <span style="color: #0000DD; font-weight: bold">0</span>, <span style="color: #0000DD; font-weight: bold">0</span>)
iface<span style="color: #333333">.</span>mapCanvas()<span style="color: #333333">.</span>layersChanged<span style="color: #333333">.</span>connect(<span style="color: #007020">self</span><span style="color: #333333">.</span>change_layers)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">change_layers</span>(<span style="color: #007020">self</span>):
canvas <span style="color: #333333">=</span> iface<span style="color: #333333">.</span>mapCanvas()
layers <span style="color: #333333">=</span> canvas<span style="color: #333333">.</span>layers()
data <span style="color: #333333">=</span> [ [] <span style="color: #008800; font-weight: bold">for</span> i <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(<span style="color: #007020">len</span>(layers)) ]
<span style="color: #008800; font-weight: bold">for</span> i, layer <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">enumerate</span>(layers):
<span style="color: #008800; font-weight: bold">for</span> j <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(<span style="color: #0000DD; font-weight: bold">2</span>):
data[i]<span style="color: #333333">.</span>append(layer<span style="color: #333333">.</span>name())
<span style="color: #008800; font-weight: bold">if</span> layer<span style="color: #333333">.</span>type() <span style="color: #333333">==</span> QgsMapLayer<span style="color: #333333">.</span>VectorLayer:
data[i]<span style="color: #333333">.</span>append(<span style="background-color: #fff0f0">'vector layer'</span>)
<span style="color: #008800; font-weight: bold">break</span>
<span style="color: #008800; font-weight: bold">if</span> layer<span style="color: #333333">.</span>type() <span style="color: #333333">==</span> QgsMapLayer<span style="color: #333333">.</span>RasterLayer:
data[i]<span style="color: #333333">.</span>append(<span style="background-color: #fff0f0">'raster layer'</span>)
<span style="color: #008800; font-weight: bold">break</span>
nb_row <span style="color: #333333">=</span> <span style="color: #007020">len</span>(data)
nb_col <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">2</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>table<span style="color: #333333">.</span>setHorizontalHeaderLabels([<span style="background-color: #fff0f0">'Layer'</span>, <span style="background-color: #fff0f0">'Layer type'</span>])
<span style="color: #007020">self</span><span style="color: #333333">.</span>table<span style="color: #333333">.</span>setRowCount(nb_row)
<span style="color: #007020">self</span><span style="color: #333333">.</span>table<span style="color: #333333">.</span>setColumnCount(nb_col)
<span style="color: #008800; font-weight: bold">for</span> row <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span> (nb_row):
<span style="color: #008800; font-weight: bold">for</span> col <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">range</span>(nb_col):
item <span style="color: #333333">=</span> QTableWidgetItem(<span style="color: #007020">str</span>(data[row][col]))
<span style="color: #007020">self</span><span style="color: #333333">.</span>table<span style="color: #333333">.</span>setItem(row, col, item)
w <span style="color: #333333">=</span> Dlg()
w<span style="color: #333333">.</span>resize(<span style="color: #0000DD; font-weight: bold">350</span>,<span style="color: #0000DD; font-weight: bold">300</span>)
w<span style="color: #333333">.</span>setWindowTitle(<span style="background-color: #fff0f0">'Example with QTableWidget'</span>)
w<span style="color: #333333">.</span>setWindowFlags(Qt<span style="color: #333333">.</span>WindowStaysOnTopHint)
w<span style="color: #333333">.</span>show()
</pre></td></tr>
</table></div><br />
Después de ejecutarlo en la Python Console de QGIS 3 con las capas que se observan en el Map Canvas (dos vectoriales y un ráster):<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg_anL6TaAWIVsmpLsgqtIq7SgvHrI3PcKDWMktdYOttcpFMRtG-RVYutFkswbius6Jx-igj0YBVlJWOUX_MwyqvoJeaSPqwMRr7VRdCwKZrMIf0Aw2x4ct33NKRBZjJ66AV3fsRGHZ_M/s1600/table1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg_anL6TaAWIVsmpLsgqtIq7SgvHrI3PcKDWMktdYOttcpFMRtG-RVYutFkswbius6Jx-igj0YBVlJWOUX_MwyqvoJeaSPqwMRr7VRdCwKZrMIf0Aw2x4ct33NKRBZjJ66AV3fsRGHZ_M/s640/table1.png" width="640" height="390" data-original-width="1600" data-original-height="975" /></a></div><br />
Como se puede observar en la imagen siguiente, se actualiza automáticamente cuando se desmarca una de las capas vectoriales y la capa ráster.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdy0S4xu9Ejz-Rohef2FzN1eIJ3hYst0Jei2ev7-aKwKhDJKrIm4KSgNEAAzxXrTTyUEb2l1c66IstRIvfX2FkrBoo15hD-Z1Ztdyu5OV5C7uj-3EJmQ5pU8X4cZyYwXU1lOr9NzfhHr0/s1600/table2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdy0S4xu9Ejz-Rohef2FzN1eIJ3hYst0Jei2ev7-aKwKhDJKrIm4KSgNEAAzxXrTTyUEb2l1c66IstRIvfX2FkrBoo15hD-Z1Ztdyu5OV5C7uj-3EJmQ5pU8X4cZyYwXU1lOr9NzfhHr0/s640/table2.png" width="640" height="390" data-original-width="1600" data-original-height="975" /></a></div><br />
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-4486624403919887472020-01-18T13:21:00.000-04:002020-01-18T13:21:07.704-04:00Clase plantilla con QDialog para crear objetos del tipo QTabWidget en QGIS 3<div style="text-align:justify;"><p>En este post se va a continuar con la clase plantilla con <b>QDialog</b> pero, en este caso, para crear objetos del tipo <b>QTabWidget</b> los cuales, a su vez, contienen tabs (objetos del tipo <b>QWidgets</b>). Estos últimos también pueden ser contenedores de objetos <b>QLabel</b>, <b>QTableWidget</b>, imágenes, etcetera. En el código a continuación se presenta un ejemplo sencillo de como implementar los <b>QTabWidget</b> con tres tabs pero sin que actuen como contenedores.</p><a name='more'></a><!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><table><tr><td><pre style="margin: 0; line-height: 125%"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22</pre></td><td><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtCore</span> <span style="color: #008800; font-weight: bold">import</span> Qt
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">Dlg</span>(QDialog):
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">__init__</span>(<span style="color: #007020">self</span>):
QDialog<span style="color: #333333">.</span>__init__(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout <span style="color: #333333">=</span> QGridLayout(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>tabs <span style="color: #333333">=</span> QTabWidget()
<span style="color: #007020">self</span><span style="color: #333333">.</span>tab1 <span style="color: #333333">=</span> QWidget()
<span style="color: #007020">self</span><span style="color: #333333">.</span>tab2 <span style="color: #333333">=</span> QWidget()
<span style="color: #007020">self</span><span style="color: #333333">.</span>tab3 <span style="color: #333333">=</span> QWidget()
<span style="color: #007020">self</span><span style="color: #333333">.</span>tabs<span style="color: #333333">.</span>addTab(<span style="color: #007020">self</span><span style="color: #333333">.</span>tab1,<span style="background-color: #fff0f0">"Tab1"</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>tabs<span style="color: #333333">.</span>addTab(<span style="color: #007020">self</span><span style="color: #333333">.</span>tab2,<span style="background-color: #fff0f0">"Tab2"</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>tabs<span style="color: #333333">.</span>addTab(<span style="color: #007020">self</span><span style="color: #333333">.</span>tab3,<span style="background-color: #fff0f0">"Tab3"</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>tabs, <span style="color: #0000DD; font-weight: bold">0</span>, <span style="color: #0000DD; font-weight: bold">0</span>)
w <span style="color: #333333">=</span> Dlg()
w<span style="color: #333333">.</span>resize(<span style="color: #0000DD; font-weight: bold">300</span>,<span style="color: #0000DD; font-weight: bold">300</span>)
w<span style="color: #333333">.</span>setWindowTitle(<span style="background-color: #fff0f0">'Example with QTabWidget'</span>)
w<span style="color: #333333">.</span>setWindowFlags(Qt<span style="color: #333333">.</span>WindowStaysOnTopHint)
w<span style="color: #333333">.</span>show()
</pre></td></tr></table></div><br />
Después de ejecutado el código anterior en la Python Console de QGIS 3 se obtiene lo siguiente:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_dnIHOLyArj3aeVxTRHtTVmH2Ippioob4b2EfPO9KsqOD4w9ZGXfCQN-zKXi75uowzSmmHZ2i5mymlFDPb7Dliqiv7b8JLrjiBshbgZVOyssZFpKkZEl4SHygToQers4ZZyDhD2lQFds/s1600/tab1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_dnIHOLyArj3aeVxTRHtTVmH2Ippioob4b2EfPO9KsqOD4w9ZGXfCQN-zKXi75uowzSmmHZ2i5mymlFDPb7Dliqiv7b8JLrjiBshbgZVOyssZFpKkZEl4SHygToQers4ZZyDhD2lQFds/s640/tab1.png" width="640" height="390" data-original-width="1600" data-original-height="975" /></a></div><br />
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-64030015600914281432020-01-16T19:34:00.000-04:002020-01-16T19:34:20.190-04:00Clase plantilla con QDialog para crear círculos<div style="text-align:justify;"><p>En el <a href="https://blogdezeka.blogspot.com/2020/01/clase-plantilla-con-qdialog-para-crear.html">post anterior</a> se introdujo una Clase plantilla con <b>QDialog</b> para crear puntos (como memory layers) a partir de las coordenadas del Map Canvas de QGIS obtenidas con un click del ratón. En este post se van a aprovechar estas coordenadas para crear un buffer circular, dado el radio, que se pide a través de un <b>QInputDialog</b> que se genera en la misma función de creación del buffer circular.</p><a name='more'></a>El código completo se expone a continuación:<br />
<br />
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><table><tr><td><pre style="margin: 0; line-height: 125%"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123</pre></td><td><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtCore</span> <span style="color: #008800; font-weight: bold">import</span> Qt
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">qgis.gui</span> <span style="color: #008800; font-weight: bold">import</span> QgsMapToolEmitPoint
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">Dlg</span>(QDialog):
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">__init__</span>(<span style="color: #007020">self</span>):
QDialog<span style="color: #333333">.</span>__init__(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout <span style="color: #333333">=</span> QGridLayout(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>label1 <span style="color: #333333">=</span> QLabel(<span style="background-color: #fff0f0">'Coordinates of map: '</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>label2 <span style="color: #333333">=</span> QLabel(<span style="background-color: #fff0f0">'Select Projection: '</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>label3 <span style="color: #333333">=</span> QLabel(<span style="background-color: #fff0f0">'Create Point: '</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>label4 <span style="color: #333333">=</span> QLabel(<span style="background-color: #fff0f0">'Create Circle: '</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>line_edit <span style="color: #333333">=</span> QLineEdit()
<span style="color: #007020">self</span><span style="color: #333333">.</span>line_edit<span style="color: #333333">.</span>setFixedWidth(<span style="color: #0000DD; font-weight: bold">350</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>sel_proj <span style="color: #333333">=</span> QgsProjectionSelectionWidget()
proj <span style="color: #333333">=</span> QgsProject<span style="color: #333333">.</span>instance()<span style="color: #333333">.</span>crs()<span style="color: #333333">.</span>postgisSrid()
crs <span style="color: #333333">=</span> QgsCoordinateReferenceSystem()
crs<span style="color: #333333">.</span>createFromSrid(proj)
<span style="color: #007020">self</span><span style="color: #333333">.</span>sel_proj<span style="color: #333333">.</span>setCrs(crs)
<span style="color: #007020">self</span><span style="color: #333333">.</span>btn1 <span style="color: #333333">=</span> QPushButton(<span style="background-color: #fff0f0">'OK'</span>, <span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>btn1<span style="color: #333333">.</span>setFixedWidth(<span style="color: #0000DD; font-weight: bold">100</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>btn2 <span style="color: #333333">=</span> QPushButton(<span style="background-color: #fff0f0">'OK'</span>, <span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>btn2<span style="color: #333333">.</span>setFixedWidth(<span style="color: #0000DD; font-weight: bold">100</span>)
<span style="color: #888888"># Save reference to the QGIS interface</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface <span style="color: #333333">=</span> iface
<span style="color: #888888"># a reference to our map canvas</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mapCanvas()
<span style="color: #888888"># this QGIS tool emits as QgsPoint after each click on the map canvas</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>pointTool <span style="color: #333333">=</span> QgsMapToolEmitPoint(<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>label1, <span style="color: #0000DD; font-weight: bold">0</span>, <span style="color: #0000DD; font-weight: bold">0</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>line_edit, <span style="color: #0000DD; font-weight: bold">0</span>, <span style="color: #0000DD; font-weight: bold">1</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>label2, <span style="color: #0000DD; font-weight: bold">2</span>, <span style="color: #0000DD; font-weight: bold">0</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>sel_proj, <span style="color: #0000DD; font-weight: bold">2</span>, <span style="color: #0000DD; font-weight: bold">1</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>label3, <span style="color: #0000DD; font-weight: bold">3</span>, <span style="color: #0000DD; font-weight: bold">0</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>btn1, <span style="color: #0000DD; font-weight: bold">3</span>, <span style="color: #0000DD; font-weight: bold">1</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>label4, <span style="color: #0000DD; font-weight: bold">4</span>, <span style="color: #0000DD; font-weight: bold">0</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>btn2, <span style="color: #0000DD; font-weight: bold">4</span>, <span style="color: #0000DD; font-weight: bold">1</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>pointTool<span style="color: #333333">.</span>canvasClicked<span style="color: #333333">.</span>connect(<span style="color: #007020">self</span><span style="color: #333333">.</span>display_point)
<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas<span style="color: #333333">.</span>setMapTool(<span style="color: #007020">self</span><span style="color: #333333">.</span>pointTool)
<span style="color: #007020">self</span><span style="color: #333333">.</span>btn1<span style="color: #333333">.</span>clicked<span style="color: #333333">.</span>connect(<span style="color: #007020">self</span><span style="color: #333333">.</span>create_point)
<span style="color: #007020">self</span><span style="color: #333333">.</span>btn2<span style="color: #333333">.</span>clicked<span style="color: #333333">.</span>connect(<span style="color: #007020">self</span><span style="color: #333333">.</span>create_circle)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">display_point</span>(<span style="color: #007020">self</span>, point, button):
<span style="color: #888888"># report map coordinates from a canvas click</span>
coords <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"{}, {}"</span><span style="color: #333333">.</span>format(point<span style="color: #333333">.</span>x(), point<span style="color: #333333">.</span>y())
<span style="color: #007020">self</span><span style="color: #333333">.</span>line_edit<span style="color: #333333">.</span>setText(<span style="color: #007020">str</span>(coords))
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">create_point</span>(<span style="color: #007020">self</span>):
pt <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>line_edit<span style="color: #333333">.</span>text()<span style="color: #333333">.</span>split(<span style="background-color: #fff0f0">','</span>)
<span style="color: #008800; font-weight: bold">try</span>:
x <span style="color: #333333">=</span> <span style="color: #007020">float</span>(pt[<span style="color: #0000DD; font-weight: bold">0</span>])
y <span style="color: #333333">=</span> <span style="color: #007020">float</span>(pt[<span style="color: #0000DD; font-weight: bold">1</span>])
point <span style="color: #333333">=</span> QgsPointXY(x,y)
epsg <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>sel_proj<span style="color: #333333">.</span>crs()<span style="color: #333333">.</span>postgisSrid()
uri <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"Point?crs=epsg:"</span> <span style="color: #333333">+</span> <span style="color: #007020">str</span>(epsg) <span style="color: #333333">+</span> <span style="background-color: #fff0f0">"&field=id:integer""&index=yes"</span>
mem_layer <span style="color: #333333">=</span> QgsVectorLayer(uri,
<span style="background-color: #fff0f0">'point'</span>,
<span style="background-color: #fff0f0">'memory'</span>)
prov <span style="color: #333333">=</span> mem_layer<span style="color: #333333">.</span>dataProvider()
feat <span style="color: #333333">=</span> QgsFeature()
feat<span style="color: #333333">.</span>setAttributes([<span style="color: #0000DD; font-weight: bold">0</span>])
feat<span style="color: #333333">.</span>setGeometry(QgsGeometry<span style="color: #333333">.</span>fromPointXY(point))
prov<span style="color: #333333">.</span>addFeatures([feat])
QgsProject<span style="color: #333333">.</span>instance()<span style="color: #333333">.</span>addMapLayer(mem_layer)
<span style="color: #008800; font-weight: bold">except</span> <span style="color: #FF0000; font-weight: bold">ValueError</span>:
<span style="color: #008800; font-weight: bold">pass</span>
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">create_circle</span>(<span style="color: #007020">self</span>):
msg <span style="color: #333333">=</span> <span style="background-color: #fff0f0">u"radius?"</span>
dlg <span style="color: #333333">=</span> QInputDialog()
d <span style="color: #333333">=</span> dlg<span style="color: #333333">.</span>getDouble(<span style="color: #007020">None</span>, <span style="background-color: #fff0f0">"Create Circle"</span>, msg, decimals<span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">5</span>)
pt <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>line_edit<span style="color: #333333">.</span>text()<span style="color: #333333">.</span>split(<span style="background-color: #fff0f0">','</span>)
<span style="color: #008800; font-weight: bold">try</span>:
x <span style="color: #333333">=</span> <span style="color: #007020">float</span>(pt[<span style="color: #0000DD; font-weight: bold">0</span>])
y <span style="color: #333333">=</span> <span style="color: #007020">float</span>(pt[<span style="color: #0000DD; font-weight: bold">1</span>])
point <span style="color: #333333">=</span> QgsPointXY(x,y)
<span style="color: #008800; font-weight: bold">if</span> d[<span style="color: #0000DD; font-weight: bold">0</span>] <span style="color: #333333">!=</span> <span style="color: #0000DD; font-weight: bold">0</span>:
geom <span style="color: #333333">=</span> QgsGeometry<span style="color: #333333">.</span>fromPointXY(point)<span style="color: #333333">.</span>buffer(d[<span style="color: #0000DD; font-weight: bold">0</span>], <span style="color: #333333">-</span><span style="color: #0000DD; font-weight: bold">1</span>)<span style="color: #333333">.</span>asWkt()
epsg <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>sel_proj<span style="color: #333333">.</span>crs()<span style="color: #333333">.</span>postgisSrid()
uri <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"Polygon?crs=epsg:"</span> <span style="color: #333333">+</span> <span style="color: #007020">str</span>(epsg) <span style="color: #333333">+</span> <span style="background-color: #fff0f0">"&field=id:integer""&index=yes"</span>
mem_layer <span style="color: #333333">=</span> QgsVectorLayer(uri,
<span style="background-color: #fff0f0">'circle'</span>,
<span style="background-color: #fff0f0">'memory'</span>)
prov <span style="color: #333333">=</span> mem_layer<span style="color: #333333">.</span>dataProvider()
feat <span style="color: #333333">=</span> QgsFeature()
feat<span style="color: #333333">.</span>setAttributes([<span style="color: #0000DD; font-weight: bold">0</span>])
feat<span style="color: #333333">.</span>setGeometry(QgsGeometry<span style="color: #333333">.</span>fromWkt(geom))
prov<span style="color: #333333">.</span>addFeatures([feat])
QgsProject<span style="color: #333333">.</span>instance()<span style="color: #333333">.</span>addMapLayer(mem_layer)
<span style="color: #008800; font-weight: bold">except</span> <span style="color: #FF0000; font-weight: bold">ValueError</span>:
<span style="color: #008800; font-weight: bold">pass</span>
w <span style="color: #333333">=</span> Dlg()
w<span style="color: #333333">.</span>setWindowTitle(<span style="background-color: #fff0f0">'Geometry Creator from Point'</span>)
w<span style="color: #333333">.</span>setWindowFlags(Qt<span style="color: #333333">.</span>WindowStaysOnTopHint)
w<span style="color: #333333">.</span>move(<span style="color: #0000DD; font-weight: bold">300</span>,<span style="color: #0000DD; font-weight: bold">200</span>)
w<span style="color: #333333">.</span>show()
</pre></td></tr>
</table></div><br />
Cuando se ejecuta el código anterior en la Python Console de QGIS 3, con el ráster de fondo, se obtiene el resultado de la imagen siguiente:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIX1l0VYSoh7YrEFjm7yderxkc1Hy8tZlI8cAMRAOw-Kbb32Mu2CtDk6k6t6Ohyphenhyphen4jhaRM8ziF3hmyXOakwWq47VVQse7toQU8ad_VLzqJ6IjRs-0xx2hOcloRK2DGgOkAC3BUoN9sw8gE/s1600/circle1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIX1l0VYSoh7YrEFjm7yderxkc1Hy8tZlI8cAMRAOw-Kbb32Mu2CtDk6k6t6Ohyphenhyphen4jhaRM8ziF3hmyXOakwWq47VVQse7toQU8ad_VLzqJ6IjRs-0xx2hOcloRK2DGgOkAC3BUoN9sw8gE/s640/circle1.png" width="640" height="390" data-original-width="1600" data-original-height="975" /></a></div><br />
A continuación, se hace click en un punto arbitrario del ráster para registrar las coordenadas, posteriormente click en el botón de "Create Circle" para luego digitar 10000 (radio en metros) en el <b>QFileDialog</b>; tal como se presenta en la imagen a continuación.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhy1-lCKvVO_V0jZmrHsArY1TFyr5gadYeQQ9VhExQCg-PuRLaKKpsqtntxqrEmO9KWC_zQIbxppGaoH9BWqemMdOsVCdLIcr3lXSjKd44fsOpcrtOkItExGY_02_zEhk3RaY6qJyYsJM4/s1600/circle2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhy1-lCKvVO_V0jZmrHsArY1TFyr5gadYeQQ9VhExQCg-PuRLaKKpsqtntxqrEmO9KWC_zQIbxppGaoH9BWqemMdOsVCdLIcr3lXSjKd44fsOpcrtOkItExGY_02_zEhk3RaY6qJyYsJM4/s640/circle2.png" width="640" height="390" data-original-width="1600" data-original-height="975" /></a></div><br />
Después de hacer click en OK, el círculo resultante (como memory layer) puede ser observado en la imagen siguiente:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXhyphenhyphenDNCOU3xuOd6wC5rtKsmBtCTuLj_gtGBIkhDK36OUk1mTSIBJeqCtYMaAPBxl94Sq1GarSF-Hyy0khyqR1oaS2DZobLbte4PljOdO9bviFHX1xbRbk2pl47zO3R5_wnP6pGMlp4WJo/s1600/circle3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXhyphenhyphenDNCOU3xuOd6wC5rtKsmBtCTuLj_gtGBIkhDK36OUk1mTSIBJeqCtYMaAPBxl94Sq1GarSF-Hyy0khyqR1oaS2DZobLbte4PljOdO9bviFHX1xbRbk2pl47zO3R5_wnP6pGMlp4WJo/s640/circle3.png" width="640" height="390" data-original-width="1600" data-original-height="975" /></a></div><br />
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-76103320681593834572020-01-12T21:47:00.002-04:002020-01-15T22:11:52.783-04:00Clase plantilla con QDialog para crear puntos<div style="text-align:justify;"><p>En el <a href="https://blogdezeka.blogspot.com/2020/01/clase-plantilla-con-qdialog-para.html">post anterior</a> se introdujo una Clase plantilla con <b>QDialog</b> para visualizar las coordenadas del Map Canvas de QGIS con un click del ratón. En este post se va a aprovechar la generación de estas coordenadas para producir memory layers de puntos con una función especial conectada a un <b>QPushButton</b>.</p><a name='more'></a>El <b>QDialog</b> incluye un objeto del tipo <b>QgsProjectionSelectionWidget</b> que permite asignar automáticamente la proyección del proyecto al iniciar el <b>QDialog</b> o cambiarla manualmente si es necesario. El código completo se presenta a continuación:<br />
<br />
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><table><tr><td><pre style="margin: 0; line-height: 125%"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73</pre></td><td><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtCore</span> <span style="color: #008800; font-weight: bold">import</span> Qt
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">qgis.gui</span> <span style="color: #008800; font-weight: bold">import</span> QgsMapToolEmitPoint
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">Dlg</span>(QDialog):
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">__init__</span>(<span style="color: #007020">self</span>):
QDialog<span style="color: #333333">.</span>__init__(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout <span style="color: #333333">=</span> QGridLayout(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>label1 <span style="color: #333333">=</span> QLabel(<span style="background-color: #fff0f0">'Coordinates of map'</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>line_edit <span style="color: #333333">=</span> QLineEdit()
<span style="color: #007020">self</span><span style="color: #333333">.</span>line_edit<span style="color: #333333">.</span>setFixedWidth(<span style="color: #0000DD; font-weight: bold">350</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>sel_proj <span style="color: #333333">=</span> QgsProjectionSelectionWidget()
proj <span style="color: #333333">=</span> QgsProject<span style="color: #333333">.</span>instance()<span style="color: #333333">.</span>crs()<span style="color: #333333">.</span>postgisSrid()
crs <span style="color: #333333">=</span> QgsCoordinateReferenceSystem()
crs<span style="color: #333333">.</span>createFromSrid(proj)
<span style="color: #007020">self</span><span style="color: #333333">.</span>sel_proj<span style="color: #333333">.</span>setCrs(crs)
<span style="color: #007020">self</span><span style="color: #333333">.</span>btn1 <span style="color: #333333">=</span> QPushButton(<span style="background-color: #fff0f0">'Create Point'</span>, <span style="color: #007020">self</span>)
<span style="color: #888888"># Save reference to the QGIS interface</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface <span style="color: #333333">=</span> iface
<span style="color: #888888"># a reference to our map canvas</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mapCanvas()
<span style="color: #888888"># this QGIS tool emits as QgsPoint after each click on the map canvas</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>pointTool <span style="color: #333333">=</span> QgsMapToolEmitPoint(<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>label1, <span style="color: #0000DD; font-weight: bold">0</span>, <span style="color: #0000DD; font-weight: bold">0</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>line_edit, <span style="color: #0000DD; font-weight: bold">1</span>, <span style="color: #0000DD; font-weight: bold">0</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>sel_proj, <span style="color: #0000DD; font-weight: bold">2</span>, <span style="color: #0000DD; font-weight: bold">0</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>btn1, <span style="color: #0000DD; font-weight: bold">3</span>, <span style="color: #0000DD; font-weight: bold">0</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>pointTool<span style="color: #333333">.</span>canvasClicked<span style="color: #333333">.</span>connect(<span style="color: #007020">self</span><span style="color: #333333">.</span>display_point)
<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas<span style="color: #333333">.</span>setMapTool(<span style="color: #007020">self</span><span style="color: #333333">.</span>pointTool)
<span style="color: #007020">self</span><span style="color: #333333">.</span>btn1<span style="color: #333333">.</span>clicked<span style="color: #333333">.</span>connect(<span style="color: #007020">self</span><span style="color: #333333">.</span>create_point)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">display_point</span>(<span style="color: #007020">self</span>, point, button):
<span style="color: #888888"># report map coordinates from a canvas click</span>
coords <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"{}, {}"</span><span style="color: #333333">.</span>format(point<span style="color: #333333">.</span>x(), point<span style="color: #333333">.</span>y())
<span style="color: #007020">self</span><span style="color: #333333">.</span>line_edit<span style="color: #333333">.</span>setText(<span style="color: #007020">str</span>(coords))
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">create_point</span>(<span style="color: #007020">self</span>):
pt <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>line_edit<span style="color: #333333">.</span>text()<span style="color: #333333">.</span>split(<span style="background-color: #fff0f0">','</span>)
<span style="color: #008800; font-weight: bold">try</span>:
x <span style="color: #333333">=</span> <span style="color: #007020">float</span>(pt[<span style="color: #0000DD; font-weight: bold">0</span>])
y <span style="color: #333333">=</span> <span style="color: #007020">float</span>(pt[<span style="color: #0000DD; font-weight: bold">1</span>])
point <span style="color: #333333">=</span> QgsPointXY(x,y)
epsg <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>sel_proj<span style="color: #333333">.</span>crs()<span style="color: #333333">.</span>postgisSrid()
uri <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"Point?crs=epsg:"</span> <span style="color: #333333">+</span> <span style="color: #007020">str</span>(epsg) <span style="color: #333333">+</span> <span style="background-color: #fff0f0">"&field=id:integer""&index=yes"</span>
mem_layer <span style="color: #333333">=</span> QgsVectorLayer(uri,
<span style="background-color: #fff0f0">'point'</span>,
<span style="background-color: #fff0f0">'memory'</span>)
prov <span style="color: #333333">=</span> mem_layer<span style="color: #333333">.</span>dataProvider()
feat <span style="color: #333333">=</span> QgsFeature()
feat<span style="color: #333333">.</span>setAttributes([<span style="color: #0000DD; font-weight: bold">0</span>])
feat<span style="color: #333333">.</span>setGeometry(QgsGeometry<span style="color: #333333">.</span>fromPointXY(point))
prov<span style="color: #333333">.</span>addFeatures([feat])
QgsProject<span style="color: #333333">.</span>instance()<span style="color: #333333">.</span>addMapLayer(mem_layer)
<span style="color: #008800; font-weight: bold">except</span> <span style="color: #FF0000; font-weight: bold">ValueError</span>:
<span style="color: #008800; font-weight: bold">pass</span>
w <span style="color: #333333">=</span> Dlg()
w<span style="color: #333333">.</span>setWindowTitle(<span style="background-color: #fff0f0">'Point Creator'</span>)
w<span style="color: #333333">.</span>setWindowFlags(Qt<span style="color: #333333">.</span>WindowStaysOnTopHint)
w<span style="color: #333333">.</span>show()
</pre></td></tr>
</table></div><br />
En la imagen siguiente se observa el <b>QDialog</b>, con sus elementos Qt correspondientes, que genera el código anterior. Una vez ejecutado en la Python Console se han hecho varios clicks del ratón en la zona del ráster; seguido posteriormente de un click en el botón 'Create Point' para producirlos.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLI1PVcmOvAqJjgy7vDZghP1szeY5pP9laXTT4MTIqsrI-Wg8_3gzATH0bJrNs6VKfnQraY9rlo7KYrZgIM72KGr8uaaZSD-7cyUbUUn7VYStge5Q9JDElOgMNWTa-SZzo-Bxo8Q_B86Q/s1600/points1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLI1PVcmOvAqJjgy7vDZghP1szeY5pP9laXTT4MTIqsrI-Wg8_3gzATH0bJrNs6VKfnQraY9rlo7KYrZgIM72KGr8uaaZSD-7cyUbUUn7VYStge5Q9JDElOgMNWTa-SZzo-Bxo8Q_B86Q/s640/points1.png" width="640" height="391" data-original-width="1600" data-original-height="978" /></a></div><br />
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-77965122635155347782020-01-12T00:04:00.002-04:002020-01-12T00:04:41.015-04:00Clase plantilla con QDialog para visualizar las coordenadas del Map Canvas de QGIS con un click del ratón<div style="text-align:justify;"><p>En posts anteriores (<a href="https://blogdezeka.blogspot.com/2018/03/obtener-coordenadas-del-movimiento-del.html">1</a>, <a href="http://blogdezeka.blogspot.com/2017/07/obtener-coordenadas-de-un-click-del.html">2</a>, <a href="http://blogdezeka.blogspot.com/2017/06/obtener-el-valor-de-un-atributo-de-una.html">3</a>) se hizo referencia a la obtención de las coordenadas del Map Canvas de QGIS con un click del ratón mediante la clase <b>QgsMapToolEmitPoint</b> de PyQGIS. En esta nueva entrega vamos a emplear la simplificación producto de la utilización de una <a href="https://blogdezeka.blogspot.com/2020/01/plantilla-para-visualizar-elementos-de.html">clase plantilla</a> con <b>QDialog</b> para el mismo fin.</p><a name='more'></a>El código producido se encuentra a continuación:<br />
<br />
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><table><tr><td><pre style="margin: 0; line-height: 125%"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35</pre></td><td><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtCore</span> <span style="color: #008800; font-weight: bold">import</span> Qt
<span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">qgis.gui</span> <span style="color: #008800; font-weight: bold">import</span> QgsMapToolEmitPoint
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">Dlg</span>(QDialog):
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">__init__</span>(<span style="color: #007020">self</span>):
QDialog<span style="color: #333333">.</span>__init__(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout <span style="color: #333333">=</span> QGridLayout(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>label1 <span style="color: #333333">=</span> QLabel(<span style="background-color: #fff0f0">'Coordinates of map'</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>line_edit <span style="color: #333333">=</span> QLineEdit()
<span style="color: #007020">self</span><span style="color: #333333">.</span>line_edit<span style="color: #333333">.</span>setFixedWidth(<span style="color: #0000DD; font-weight: bold">350</span>)
<span style="color: #888888"># Save reference to the QGIS interface</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>iface <span style="color: #333333">=</span> iface
<span style="color: #888888"># a reference to our map canvas</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas <span style="color: #333333">=</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>iface<span style="color: #333333">.</span>mapCanvas()
<span style="color: #888888"># this QGIS tool emits as QgsPoint after each click on the map canvas</span>
<span style="color: #007020">self</span><span style="color: #333333">.</span>pointTool <span style="color: #333333">=</span> QgsMapToolEmitPoint(<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>label1, <span style="color: #0000DD; font-weight: bold">0</span>, <span style="color: #0000DD; font-weight: bold">0</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>line_edit, <span style="color: #0000DD; font-weight: bold">1</span>, <span style="color: #0000DD; font-weight: bold">0</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>pointTool<span style="color: #333333">.</span>canvasClicked<span style="color: #333333">.</span>connect(<span style="color: #007020">self</span><span style="color: #333333">.</span>display_point)
<span style="color: #007020">self</span><span style="color: #333333">.</span>canvas<span style="color: #333333">.</span>setMapTool(<span style="color: #007020">self</span><span style="color: #333333">.</span>pointTool)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">display_point</span>(<span style="color: #007020">self</span>, point, button):
<span style="color: #888888"># report map coordinates from a canvas click</span>
coords <span style="color: #333333">=</span> <span style="background-color: #fff0f0">"{}, {}"</span><span style="color: #333333">.</span>format(point<span style="color: #333333">.</span>x(), point<span style="color: #333333">.</span>y())
<span style="color: #007020">self</span><span style="color: #333333">.</span>line_edit<span style="color: #333333">.</span>setText(<span style="color: #007020">str</span>(coords))
w <span style="color: #333333">=</span> Dlg()
w<span style="color: #333333">.</span>setWindowTitle(<span style="background-color: #fff0f0">'Map Canvas Coordinates Visor'</span>)
w<span style="color: #333333">.</span>setWindowFlags(Qt<span style="color: #333333">.</span>WindowStaysOnTopHint)
w<span style="color: #333333">.</span>show()
</pre></td></tr></table></div><br />
Después de ejecutado el script anterior en la Python Console de QGIS, el resultado puede ser visualizado en la imagen siguiente. Cada click del ratón con el ráster de referencia observado abajo permite recuperar en la <b>QLineEdit</b> embebida en el <b>QDialog</b> las coordenadas correspondientes del Map Canvas.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgamJZX0ULh4webjqxn5oEzibPTL7X7rIc9A-iCmJ5fsUDZMFvtpvH4zRUIbjjxpJGcbs9vuYkF9sdNO5ismo3Ia5SFQKXyJN-pHDXlhpk-7Fqqk30P8SwwSDkj_q4_7N4StjLLiBjBcQs/s1600/click1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgamJZX0ULh4webjqxn5oEzibPTL7X7rIc9A-iCmJ5fsUDZMFvtpvH4zRUIbjjxpJGcbs9vuYkF9sdNO5ismo3Ia5SFQKXyJN-pHDXlhpk-7Fqqk30P8SwwSDkj_q4_7N4StjLLiBjBcQs/s640/click1.png" width="640" height="391" data-original-width="1600" data-original-height="977" /></a></div><br />
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0tag:blogger.com,1999:blog-5109184980422842703.post-46241572328081442342020-01-11T11:20:00.000-04:002020-01-11T11:20:07.385-04:00Plantilla para visualizar elementos de un QDialog con PyQGIS<div style="text-align:justify;"><p>Aunque con la Python Console es posible visualizar de manera independiente muchos de los diferentes elementos Qt presentes en QGIS, con muy pocas líneas de código también se puede crear una clase "plantilla" para incluir varios de ellos y visualizarlos a todos de manera simultánea antes de crear un plugin. La clase <b>Dlg</b> que se va a proponer a continuación emplea un objeto <b>QDialog</b> al cual se le incorpora una <b>QgsComboBox</b> y una <b>QListWidget</b>.</p><a name='more'></a>La Combo Box emplea un filtro para seleccionar sólo las capas vectoriales e imprimir en la <b>QListWidget</b> el nombre de los campos y seleccionarlos de manera múltiple activando el modo 'ExtendedSelection'. Cuando se selecciona otra capa vectorial en la Combo Box la función 'changed_layer' permite imprimir los campos correspondientes a la nueva capa y borrar los anteriores. <br />
<br />
El código completo se incluye a continuación:<br />
<br />
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><table><tr><td><pre style="margin: 0; line-height: 125%"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25</pre></td><td><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">PyQt5.QtCore</span> <span style="color: #008800; font-weight: bold">import</span> Qt
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">Dlg</span>(QDialog):
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">__init__</span>(<span style="color: #007020">self</span>):
QDialog<span style="color: #333333">.</span>__init__(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout <span style="color: #333333">=</span> QGridLayout(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>cb_layer <span style="color: #333333">=</span> QgsMapLayerComboBox()
<span style="color: #007020">self</span><span style="color: #333333">.</span>cb_layer<span style="color: #333333">.</span>setFilters(QgsMapLayerProxyModel<span style="color: #333333">.</span>VectorLayer)
<span style="color: #007020">self</span><span style="color: #333333">.</span>cb_layer<span style="color: #333333">.</span>layerChanged<span style="color: #333333">.</span>connect(<span style="color: #007020">self</span><span style="color: #333333">.</span>layer_changed)
<span style="color: #007020">self</span><span style="color: #333333">.</span>fields_list <span style="color: #333333">=</span> QListWidget(<span style="color: #007020">self</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>fields_list<span style="color: #333333">.</span>setSelectionMode(QListWidget<span style="color: #333333">.</span>ExtendedSelection)
<span style="color: #008800; font-weight: bold">if</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>cb_layer<span style="color: #333333">.</span>currentLayer() <span style="color: #000000; font-weight: bold">is</span> <span style="color: #000000; font-weight: bold">not</span> <span style="color: #007020">None</span>:
<span style="color: #007020">self</span><span style="color: #333333">.</span>fields_list<span style="color: #333333">.</span>addItems([f<span style="color: #333333">.</span>name() <span style="color: #008800; font-weight: bold">for</span> f <span style="color: #000000; font-weight: bold">in</span> <span style="color: #007020">self</span><span style="color: #333333">.</span>cb_layer<span style="color: #333333">.</span>currentLayer()<span style="color: #333333">.</span>fields() ])
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>cb_layer, <span style="color: #0000DD; font-weight: bold">0</span>, <span style="color: #0000DD; font-weight: bold">0</span>)
<span style="color: #007020">self</span><span style="color: #333333">.</span>layout<span style="color: #333333">.</span>addWidget(<span style="color: #007020">self</span><span style="color: #333333">.</span>fields_list, <span style="color: #0000DD; font-weight: bold">1</span>, <span style="color: #0000DD; font-weight: bold">0</span>)
<span style="color: #008800; font-weight: bold">def</span> <span style="color: #0066BB; font-weight: bold">layer_changed</span>(<span style="color: #007020">self</span>, layer):
<span style="color: #007020">self</span><span style="color: #333333">.</span>fields_list<span style="color: #333333">.</span>clear()
fields <span style="color: #333333">=</span> [f<span style="color: #333333">.</span>name() <span style="color: #008800; font-weight: bold">for</span> f <span style="color: #000000; font-weight: bold">in</span> layer<span style="color: #333333">.</span>fields()]
<span style="color: #007020">self</span><span style="color: #333333">.</span>fields_list<span style="color: #333333">.</span>addItems(fields)
w <span style="color: #333333">=</span> Dlg()
w<span style="color: #333333">.</span>setWindowFlags(Qt<span style="color: #333333">.</span>WindowStaysOnTopHint)
w<span style="color: #333333">.</span>show()
</pre></td></tr></table></div><br />
Al ejecutar el código anterior en la Python Console el resultado se observa en la imagen siguiente. El <b>QDialog</b> incluye la <b>QgsComboBox</b> y la <b>QListWidget</b>. Los campos impresos en la <b>QlistWidget</b> corresponden a la capa <b>polygon8</b> donde se han seleccionado arbitrariamente algunos de ellos (resaltado en azul).<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZOUZIcQv2N0TUQRJqhAgUssKNEvHT3uAOP8XobD5amzVxgUolR5zjtxP2p4c09uFQM_n6SFuAPUt6nHVEcLsu35KuNttf621OwRlyhM4tRigqKOIx0t1OODhkdJKhE9LtrQZYdbzO8Q4/s1600/dialog1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZOUZIcQv2N0TUQRJqhAgUssKNEvHT3uAOP8XobD5amzVxgUolR5zjtxP2p4c09uFQM_n6SFuAPUt6nHVEcLsu35KuNttf621OwRlyhM4tRigqKOIx0t1OODhkdJKhE9LtrQZYdbzO8Q4/s640/dialog1.png" width="640" height="391" data-original-width="1600" data-original-height="977" /></a></div><br />
<br />
</div>José Guerrerohttp://www.blogger.com/profile/09671811374386414552noreply@blogger.com0