"""Extrudes closed planar outlines to height of a point - if point, viewed from
World Top viewis is contained inside outline  Script by MItch Heynick 06.05.19"""

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

#planar closed curves
def cp_crv_filt(rhino_object, geometry, component_index):
    return rs.IsCurvePlanar(geometry) and rs.IsCurveClosed(geometry)

def ExtrudeBldgsToPtHt():
    
    msg="Select closed planar building outlines"
    baseIDs=rs.GetObjects(msg,4,preselect=True,custom_filter=cp_crv_filt)
    if not baseIDs: return
    
    ptIDs=rs.GetObjects("Select points",1)
    if not ptIDs: return
    
    xform=Rhino.Geometry.Transform.PlanarProjection(Rhino.Geometry.Plane.WorldXY)
    bases_geo=[rs.coercecurve(baseID) for baseID in baseIDs]
    bases_z=[crv.PointAtStart.Z for crv in bases_geo]
    #make a copy of bases, then project to world XY for containment check
    bases_proj=[crv.Duplicate() for crv in bases_geo]
    for crv in bases_proj: crv.Transform(xform)
    
    pts=[rs.coerce3dpoint(ptID) for ptID in ptIDs]
    #get point Z heights
    pts_z=[pt.Z for pt in pts]
    #project pts to 0 plane for containment check
    for pt in pts: pt.Transform(xform)
    
    vols=[]
    pt_in=Rhino.Geometry.PointContainment.Inside
    for i, base in enumerate(bases_proj):
        for j, pt in enumerate(pts):
            if base.Contains(pt)==pt_in:
                ht=pts_z[j]-bases_z[i]
                vol=Rhino.Geometry.Extrusion.Create(bases_geo[i],ht,True)
                if vol: vols.append(vol)
                #remove pt that was used from lists to go faster
                pts.pop(j) ; pts_z.pop(j)
                #break out of loop
                break
    if vols:
        exIDs=[sc.doc.Objects.AddExtrusion(vol) for vol in vols]
        sc.doc.Views.Redraw()

ExtrudeBldgsToPtHt()