Macro Z Height Map/it

Icona macro generica. Crea la tua icona personale con lo stesso nome della macro Macro Z Height Map

Descrizione
Trasforma un scala di grigi in una mappa in z.

Versione macro: 0.1
Ultima modifica: 28-08-2022
Autore: heda
Autore
heda
Download
None
Link
Versione macro
0.1
Data ultima modifica
28-08-2022
Versioni di FreeCAD
None
Scorciatoia
Nessuna
Vedere anche
Nessuno

Descrizione

Crea una mappa di quote in altezza da una scala di grigi ricavata da tutti gli oggetti visibili con un volume nel documento attivo. Non esiste una GUI, le opzioni possono essere impostate nel file macro, il file immagine viene salvato con il nome del documento.

Utilizzo

Eseguire la macro con un documento aperto.

Installazione

Tramite Addon manager.

Link

Forum: nessun thread dedicato, ma è nato da questo forum post.

Versione

v0.1 2022-08-28 : primo rilascio

Script

Macro_Z_height_map.FCMacro

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# ***************************************************************************
# *   Copyright (c) 2022 heda <heda @ freecad forum>                        *
# *                                                                         *
# *   This file is part of the FreeCAD CAx development system.              *
# *                                                                         *
# *   This program is free software; you can redistribute it and/or modify  *
# *   it under the terms of the GNU Lesser General Public License (LGPL)    *
# *   as published by the Free Software Foundation; either version 2 of     *
# *   the License, or (at your option) any later version.                   *
# *   for detail see the LICENCE text file.                                 *
# *                                                                         *
# *   This program is distributed in the hope that it will be useful,       *
# *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
# *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
# *   GNU Library General Public License for more details.                  *
# *                                                                         *
# *   You should have received a copy of the GNU Library General Public     *
# *   License along with this program; if not, write to the Free Software   *
# *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
# *   USA                                                                   *
# *                                                                         *
# ***************************************************************************


__Name__ = 'Z_height_map'
__Comment__ = 'Makes a grayscale heightmap in z'
__Author__ = 'heda @ fc-forum'
__Version__ = '0.1'
__Date__ = '2022-08-28'
__License__ = 'LGPL-2.0-or-later'
__Web__ = ''
__Wiki__ = 'https://wiki.freecad.org/Macro_Z_height_map'
__Icon__ = ''
__Help__ = 'Run macro and heightmap is created.'
__Status__ = 'Stable'
__Requires__ = 'tested on FreeCAD v0.20'
__Communication__ = 'forum'
__Files__ = ''


__doc__ = """
Makes the grayscale height map for all visible root objects with a volume
from the active document.

No gui, options can be set in macro-file.

png file saved with document name.
"""

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

pxpmm = 1 # pixels per mm
# adjust pxpmm up/down if there are bands in the heightmap
pad = 2
grayscale_compress = 0.1 # range 0 - 1
invert = False # grayscale, high is white with False

IMSHOW = True
IMSAVE = True
IMRESIZE = False # only saved pil-image, quicker than increase of pxpmm
imwidth = 500 # resizing does give artefacts, can change interpolation...

doc = App.ActiveDocument

shapes = list()
for obj in doc.Objects:
    if hasattr(obj, 'Shape'):
        if hasattr(obj.Shape, 'Volume'):
            if obj.Shape.Volume > 0:
                if obj.ViewObject.Visibility:
                    shapes.append(obj.Shape)

xmin, ymin, zmin =  (min((getattr(shp.BoundBox, f'{which}Min')
                          for shp in shapes)) for which in 'XYZ')
xmax, ymax, zmax =  (max((getattr(shp.BoundBox, f'{which}Max')
                          for shp in shapes)) for which in 'XYZ')

xspan, yspan, zspan = xmax - xmin, ymax - ymin, zmax - zmin
w, h = (int(span * pxpmm) for span in (xspan, yspan))
pic = np.zeros((w + 1, h + 1, len(shapes)))

print('w x h --> {} x {}'.format(w, h))
print('working on pixels, might take a while...')

for i, shape in enumerate(shapes):
    pv = shape.getPoints(1/pxpmm)
    zpoints = (p for p, v in zip(*pv) if v.z > 0)
    for zpoint in zpoints:
        x = round((zpoint.x - xmin) / xspan * w)
        y = round((zpoint.y - ymin) / yspan * h)
        pic[x, y, i] = zpoint.z

print('pic loop done')

pic = (pic.max(axis=2) - zmin) / zspan
im = np.zeros((w + 1 + 2 * pad, h + 1 + 2 * pad))
pic = (1 - grayscale_compress) * pic + grayscale_compress
im[pad:pad + w + 1, pad:pad + h + 1] = pic
im = (im.T * 255).astype(np.uint8)
h, w = im.shape

if invert:
    im = 255 - im
    print('grayscale inverted')

if IMSHOW:
    plt.imshow(im, cmap='gray', interpolation='none')
    plt.grid(color='r')
    plt.show()

if IMSAVE:
    with Image.fromarray(im, mode='L') as pim:
        if IMRESIZE:
            pim = pim.resize((imwidth, int(h * imwidth / w)),
                             Image.Resampling.LANCZOS)
            print('resized to:', pim.size)
        pim.save('{}.png'.format(doc.Name), mode='L')

print('height map done')