[Bf-extensions-cvs] [be74fdaf] master: io_convert_image_to_mesh_img: moved to contrib: T63750

meta-androcto noreply at git.blender.org
Fri May 24 03:45:09 CEST 2019


Commit: be74fdaf30e62a008fb1727cde59eef5dbf34c14
Author: meta-androcto
Date:   Fri May 24 11:44:40 2019 +1000
Branches: master
https://developer.blender.org/rBACbe74fdaf30e62a008fb1727cde59eef5dbf34c14

io_convert_image_to_mesh_img: moved to contrib: T63750

===================================================================

A	io_convert_image_to_mesh_img/__init__.py
A	io_convert_image_to_mesh_img/mesh/__init__.py
A	io_convert_image_to_mesh_img/mesh/dtm.py
A	io_convert_image_to_mesh_img/mesh/terrain.py
A	io_convert_image_to_mesh_img/mesh/triangulate.py
A	io_convert_image_to_mesh_img/pvl/__init__.py
A	io_convert_image_to_mesh_img/pvl/label.py
A	io_convert_image_to_mesh_img/pvl/parse.py
A	io_convert_image_to_mesh_img/pvl/patterns.py
A	io_convert_image_to_mesh_img/ui/__init__.py
A	io_convert_image_to_mesh_img/ui/importer.py
A	io_convert_image_to_mesh_img/ui/terrainpanel.py

===================================================================

