Skip to content

Commit

Permalink
fix(dictutil): Add a dictutil module to assist with serialization
Browse files Browse the repository at this point in the history
* Add files via upload

New "dictutil" for Ladybug Geometry, similar to the existing Honeybee "dictutil". Converts any input dict into a new Ladybug Object.

* Add files via upload

Tests for new Ladybug Geometry dictutil converter function

* Updated dicutil tests, import

Update to PR #311 - revised "test/dictutil_test.py" import statements, updated names (files, function) as per comments. Added new tests for completeness. Verified that all tests pass.

* Updated styling/syntax as per @chriswmackey comments

Co-authored-by: EM <Ed@bldgtyp.com>
  • Loading branch information
ed-p-may and edpmay committed Aug 6, 2021
1 parent 469b274 commit 9f8d411
Show file tree
Hide file tree
Showing 3 changed files with 278 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
*.pyc
.venv/
test.py
.pytest_cache
*__pycache__
Expand Down
65 changes: 65 additions & 0 deletions ladybug_geometry/dictutil.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# coding=utf-8
"""Utilities to convert any Ladybug Geometry dictionary to Python objects.
Note that importing this module will import almost all modules within the
Ladybug_geometry library in order to be able to re-serialize almost any
dictionary produced from the library.
"""

from ladybug_geometry.geometry2d import Vector2D, Point2D, Ray2D, \
LineSegment2D, Arc2D, Polyline2D, Polygon2D, Mesh2D
from ladybug_geometry.geometry3d import Vector3D, Point3D, Ray3D, \
LineSegment3D, Arc3D, Polyline3D, Polyface3D, Mesh3D,\
Plane, Face3D, Sphere, Cone, Cylinder

def geometry_dict_to_object(ladybug_geom_dict, raise_exception=True):
"""
Args:
ladybug_geom_dict (dict): A dictionary of any Ladybug Geometry object.
raise_exception (bool): Boolean to note whether an exception should be raised
if the object is not identified as a part of ladybug_geometry.
Default: True.
Returns:
A Python object derived from the input ladybug_geom_dict.
"""

lbt_types = {
'Vector2D': Vector2D,
'Point2D': Point2D,
'Ray2D': Ray2D,
'LineSegment2D': LineSegment2D,
'Arc2D': Arc2D,
'Polyline2D': Polyline2D,
'Polygon2D': Polygon2D,
'Mesh2D': Mesh2D,
'Vector3D': Vector3D,
'Point3D': Point3D,
'Ray3D': Ray3D,
'LineSegment3D': LineSegment3D,
'Arc3D': Arc3D,
'Polyline3D': Polyline3D,
'Mesh3D': Mesh3D,
'Plane': Plane,
'Polyface3D': Polyface3D,
'Face3D':Face3D,
'Sphere':Sphere,
'Cone':Cone,
'Cylinder':Cylinder,
}

# Get the ladybug_geometry object 'Type'
try:
obj_type = ladybug_geom_dict['type']
except KeyError:
raise ValueError('Ladybug dictionary lacks required "type" key.')

# Build a new Ladybug Python Object based on the "Type"
try:
lbt_class = lbt_types[obj_type]
return lbt_class.from_dict( ladybug_geom_dict )
except KeyError:
if raise_exception:
raise ValueError('{} is not a recognized ladybug geometry type'.format(obj_type))
else:
return None
212 changes: 212 additions & 0 deletions tests/dictutil_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
"""Tests for Ladybug Geometry dict->Object converter.
Note: Written in PyTest format.
"""
import pytest
from ladybug_geometry.geometry2d import (Vector2D, Point2D, Ray2D,
LineSegment2D, Arc2D, Polyline2D, Polygon2D, Mesh2D)
from ladybug_geometry.geometry3d import (Vector3D, Point3D, Ray3D,
LineSegment3D, Arc3D, Polyline3D, Polyface3D, Mesh3D,
Plane, Face3D, Sphere, Cone, Cylinder)
from ladybug_geometry.dictutil import geometry_dict_to_object

