14
Equivalent JS de la fonction Python int()
Javascript, Web
23 mar 2018
function int(n) {
    n = Math.round(n);

    if(!isNaN(n)){
        return n;
    } else { return 0; }
}

Si on est joueur, on peut (fin 2018) déjà utiliser les nouvelles fonctionnalités Javascript de l'élément Number pour tester si on a bien un entier, via Number.isInteger(n), voir cette doc. Attention, il n'y par exemple pas de support Internet Explorer, ni navigateur BlackBerry OS.

13
Utiliser HERE Maps comme fournisseur de tuiles avec Leaflet
Web, Javascript
10 nov 2018

Une bonne alternative aux fournisseurs habituels que sont Google Maps ou OpenStreetMaps est Here Maps (ex-Nokia, aujourd'hui détenu par les constructeurs automobile allemands, ). D'expérience c'est un peu plus lent que Google Maps mais on évite la publicité déguisée. Les cartes sont claires et le graphisme élégant.

var HereMaps = L.tileLayer('https://{s}.base.maps.api.here.com/maptile/2.1/maptile/newest/pedestrian.day/{z}/{x}/{y}/256/png8?app_id=bC4fb9WQfCCZfkxspD4z&app_code=K2Cpd_EKDzrZb1tz0zdpeQ&lg=fre&ppi=72&pview=DEF', {
    maxZoom: 20,
    subdomains:['1','2','3','4'],
    attribution: '© HERE'
});

HereMaps.addTo(map);

Plus d'information sur la construction de la requète, voir la documentation de HERE.

Les codes (jeton) API app_code et app_id utilisés ici sont ceux de la carte de la page d'accueil de HERE. C'est très probablement interdit de l'utiliser pour vos projets et risque de changer dans le temps. A noter que HERE propose un service gratuit sous 250 000 transactions par an pour vous procurer vos propres codes.

Pour info, pour récupérer les codes API courants de la carte publique HERE, le plus simple est d'écouter les requêtes serveurs en naviguant sur la page. Faites Ctrl+Maj+I, onglet Réseau, déplacez vous sur la carte et regardez les adresses des tuiles qui chargent.

12
Commande Rhino équivalente au MatchProperties d'Autocad
Python, Rhino3D
24 oct 2018
import rhinoscriptsyntax as rs

def acadMatch(source):
    rs.Command("_SelWindow")

    targets = rs.SelectedObjects()
    if targets:
        rs.MatchObjectAttributes(targets, source)
        rs.UnselectAllObjects()
        acadMatch(source)
    else:
        print "No target object found."

sources = rs.SelectedObjects()
if len(sources) > 0:
    source = sources[0]
else:
    source = rs.GetObject("Select source object")

if source:
    rs.UnselectAllObjects()
    acadMatch(source)
else:
    print "No source object found."

A ajouter dans un bouton (voir article. On peut même prendre l'icône d'Autocad pour faire encore plus vrai.

11
Triangulation de Delaunay entre des points dans QGIS
Python, Qgis
13 juil 2018

Au travers de l'interface Python, on peut construire une triangulation de Delaunay entre des points QGIS. Ou plutôt : on ne peut pas directement – du moins pas à ma connaissance – mais on peut faire appel à librairie externe qui sait le faire.

Triangulation de Delaunay entre des points
Triangulation de Delaunay entre des points

C'est légèrement bricolé, mais efficace. J'utilise les fonctions du projet delaunay de Peter Beard. On a besoin ici uniquement du fichier geometry.py qui contient les routines géométriques nécessaires. Pour faire appel à ces fonctions dans pyQGIS, il faut placer le fichier dans le dossier lib de l'installation Python de QGIS. Sous Windows et si vous avez installé QGIS via OSGeo, ce sera ici C:\OSGeo4W64\apps\Python27\Lib.

Ci-dessous le code d'une utilisation typique

# coding: utf8

from qgis.core import *
from qgis.gui import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *

import math
from geometry import *
# by Peter Beard, https://github.com/PeterBeard/delaunay
# to import Python external library to QGIS, put the .py (here geometry.py) file in C:\OSGeo4W64\apps\Python27\Lib

inputPts = [QgsPoint(7.7,48.6), QgsPoint(2.3,48.9), QgsPoint(4.3,50.8), QgsPoint(13.4,52.5), QgsPoint(12.6,55.7), QgsPoint(-0.1,51.5), QgsPoint(5.4,43.3)]
#Qgis Point objects (Strasbourg, Paris, Berlin, Copenhagen, London, Marseille)


# Translate Points (Qgis Point objects) into geometry.py points

delaunayPts = []
for pt in inputPts:
    geometryPoint = Point(pt.x(), pt.y())
    delaunayPts.append(geometryPoint)

delaunayTriangles = delaunay_triangulation(delaunayPts) #returns geometry.py Triangle objects


# Get lines from group of Delaunay triangles

delaunayLines = [] #Pairs (here tuples) of Qgis Point objects (start and end of line)

for triangle in delaunayTriangles:
    pointA = QgsPoint(triangle[0].x, triangle[0].y)
    pointB = QgsPoint(triangle[1].x, triangle[1].y)
    pointC = QgsPoint(triangle[2].x, triangle[2].y)

    if pointA in inputPts and pointB in inputPts:
    #excludes automatically created bounding points from geometry.py

        lineA = (pointA, pointB)
        delaunayLines.append(lineA)

    if pointA in inputPts and pointC in inputPts:
        lineB = (pointA, pointC)
        delaunayLines.append(lineB)

    if pointB in inputPts and pointC in inputPts:
        lineC = (pointB, pointC)
        delaunayLines.append(lineC)


# Delete duplicates

def removeTupleDuplicatesinArray(array):
    duplicateFreeArray = []

    for t in array:
        if (t[0],t[1]) not in duplicateFreeArray and (t[1],t[0]) not in duplicateFreeArray:
            duplicateFreeArray.append(t)
    return duplicateFreeArray

delaunayLines = removeTupleDuplicatesinArray(delaunayLines)


# Preview lines

for line in delaunayLines:
    rb = QgsRubberBand( qgis.utils.iface.mapCanvas(), True )
    rb.setColor (Qt.blue)
    rb.addPoint(QgsPoint(line[0].x(), line[0].y()))
    rb.addPoint(QgsPoint(line[1].x(), line[1].y()))
10
Ajouter des règles CSS (en CSS !) à une page via Javascript
Javascript, Web
11 juin 2018

Evite de devoir retraduire en instructions purement Javascript. Ajoute au DOM un élément <style>.

var cssRules = "body{background-color: rgba(150,200,200,1);} div{border: .5vw white solid;} p{text-size: 10vw; color: white;}";

var style = document.createElement("style");
style.type = "text/css";
style.appendChild(document.createTextNode(cssRules));

document.head.appendChild(style);

Attention au formatage des règles CSS (sauts de ligne, apostrophes, ...) si l'on reprend son code depuis un fichier CSS.

9
Rogner plusieurs images d'un coup avec ImageMagick
Windows
5 mai 2018

Pour automatiser le rognage d'une série d'images, par exemple pour enlever le filigrane (logo), on peut utiliser les exécutables de ImageMagick. Pour utiliser ImageMagick sur Windows, le plus simple est de télécharger la version portable du logiciel et de placer les fichiers téléchargés dans un dossier qui contient les images à traiter.

Dans l'invité de commande (~Terminal), on va ensuite chercher ce dossier pour faire appel aux fonctionnalités. Pour faire propre, je garde le dossier ImageMagick comme sous-dossier de mon répertoire de travail contentenant les images. Ici je l'ai renommé im, d'où la commande suivante.

im\convert *.jpg -crop 1920x1000+0+0 converted_%04d.jpg

Dans cet exemple, 1920 par 1000px sera la taille finale de toutes les images, avec le rognage démarré en haut à gauche.

8
Plaquer des objets sur une surface avec Rhino Python
Python, Rhino3D
1er mai 2017
PutOnSurface.py démo

Script permettant de faire « tomber » des objets sur une face, c'est à dire les placer automatiquement au point d'intersection avec la surface, comme s'ils étaient physiquement posés dessus. L'intersection se calcule verticalement (vecteur Z) mais on peut choisir d'utiliser le z d'un plan de construction. On a également la possibilité d'ajouter une marge supplémentaire (offset) à la chute pour masquer certaines parties de l'objet (racines d'un arbre par exemple).

import rhinoscriptsyntax as rs

objectIds = rs.GetObjects("Select objects")
projectionSrfId = rs.GetObject("Select surface or polysurface to project to", rs.filter.polysurface | rs.filter.surface)

planes = []
planes.append("WorldXY") # add World XY

cplanes = rs.NamedCPlanes() # add named CPlanes
if cplanes:
    for cplane in cplanes:
        planes.append(cplane)

projectionPlane = rs.GetString("Plane to use for direction of projection (World or named CPlanes)", "WorldXY", planes)
offset = rs.GetReal("z Offset", 0)

if projectionSrfId:
    if objectIds:
        for objectId in objectIds:
            box = rs.BoundingBox(objectId,rs.NamedCPlane(projectionPlane), True) #if CPlane name is not found, falls back on WorldXY

            if box:
                bottomRightPt = [0,0,0]
                topLeftPt = [0,0,0]
                bottomLeftPt = [0,0,0]
                for i, point in enumerate(box):
                    if i==1:
                        bottomRightPt = point
                    if i==7:
                        topLeftPt = point
                    if i==3:
                        bottomLeftPt = point
                diagonal = rs.AddLine(topLeftPt, bottomRightPt)
                centroidPt = rs.CurveMidPoint(diagonal)
                rs.DeleteObject(diagonal)

                zVector = rs.VectorCreate(bottomLeftPt, topLeftPt)
                zVector = rs.VectorDivide(zVector, 2)
                zVectorU = rs.VectorUnitize(zVector)
                offsetVector = rs.VectorScale(zVectorU,-offset)

                bottomCentroidPt = [centroidPt[0] + zVector[0], centroidPt[1] + zVector[1], centroidPt[2] + zVector[2]]

                projectedPts = rs.ProjectPointToSurface(bottomCentroidPt, projectionSrfId, zVector)

                if projectedPts:
                    nearestProjectedPtId = rs.PointArrayClosestPoint(projectedPts, bottomCentroidPt)
                    destinationPt = projectedPts[nearestProjectedPtId]
                    rs.AddPoint(destinationPt)

                    projectVector = rs.VectorCreate(destinationPt,bottomCentroidPt)
                    if offset != 0:
                        projectVector = rs.VectorAdd(projectVector,offsetVector)
                    rs.MoveObject(objectId, projectVector)
                else:
                    print "Object cannot be projected on surface."
            else:
                print "Bounding-boxes couldn't be created."

    else:
        print "No object selected."
else:
    print "No surface selected."
7
Nettoyer le Rubberband de PyQGIS
Qgis, Python
18 mar 2016

Avec PyQGIS on fait souvent appel à l'élément RubberBand en phase de test pour afficher un aperçu de ce que l'on calcule. Le problème c'est qu'il reste affiché d'une exécution du code à l'autre. C'est alors pratique d'une cette fonction, à lancer en début de script, pour nettoyer ces « élastiques » avant chaque nouveau lancement.

def removeRubberbands():
    rbb_items = [ i for i in iface.mapCanvas().scene().items() if issubclass(type(i), qgis.gui.QgsRubberBand)]

    for rbb in rbb_items:
        if rbb in iface.mapCanvas().scene().items():
            iface.mapCanvas().scene().removeItem(rbb)
6
Filtrer les clés d'une archive OSM
Qgis, Osm
16 nov 2016

Dans cette note j'expliquais comme on peut réduire à une zone un fichier OSM. De même il est souvent utile de réduire ce fichier aux clés qui nous intéressent uniquement. Pour ce faire, on a le programme osmfilter.

C'est un exécutable qui s'utilise de la même manière que osmconvert, via l'invité de commande en plaçant le programme et le fichier OSM dans le même dossier.

Pour sélectionner les clés OSM, vous pouvez consultez la liste des contenus OpenStreetMaps avec leur nom. Dans mon cas je veux extraire uniquement les villages et hameaux, soit les entrées place:village et place:hamlet. La commande pour mon fichier OSM pour le Luberon sera :

osmfilter luberon.osm --keep="place=village place=hamlet" -o=luberon_village_hamlet.osm

On peut utiliser un astérisque pour pour prendre toute les valeurs d'une clé. Pour toutes les place par exemple on écrira -keep="place=*".

Une fonction autre utile de ce programme permet de lister les clés présentes sur un fichier avec leur quantité. On utilisera la commande suivante :

osmfilter luberon.osm --out-count

On peut également regarder à l'intérieur d'une clé, ici place

osmfilter luberon.osm --out-count=place

Pour ceux qui utilisent l'invité de commande natif de Windows, vous serez peut-être embettez par les très longues listes de clés si vous appliquez la fonction à un fichier OSM complet. La barre de défilement va être bloquée à un certain niveau. Pour visualiser la totalité de la liste, vous devrez utiliser un autre invité de commande, comme ComEmu.

5
Importer des données OSM dans QGIS
Osm, Qgis
9 nov 2016

QGIS s'utilise très bien avec OpenStreetMaps mais pour importer ses données OSM dans QGIS, ce n'est pas aussi direct qu'on pourrait le penser.

La première étape consiste à se procurer des données OSM brutes, via les extraits Geofabrik. L'extension qui nous intéresse est .osm.pbf. Choissez la zone la plus réduite possible selon vos besoins. Les fichiers sont lourds et on a tout à gagner à travailler avec des zones resserrées. Pour affiner son fichier, on peut encore réduire à un cadre géographique précis ou filtrer les clés qui nous intéressent.

En utilisant osmconvert on convertit l'archive OSM .osm.pbf en .osm (décompressé) via la commande suivante :

osmconvert alsace-latest.osm.pbf -o=alsace-latest.osm

Pour importer ce fichier dans QGIS, on va dans Vecteur > OpenStreetMaps > Importer la topologie depuis un XML. Sélectionnez votre fichier .osm et faites OK, puis Fermer. Cette opération créera une base de donnée lisible par QGIS de votre fichier sous l'extension .osm.db.

Pour afficher cette base de donnée sur votre carte, cherchez Vecteur > OpenStreetMaps > Exporter la topologie OSM vers Spatialite. Sélectionnez le fichier .osm.db, cliquez sur Charger depuis une base pour afficher les étiquettes disponibles. Faites votre choix, séléctionnez un type d'export et cliquez sur OK.

Si vous avez des difficultés avec la projection, sachez qu'OpenStreetMaps utilise Pseudo-Mercator, code EPSG:3857.