diff --git a/io_convert_image_to_mesh_img/__init__.py b/io_convert_image_to_mesh_img/__init__.py
new file mode 100644
index 00000000..a884fb90
--- /dev/null
+++ b/io_convert_image_to_mesh_img/__init__.py
@@ -0,0 +1,63 @@
+# This file is a part of the HiRISE DTM Importer for Blender
+#
+# Copyright (C) 2017 Arizona Board of Regents on behalf of the Planetary Image
+# Research Laboratory, Lunar and Planetary Laboratory at the University of
+# Arizona.
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# 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 General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""A HiRISE DTM Importer for Blender"""
+
+bl_info = {
+    "name": "HiRISE DTM Importer",
+    "author": "Nicholas Wolf (nicwolf at pirl.lpl.arizona.edu)",
+    "version": (0, 2, 2),
+    "blender": (2, 78, 0),
+    "location": "File > Import > HiRISE DTM (.img)",
+    "description": "Import a HiRISE DTM as a mesh",
+    "warning": "May consume a lot of memory",
+    "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/"
+                "Scripts/Import-Export/HiRISE_DTM_from_PDS_IMG",
+    "category": "Import-Export",
+}
+
+if "bpy" in locals():
+    import importlib
+    importlib.reload(importer)
+    importlib.reload(terrainpanel)
+
+else:
+    from .ui import importer
+    from .ui import terrainpanel
+
+import bpy
+
+
+def menu_import(self, context):
+    i = importer.ImportHiRISETerrain
+    self.layout.operator(i.bl_idname, text=i.bl_label)
+
+
+def register():
+    bpy.utils.register_module(__name__)
+    bpy.types.TOPBAR_MT_file_import.append(menu_import)
+
+
+def unregister():
+    bpy.utils.unregister_module(__name__)
+    bpy.types.TOPBAR_MT_file_import.remove(menu_import)
+
+
+if __name__ == '__main__':
+    register()
diff --git a/io_convert_image_to_mesh_img/mesh/__init__.py b/io_convert_image_to_mesh_img/mesh/__init__.py
new file mode 100644
index 00000000..edbc8c88
--- /dev/null
+++ b/io_convert_image_to_mesh_img/mesh/__init__.py
@@ -0,0 +1,25 @@
+# This file is a part of the HiRISE DTM Importer for Blender
+#
+# Copyright (C) 2017 Arizona Board of Regents on behalf of the Planetary Image
+# Research Laboratory, Lunar and Planetary Laboratory at the University of
+# Arizona.
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# 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 General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""A sub-package for loading DTMs as 3D models"""
+
+from . import dtm
+from . import terrain
+
+__all__ = ['dtm', 'terrain', ]
diff --git a/io_convert_image_to_mesh_img/mesh/dtm.py b/io_convert_image_to_mesh_img/mesh/dtm.py
new file mode 100644
index 00000000..a6ab6e30
--- /dev/null
+++ b/io_convert_image_to_mesh_img/mesh/dtm.py
@@ -0,0 +1,219 @@
+# This file is a part of the HiRISE DTM Importer for Blender
+#
+# Copyright (C) 2017 Arizona Board of Regents on behalf of the Planetary Image
+# Research Laboratory, Lunar and Planetary Laboratory at the University of
+# Arizona.
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# 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 General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""Objects for importing HiRISE DTMs."""
+
+import numpy as np
+
+from .. import pvl
+
+
+class DTM:
+    """
+    HiRISE Digital Terrain Model
+
+    This class imports a HiRISE DTM from a Planetary Data Systems (PDS)
+    compliant .IMG file.
+
+    Parameters
+    ----------
+    path : str
+    terrain_resolution : float, optional
+        Controls the resolution the DTM is read at. This should be a float
+        in the range [0.01, 1.0] (and will be constrained to this range). A
+        value of 1.0 will result in the DTM being read at full resolution. A
+        value of 0.01 will result in the DTM being read at 1/100th resolution.
+        Default is 1.0 (no downsampling).
+
+    Todo
+    ----
+    * Use GDAL for importing the DTM if it is installed for this Python
+      environment. If/when I have the time to do this, it probably
+      warrants breaking out separate importer classes. The benefits of
+      doing this are pretty substantial, though:
+
+        + More reliable (doesn't rely on my PVL parser for finding the
+          valid values in the DTM, for locating the starting position of
+          the elevation data in the .IMG file)
+
+        + Other, better, downsampling algorithms are already built in.
+
+        + Would make this much better at general PDS DTM importing,
+          currently some of the import code is specific to HiRISE DTMs.
+
+    """
+
+    # Special constants in our data:
+    #     NULL : No data at this point.
+    #     LRS  : Low Representation Saturation
+    #     LIS  : Low Instrument Saturation
+    #     HRS  : High Representation Saturation
+    #     HIS  : High Insturment Saturation
+    SPECIAL_VALUES = {
+        "NULL": np.fromstring(b'\xFF\x7F\xFF\xFB', dtype='>f4')[0],
+        "LRS": np.fromstring(b'\xFF\x7F\xFF\xFC', dtype='>f4')[0],
+        "LIS": np.fromstring(b'\xFF\x7F\xFF\xFD', dtype='>f4')[0],
+        "HRS": np.fromstring(b'\xFF\x7F\xFF\xFE', dtype='>f4')[0],
+        "HIS": np.fromstring(b'\xFF\x7F\xFF\xFF', dtype='>f4')[0]
+    }
+
+    def __init__(self, path, terrain_resolution=1.0):
+        self.path = path
+        self.terrain_resolution = terrain_resolution
+        self.label = self._read_label()
+        self.data = self._read_data()
+
+    def _read_label(self):
+        """Returns a dict-like representation of a PVL label"""
+        return pvl.load(self.path)
+
+    def _read_data(self):
+        """
+        Reads elevation data from a PDS .IMG file.
+
+        Notes
+        -----
+        * Uses nearest-neighbor to downsample data.
+
+        Todo
+        ----
+        * Add other downsampling algorithms.
+
+        """
+        h, w = self.image_resolution
+        max_samples = int(w - w % self.bin_size)
+
+        data = np.zeros(self.shape)
+        with open(self.path, 'rb') as f:
+            # Seek to the first byte of data
+            start_byte = self._get_data_start()
+            f.seek(start_byte)
+            # Iterate over each row of the data
+            for r in range(data.shape[0]):
+                # Each iteration, seek to the right location before
+                # reading a row. We determine this location as the
+                # first byte of data PLUS a offset which we calculate as the
+                # product of:
+                #
+                #     4, the number of bytes in a single record
+                #     r, the current row index
+                #     w, the number of records in a row of the DTM
+                #     bin_size, the number of records in a bin
+                #
+                # This is where we account for skipping over rows.
+                offset = int(4 * r * w * self.bin_size)
+                f.seek(start_byte + offset)
+                # Read a row
+                row = np.fromfile(f, dtype=np.float32, count=max_samples)
+                # This is where we account for skipping over columns.
+                data[r] = row[::self.bin_size]
+
+        data = self._process_invalid_data(data)
+        return data
+
+    def _get_data_start(self):
+        """Gets the start position of the DTM data block"""
+        label_length = self.label['RECORD_BYTES']
+        num_labels = self.label.get('LABEL_RECORDS', 1)
+        return int(label_length * num_labels)
+
+    def _process_invalid_data(self, data):
+        """Sets any 'NULL' elevation values to np.NaN"""
+        invalid_data_mask = (data <= self.SPECIAL_VALUES['NULL'])
+        data[invalid_data_mask] = np.NaN
+        return data
+
+    @property
+    def map_size(self):
+        """Geographic size of the bounding box around the DTM"""
+        scale = self.map_scale * self.unit_scale
+        w = self.image_resolution[0] * scale
+        h = self.image_resolution[1] * scale
+        return (w, h)
+
+    @property
+    def mesh_scale(self):
+        """Geographic spacing between mesh vertices"""
+        return self.bin_size * self.map_scale * self.unit_scale
+
+    @property
+    def map_info(self):
+        """Map Projection metadata"""
+        return self.label['IMAGE_MAP_PROJECTION']
+
+    @property
+    def map_scale(self):
+        """Geographic spacing between DTM posts"""
+        map_scale = self.map_info.get('MAP_SCALE', None)
+        return getattr(map_scale, 'value', 1.0)
+
+    @property
+    def map_units(self):
+        """Geographic unit for spacing between DTM posts"""
+        map_scale = self.map_info.get('MAP_SCALE', None)
+        return getattr(map_scale, 'units', None)
+
+    @property
+    def unit_scale(self):
+        """
+        The function that creates a Blender mesh 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list