#--- Test not Ladubug Geometry dict
def test_not_valid_dict():
d = { 'key_1':'val_1' } # dict Does NOT inlcude 'type' key
with pytest.raises(ValueError):
obj = geometry_dict_to_object( d )

def test_not_valid_dict():
d = { 'type':'not_a_valid_type' } # Includes 'type', but is not a valid Ladybug Type
with pytest.raises(ValueError):
obj = geometry_dict_to_object( d )

#--- Test 2D Geometry
def test_Point2D():
obj1 = Point2D()
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

def test_Arc2D():
pt1 = Point2D()
obj1 = Arc2D(pt1, 2)
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

def test_Vector2D():
obj1 = Vector2D(0,1)
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

def test_Ray2D():
pt1 = Point2D()
v1 = Vector2D(0,1)
obj1 = Ray2D(pt1,v1)
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

def test_LineSegment2D():
pt1 = Point2D()
v1 = Vector2D(0,1)
obj1 = LineSegment2D(pt1,v1)
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

def test_Polyline2D():
pt1 = Point2D(0,1)
pt2 = Point2D(1,2)
pt3 = Point2D(2,3)
obj1 = Polyline2D([pt1, pt2, pt3], False)
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

def test_Polygon2D():
pt1 = Point2D(0,1)
pt2 = Point2D(1,1)
pt3 = Point2D(1,0)
pt4 = Point2D(0,1)
obj1 = Polygon2D([pt1, pt2, pt3, pt4])
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

def test_Mesh2D():
pt1 = Point2D(0,1)
pt2 = Point2D(1,1)
pt3 = Point2D(1,0)
pt4 = Point2D(0,1)
obj1 = Mesh2D(vertices=(pt1, pt2, pt3, pt4), faces=[(0,1,2)] )
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

#--- Test 3D Geometry
def test_Point3D():
obj1 = Point3D()
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

def test_Arc3D():
pl = Plane()
obj1 = Arc3D(pl, 2)
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

def test_Vector3D():
obj1 = Vector3D(0,1)
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

def test_Ray3D():
pt1 = Point3D()
v1 = Vector3D(0,1)
obj1 = Ray3D(pt1,v1)
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

def test_LineSegment3D():
pt1 = Point3D()
v1 = Vector3D(0,1)
obj1 = LineSegment3D(pt1,v1)
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

def test_Polyline3D():
pt1 = Point3D(0,1)
pt2 = Point3D(1,2)
pt3 = Point3D(2,3)
obj1 = Polyline3D([pt1, pt2, pt3], False)
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

def test_Polyface3D():
pt1 = Point3D(0,1)
pt2 = Point3D(1,1)
pt3 = Point3D(1,0)
pt4 = Point3D(0,1)
obj1 = Polyface3D(vertices=[pt1, pt2, pt3, pt4], face_indices=[ [[1]] ] )
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

def test_Mesh3D():
pt1 = Point3D(0,1)
pt2 = Point3D(1,1)
pt3 = Point3D(1,0)
pt4 = Point3D(0,1)
obj1 = Mesh3D(vertices=(pt1, pt2, pt3, pt4), faces=[(0,1,2)] )

d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

def test_Plane():
obj1 = Plane()
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

def test_Face3D():
pt1 = Point3D(0,1)
pt2 = Point3D(1,2)
pt3 = Point3D(2,3)
obj1 = Face3D([pt1, pt2, pt3])
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

def test_Sphere():
pt1 = Point3D()
obj1 = Sphere(pt1, 1)
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

def test_Cone():
v1 = Point3D()
axis = Vector3D(0,0,1)
obj1 = Cone(v1, axis, 45)
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

def test_Cylinder():
v1 = Point3D()
axis = Vector3D(0,0,1)
obj1 = Cylinder(v1, axis, 10)
d = obj1.to_dict()
obj2 = geometry_dict_to_object(d)

assert obj2 == obj1

0 comments on commit 9f8d411

Please sign in to comment.