External surfaces of windows

Hello guys , I’m trying to extract window external surfaces , i have tried with the logic of extracting the window faces , calculating their normals , comparing their normals with wall orientation .
I thought this will keep only the external window surfaces but has extracted internal and external ones .
So I want to verify the intersection of wall external surfaces with the remaining window faces , so that to keep only external ones … but Im finding errors .
here is the python code im using to extract

import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)

# Input: lists of wall surfaces and window surfaces
wall_surfaces_list = IN[0]  # List of lists of wall surfaces
window_faces_list = IN[1]  # List of list of lists of window faces

# Function to get normal vector of a surface
def get_normal_vector(surface):
    return surface.NormalAtParameter(0.5, 0.5)

# Function to check if the window surface's bounding box is contained within the wall surface's bounding box
def check_bounding_box_containment(wall_surface, window_surface):
    wall_bbox = wall_surface.GetBoundingBox()
    window_bbox = window_surface.GetBoundingBox()
    
    return (wall_bbox.Min.X <= window_bbox.Min.X and
            wall_bbox.Max.X >= window_bbox.Max.X and
            wall_bbox.Min.Y <= window_bbox.Min.Y and
            wall_bbox.Max.Y >= window_bbox.Max.Y and
            wall_bbox.Min.Z <= window_bbox.Min.Z and
            wall_bbox.Max.Z >= window_bbox.Max.Z)

# Check if window face has the same normal vector as a wall surface and is contained within the wall surface
matching_window_surfaces = []

print("Number of Wall Surfaces:", len(wall_surfaces_list))
print("Number of Window Faces:", len(window_faces_list))

for window_faces_group in window_faces_list:
    for window_faces in window_faces_group:
        for window_face in window_faces:
            if isinstance(window_face, list):
                continue
            
            window_surface = window_face.SurfaceGeometry
            if not isinstance(window_surface, Surface):
                continue

            window_normal = get_normal_vector(window_surface)
            print("Window Normal:", window_normal)

            for wall_surfaces in wall_surfaces_list:
                for wall_surface in wall_surfaces:
                    if isinstance(wall_surface, list):
                        continue
                    
                    wall_normal = get_normal_vector(wall_surface)
                    print("Wall Normal:", wall_normal)

                    if window_normal.IsAlmostEqualTo(wall_normal):
                        if check_bounding_box_containment(wall_surface, window_surface):
                            matching_window_surfaces.append(window_surface)
                            print("Matching Window Surface Found")
                            break  # Stop checking further wall surfaces for this window face
                else:
                    continue
                break

# Output the list of matching window surfaces
OUT = matching_window_surfaces

can someone help please !

Try to set and converse a relationship between walls and windows before working with geometries.

here’s an example using GetMaterialIds() and GetMaterialArea() to retain only the surface of transparent materials

import clr
import sys
import System
#
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS

#import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB

#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument

def has_TransparencyMaterial(elem):
    #
    has_TransparencyMaterial.Area = 0
    lstMatGlassId = [xId for xId in elem.GetMaterialIds(False) if doc.GetElement(xId).Transparency > 85 ]
    lstArea = [elem.GetMaterialArea(xId, False) * 0.092903 for xId in lstMatGlassId] # squre feet to square meter
    if len(lstArea) > 0:
        sumArea = sum(lstArea) / 2.0 # divide per 2 because it's a solid area by default not a face
        has_TransparencyMaterial.Area = sumArea
        return True
            
    return False

def toList(x):
    if isinstance(x, (list, dict)) or \
            (hasattr(x, "GetType") and x.GetType().GetInterface("ICollection") is not None):
        return x
    else : return [x]

out = []
#Preparing input from dynamo to revit
lstWalls = toList(UnwrapElement(IN[0]))
for wall in lstWalls:
    # get all windows Dependent
    lst_windows_Ids = wall.GetDependentElements(ElementCategoryFilter(BuiltInCategory.OST_Windows))
    lst_windows = [doc.GetElement(xId) for xId in lst_windows_Ids]
    # remove false
    lst_windows = [wind for wind in lst_windows if wind.Host.Id == wall.Id]
    sum_area_glass = 0
    for wind in lst_windows :
        if has_TransparencyMaterial(wind):
            sum_area_glass += has_TransparencyMaterial.Area 
    out.append([wall, lst_windows, f"Sum of glass surfaces for this wall : {sum_area_glass:.2f} m²"])

OUT = out