# coding=utf-8
"""Utility functions for performing plane projections in 3D space.
This module can be used to create axonometric views of geometry among other
purposes.
"""
from __future__ import division
from .geometry2d import Vector2D, Point2D, Ray2D, LineSegment2D, \
Polyline2D, Arc2D, Polygon2D, Mesh2D
from .geometry3d import Vector3D, Point3D, Ray3D, Plane, LineSegment3D, \
Polyline3D, Arc3D, Face3D, Mesh3D, Polyface3D, Sphere, Cone, Cylinder
[docs]
def project_geometry(plane, geometries):
""""Project multiple geometries into a plane to get them in the world 3D system.
Args:
plane: The Plane into which the geometries will be projected.
geometries: An array of any ladybug_geometry objects which will be projected
into the plane. Note that 2D geometry objects will be converted into
3D (and are assumed to be in the World XY plane) in order to be
projected into the Plane. Also, Arcs will be converted to Polylines
in order to be represented correctly in the plane.
Returns:
The input geometries projected into the Plane. All coordinate values will
be in the World 3D system.
"""
projected_geos = []
for geo in geometries:
if isinstance(geo, (Point3D, Point2D)):
geo = Point3D.from_point2d(geo) if isinstance(geo, Point2D) else geo
projected_geos.append(plane.project_point(geo))
elif isinstance(geo, (LineSegment3D, LineSegment2D)):
geo = LineSegment3D.from_line_segment2d(geo) \
if isinstance(geo, LineSegment2D) else geo
st, end = plane.project_points(geo.endpoints)
projected_geos.append(LineSegment3D.from_end_points(st, end))
elif isinstance(geo, (Polyline3D, Polyline2D)):
geo = Polyline3D.from_polyline2d(geo) if isinstance(geo, Polyline2D) else geo
vertices = plane.project_points(geo.vertices)
projected_geos.append(Polyline3D(vertices, interpolated=geo.interpolated))
elif isinstance(geo, (Arc3D, Arc2D)):
geo = Arc3D.from_arc2d(geo) if isinstance(geo, Arc2D) else geo
p_line = geo.to_polyline(30, interpolated=True)
vertices = plane.project_points(p_line.vertices)
projected_geos.append(Polyline3D(vertices, interpolated=True))
elif isinstance(geo, Polygon2D):
vertices = plane.project_points(geo.vertices)
projected_geos.append(Face3D(vertices))
elif isinstance(geo, Face3D):
boundary = plane.project_points(geo.boundary)
holes = None
if geo.has_holes:
holes = [plane.project_points(h) for h in geo.holes]
projected_geos.append(Face3D(boundary, geo.plane, holes))
elif isinstance(geo, (Mesh3D, Mesh2D)):
geo = Mesh3D.from_mesh2d(geo) if isinstance(geo, Mesh2D) else geo
vertices = plane.project_points(geo.vertices)
projected_geos.append(Mesh3D(vertices, geo.faces, geo.colors))
elif isinstance(geo, Polyface3D):
vertices = plane.project_points(geo.vertices)
proj_p_face = Polyface3D(vertices, geo.face_indices, geo.edge_information)
projected_geos.append(proj_p_face)
elif isinstance(geo, (Ray3D, Ray2D)):
geo = Ray3D.from_ray2d(geo) if isinstance(geo, Ray2D) else geo
pt = plane.project_point(geo.p)
vec = plane.project_point(Point3D(geo.v.x, geo.v.y, geo.v.z))
projected_geos.append(Ray3D(pt, Vector3D(vec.x, vec.y, vec.z)))
elif isinstance(geo, (Vector3D, Vector2D)):
geo = Vector3D.from_vector2d(geo) if isinstance(geo, Vector2D) else geo
vec = plane.project_point(Point3D(geo.x, geo.y, geo.z))
projected_geos.append(Vector3D(vec.x, vec.y, vec.z))
elif isinstance(geo, Plane):
origin = plane.project_point(geo.o)
normal = plane.project_point(Point3D(geo.n.x, geo.n.y, geo.n.z))
normal = Vector3D(normal.x, normal.y, normal.z)
projected_geos.append(Plane(normal, origin))
elif isinstance(geo, Sphere):
center = plane.project_point(geo.center)
projected_geos.append(Sphere(center, geo.radius))
elif isinstance(geo, Cone):
pt = plane.project_point(geo.vertex)
vec = plane.project_point(Point3D(geo.axis.x, geo.axis.y, geo.axis.z))
projected_geos.append(Cone(pt, Vector3D(vec.x, vec.y, vec.z), geo.angle))
elif isinstance(geo, Cylinder):
pt = plane.project_point(geo.center)
vec = plane.project_point(Point3D(geo.axis.x, geo.axis.y, geo.axis.z))
projected_geos.append(Cone(pt, Vector3D(vec.x, vec.y, vec.z), geo.radius))
else:
raise ValueError('Unrecognized geometry type {}: {}'.format(type(geo), geo))
return projected_geos
[docs]
def project_geometry_2d(plane, geometries):
""""Project multiple geometries into a plane to get them in the plane's 2D system.
Args:
plane: The Plane into which the geometries will be projected.
geometries: An array of any ladybug_geometry objects which will be projected
into the plane. 2D geometry objects will retain their 2D classes as
they are projected into the new system.
Returns:
The input geometries projected into the Plane. All coordinate values will
be in the 2D system of the input plane.
"""
projected_geos = []
for geo in geometries:
if isinstance(geo, (Point3D, Point2D)):
geo = Point3D.from_point2d(geo) if isinstance(geo, Point2D) else geo
projected_geos.append(plane.xyz_to_xy(plane.project_point(geo)))
elif isinstance(geo, (LineSegment3D, LineSegment2D)):
geo = LineSegment3D.from_line_segment2d(geo) \
if isinstance(geo, LineSegment2D) else geo
st, end = plane.project_points(geo.endpoints)
st, end = plane.xyz_to_xy(st), plane.xyz_to_xy(end)
projected_geos.append(LineSegment2D.from_end_points(st, end))
elif isinstance(geo, (Polyline3D, Polyline2D)):
geo = Polyline3D.from_polyline2d(geo) if isinstance(geo, Polyline2D) else geo
vertices = plane.project_points(geo.vertices)
vertices = [plane.xyz_to_xy(pt) for pt in vertices]
projected_geos.append(Polyline2D(vertices, interpolated=geo.interpolated))
elif isinstance(geo, (Arc3D, Arc2D)):
geo = Arc3D.from_arc2d(geo) if isinstance(geo, Arc2D) else geo
p_line = geo.to_polyline(30, interpolated=True)
vertices = plane.project_points(p_line.vertices)
vertices = [plane.xyz_to_xy(pt) for pt in vertices]
projected_geos.append(Polyline2D(vertices, interpolated=True))
elif isinstance(geo, Polygon2D):
vertices = plane.project_points(geo.vertices)
vertices = [plane.xyz_to_xy(pt) for pt in vertices]
projected_geos.append(Polygon2D(vertices))
elif isinstance(geo, Face3D):
boundary = plane.project_points(geo.boundary)
boundary = [Point3D.from_point2d(plane.xyz_to_xy(pt)) for pt in boundary]
holes = None
if geo.has_holes:
holes = []
for h in geo.holes:
h = plane.project_points(h)
h = [Point3D.from_point2d(plane.xyz_to_xy(pt)) for pt in h]
holes.append(h)
projected_geos.append(Face3D(boundary, geo.plane, holes))
elif isinstance(geo, (Mesh3D, Mesh2D)):
geo = Mesh3D.from_mesh2d(geo) if isinstance(geo, Mesh2D) else geo
vertices = plane.project_points(geo.vertices)
vertices = [plane.xyz_to_xy(pt) for pt in vertices]
projected_geos.append(Mesh2D(vertices, geo.faces, geo.colors))
elif isinstance(geo, Polyface3D):
vertices = plane.project_points(geo.vertices)
vertices = [Point3D.from_point2d(plane.xyz_to_xy(pt)) for pt in vertices]
proj_p_face = Polyface3D(vertices, geo.face_indices, geo.edge_information)
projected_geos.append(proj_p_face)
elif isinstance(geo, (Ray3D, Ray2D)):
geo = Ray3D.from_ray2d(geo) if isinstance(geo, Ray2D) else geo
pt = plane.xyz_to_xy(plane.project_point(geo.p))
vec = plane.project_point(Point3D(geo.v.x, geo.v.y, geo.v.z))
vec = plane.xyz_to_xy(vec)
projected_geos.append(Ray2D(pt, Vector2D(vec.x, vec.y)))
elif isinstance(geo, (Vector3D, Vector2D)):
geo = Vector3D.from_vector2d(geo) if isinstance(geo, Vector2D) else geo
vec = plane.project_point(Point3D(geo.x, geo.y, geo.z))
vec = plane.xyz_to_xy(vec)
projected_geos.append(Vector2D(vec.x, vec.y))
elif isinstance(geo, Plane):
origin = plane.xyz_to_xy(plane.project_point(geo.o))
normal = plane.project_point(Point3D(geo.n.x, geo.n.y, geo.n.z))
normal = plane.xyz_to_xy(normal)
normal = Vector3D(normal.x, normal.y)
projected_geos.append(Plane(normal, Point3D(origin.x, origin.y)))
elif isinstance(geo, Sphere):
center = plane.xyz_to_xy(plane.project_point(geo.center))
center = Point3D.from_point2d(center)
projected_geos.append(Sphere(center, geo.radius))
elif isinstance(geo, Cone):
pt = Point3D.from_point2d(plane.xyz_to_xy(plane.project_point(geo.vertex)))
vec = plane.project_point(Point3D(geo.axis.x, geo.axis.y, geo.axis.z))
vec = Point3D.from_point2d(plane.xyz_to_xy(vec))
projected_geos.append(Cone(pt, Vector3D(vec.x, vec.y, vec.z), geo.angle))
elif isinstance(geo, Cylinder):
pt = Point3D.from_point2d(plane.xyz_to_xy(plane.project_point(geo.center)))
vec = plane.project_point(Point3D(geo.axis.x, geo.axis.y, geo.axis.z))
vec = Point3D.from_point2d(plane.xyz_to_xy(vec))
projected_geos.append(Cone(pt, Vector3D(vec.x, vec.y, vec.z), geo.radius))
else:
raise ValueError('Unrecognized geometry type {}: {}'.format(type(geo), geo))
return projected_geos