コード例 #1
0
def intersect_shape_by_line(topods_shape,
                            line,
                            low_parameter=0.0,
                            hi_parameter=float("+inf")):
    """
    finds the intersection of a shape and a line

    :param shape: any TopoDS_*
    :param line: gp_Lin
    :param low_parameter:
    :param hi_parameter:

    :return: a list with a number of tuples that corresponds to the number
    of intersections found
    the tuple contains ( gp_Pnt, TopoDS_Face, u,v,w ), respectively the
    intersection point, the intersecting face
    and the u,v,w parameters of the intersection point
    :raise:
    """
    from OCC.IntCurvesFace import IntCurvesFace_ShapeIntersector
    shape_inter = IntCurvesFace_ShapeIntersector()
    shape_inter.Load(topods_shape, TOLERANCE)
    shape_inter.PerformNearest(line, low_parameter, hi_parameter)

    with assert_isdone(shape_inter,
                       "failed to computer shape / line intersection"):
        return (shape_inter.Pnt(1), shape_inter.Face(1),
                shape_inter.UParameter(1), shape_inter.VParameter(1),
                shape_inter.WParameter(1))
コード例 #2
0
ファイル: intersect.py プロジェクト: buguen/aoc-utils
def shape_by_line(topods_shape,
                  line,
                  low_parameter=0.0,
                  hi_parameter=float("+inf")):
    r"""Finds the intersection of a shape and a line

    Parameters
    ----------
    topods_shape : any TopoDS_*
    line : gp_Lin
    low_parameter : float, optional
        (the default value is 0.0)
    hi_parameter : float, optional
        (the default value is infinity)

    Returns
    -------
    a list with a number of tuples that corresponds to the
    number of intersections found.
    the tuple contains ( OCC.gp.gp_Pnt, TopoDS_Face, u,v,w ),
    respectively the intersection point, the intersecting face
    and the u,v,w parameters of the intersection point

    """
    shape_inter = IntCurvesFace_ShapeIntersector()
    shape_inter.Load(topods_shape, OCCUTILS_DEFAULT_TOLERANCE)
    shape_inter.PerformNearest(line, low_parameter, hi_parameter)

    with AssertIsDone(shape_inter,
                      "failed to computer shape / line intersection"):
        return (shape_inter.Pnt(1),
                shape_inter.Face(1),
                shape_inter.UParameter(1),
                shape_inter.VParameter(1),
                shape_inter.WParameter(1))
コード例 #3
0
ファイル: intersect.py プロジェクト: buguen/aoc-utils
def _intersect_shape_by_line(topods_shape,
                             line,
                             low_parameter=0.0,
                             hi_parameter=float("+inf")):
    r"""Finds the intersection of a shape and a line

    Parameters
    ----------
    topods_shape : any TopoDS_*
    line : gp_Lin
    low_parameter : float, optional
        (the default value is 0.0)
    hi_parameter : float, optional
        (the default value is infinity)

    Returns
    -------
    a list of gp_Pnt

    """
    shape_inter = IntCurvesFace_ShapeIntersector()
    shape_inter.Load(topods_shape, OCCUTILS_DEFAULT_TOLERANCE)
    # shape_inter.PerformNearest(line, low_parameter, hi_parameter)
    shape_inter.Perform(line, low_parameter, hi_parameter)

    with AssertIsDone(shape_inter, "failed to computer shape / line "
                                   "intersection"):
        points = list()

        # Bug correction (some intersection points were missed)
        # for i in range(1, shape_inter.NbPnt()):
        for i in range(1, shape_inter.NbPnt() + 1):
            points.append(shape_inter.Pnt(i))

    return points
コード例 #4
0
ファイル: calculate.py プロジェクト: Linwal/pyliburo
def intersect_shape_with_ptdir(occ_shape, pypt, pydir):
    occ_line = gp_Lin(
        gp_Ax1(gp_Pnt(pypt[0], pypt[1], pypt[2]),
               gp_Dir(pydir[0], pydir[1], pydir[2])))
    shape_inter = IntCurvesFace_ShapeIntersector()
    shape_inter.Load(occ_shape, 1e-6)
    shape_inter.PerformNearest(occ_line, 0.0, float("+inf"))
    if shape_inter.IsDone():
        npts = shape_inter.NbPnt()
        if npts != 0:
            return shape_inter.Pnt(1), shape_inter.Face(1)
        else:
            return None, None
    else:
        return None, None
コード例 #5
0
def intersect_shape_by_line(
        shape: TopoDS_Shape,
        line: gp.gp_Lin,
        low_parameter: Optional[float]=0.0,
        hi_parameter: Optional[float]=float("+inf"),
        tol:Optional[float]=0.001
        ):
    """
    finds the intersection of a shape and a line

    :param shape: any TopoDS_*
    :param line: gp_Lin
    :param low_parameter:
    :param hi_parameter:

    IntCurvesFace_ShapeIntersector

    :return: a list with a number of tuples that corresponds to the number
    of intersections found
    the tuple contains ( gp_Pnt, TopoDS_Face, u,v,w ), respectively the
    intersection point, the intersecting face
    and the u,v,w parameters of the intersection point
    :raise:
    """
    shape_inter = IntCurvesFace_ShapeIntersector()
    shape_inter.Load(shape, tol)
    shape_inter.PerformNearest(line, low_parameter, hi_parameter)

    with assert_isdone(shape_inter, "failed to computer shape / line intersection"):
        try:
            return (shape_inter.Pnt(1),
                    shape_inter.Face(1),
                    shape_inter.UParameter(1),
                    shape_inter.VParameter(1),
                    shape_inter.WParameter(1))
        except:
            return None, None, None, None, None
コード例 #6
0
ファイル: calculate.py プロジェクト: CES-MDE/py4design
def intersect_shape_with_ptdir(occtopology, pypt, pydir):
    """
    This function projects a point in a direction and calculates the at which point does the point intersects the OCCtopology.
 
    Parameters
    ----------
    occtopology : OCCtopology
        The OCCtopology to be projected on.
        OCCtopology includes: OCCshape, OCCcompound, OCCcompsolid, OCCsolid, OCCshell, OCCface, OCCwire, OCCedge, OCCvertex 
        
    pypt : tuple of floats
        The point to be projected. A pypt is a tuple that documents the xyz coordinates of a pt e.g. (x,y,z)
        
    pydir : tuple of floats
        The direction of the point to be projected. A pydir is a tuple that documents the xyz vector of a dir e.g. (x,y,z)
        
    Returns
    -------
    intersection point : pypt
        The point in which the projected point intersect the OCCtopology. If None means there is no intersection.
    
    intersection face : OCCface
        The OCCface in which the projected point hits. If None means there is no intersection.
    """
    occ_line = gp_Lin(
        gp_Ax1(gp_Pnt(pypt[0], pypt[1], pypt[2]),
               gp_Dir(pydir[0], pydir[1], pydir[2])))
    shape_inter = IntCurvesFace_ShapeIntersector()
    shape_inter.Load(occtopology, 1e-6)
    shape_inter.PerformNearest(occ_line, 0.0, float("+inf"))
    if shape_inter.IsDone():
        npts = shape_inter.NbPnt()
        if npts != 0:
            return modify.occpt_2_pypt(shape_inter.Pnt(1)), shape_inter.Face(1)
        else:
            return None, None
    else:
        return None, None
コード例 #7
0
 def terrain_intersection_curves(self, geometry_terrain):
     # make shell out of tin_occface_list and create OCC object
     terrain_shell = construct.make_shell(geometry_terrain)
     terrain_intersection_curves = IntCurvesFace_ShapeIntersector()
     terrain_intersection_curves.Load(terrain_shell, 1e-6)
     return terrain_intersection_curves
コード例 #8
0
def building_2d_to_3d(citygml_writer, zone_shp_path, district_shp_path,
                      tin_occface_list, height_col, nfloor_col):
    """
    This script extrudes buildings from the shapefile and creates intermediate floors.

    :param citygml_writer: the cityGML object to which the buildings are gonna be created.
    :param district_shp_path: path to the shapefile to be extruded of the district
    :param tin_occface_list: the faces of the terrain, to be used to put the buildings on top.
    :param height_col:
    :param nfloor_col:
    :return:
    """
    # read district shapefile and names of buildings of the zone of analysis
    district_building_records = gdf.from_file(district_shp_path).set_index(
        'Name')
    district_building_names = district_building_records.index.values
    zone_building_names = gdf.from_file(zone_shp_path)['Name'].values

    #make shell out of tin_occface_list and create OCC object
    terrain_shell = construct.sew_faces(tin_occface_list)[0]
    terrain_intersection_curves = IntCurvesFace_ShapeIntersector()
    terrain_intersection_curves.Load(terrain_shell, 1e-6)
    bsolid_list = []

    #create the buildings in 3D
    for name in district_building_names:
        height = float(district_building_records.loc[name, height_col])
        nfloors = int(district_building_records.loc[name, nfloor_col])

        # Make floors only for the buildings of the zone of interest
        # for the rest just consider one high floor.
        # simplify geometry tol =1 for buildings of interest, tol = 5 for surroundings
        if name in zone_building_names:
            range_floors = range(nfloors + 1)
            floor_to_floor_height = height / nfloors
            geometry = district_building_records.ix[name].geometry.simplify(
                1, preserve_topology=True)
        else:
            range_floors = [0, 1]
            floor_to_floor_height = height
            geometry = district_building_records.ix[name].geometry.simplify(
                5, preserve_topology=True)

        point_list_2D = list(geometry.exterior.coords)
        point_list_3D = [(a, b, 0)
                         for (a, b) in point_list_2D]  # add 0 elevation

        #creating floor surface in pythonocc
        face = construct.make_polygon(point_list_3D)
        #get the midpt of the face
        face_midpt = calculate.face_midpt(face)

        #project the face_midpt to the terrain and get the elevation
        inter_pt, inter_face = calc_intersection(terrain_intersection_curves,
                                                 face_midpt, (0, 0, 1))

        loc_pt = (inter_pt.X(), inter_pt.Y(), inter_pt.Z())
        #reconstruct the footprint with the elevation
        face = fetch.topo2topotype(modify.move(face_midpt, loc_pt, face))

        moved_face_list = []
        for floor_counter in range_floors:
            dist2mve = floor_counter * floor_to_floor_height
            #get midpt of face
            orig_pt = calculate.face_midpt(face)
            #move the pt 1 level up
            dest_pt = modify.move_pt(orig_pt, (0, 0, 1), dist2mve)
            moved_face = modify.move(orig_pt, dest_pt, face)
            moved_face_list.append(moved_face)

        #loft all the faces and form a solid
        vertical_shell = construct.make_loft(moved_face_list)
        vertical_face_list = fetch.topo_explorer(vertical_shell, "face")
        roof = moved_face_list[-1]
        footprint = moved_face_list[0]
        all_faces = []
        all_faces.append(footprint)
        all_faces.extend(vertical_face_list)
        all_faces.append(roof)
        bldg_shell_list = construct.sew_faces(all_faces)

        # make sure all the normals are correct (they are pointing out)
        if bldg_shell_list:
            bldg_solid = construct.make_solid(bldg_shell_list[0])
            bldg_solid = modify.fix_close_solid(bldg_solid)
            bsolid_list.append(bldg_solid)
            occface_list = fetch.topo_explorer(bldg_solid, "face")
            geometry_list = gml3dmodel.write_gml_srf_member(occface_list)
            citygml_writer.add_building("lod1", name, geometry_list)

    return bsolid_list
コード例 #9
0
def building2d23d(zone_shp_path, district_shp_path, tin_occface_list,
                  architecture_path, simplification_params, height_col,
                  nfloor_col):
    """

    :param zone_shp_path: path to zone geometrydatabase
    :param district_shp_path: path to district geometry database
    :param tin_occface_list: list of faces of terrain
    :param architecture_path: path to database of architecture properties
    :param simplification_params: parameters that configure the level of simplification of geometry
    :param height_col: name of the columns storing the height of buildings
    :param nfloor_col: name ofthe column storing the number of floors in buildings.
    :return:
    """
    # read district shapefile and names of buildings of the zone of analysis
    district_building_records = gdf.from_file(district_shp_path).set_index(
        'Name')
    district_building_names = district_building_records.index.values
    zone_building_names = gdf.from_file(zone_shp_path)['Name'].values
    architecture_wwr = gdf.from_file(architecture_path).set_index('Name')

    #make shell out of tin_occface_list and create OCC object
    terrain_shell = construct.make_shell_frm_faces(tin_occface_list)[0]
    terrain_intersection_curves = IntCurvesFace_ShapeIntersector()
    terrain_intersection_curves.Load(terrain_shell, 1e-6)

    #empty list where to store the closed geometries
    geometry_3D_zone = []
    geometry_3D_surroundings = []

    for name in district_building_names:
        height = float(district_building_records.loc[name, height_col])
        nfloors = int(district_building_records.loc[name, nfloor_col])

        # simplify geometry tol =1 for buildings of interest, tol = 5 for surroundings
        if (name in zone_building_names) and (
                simplification_params['consider_floors'] == True):
            range_floors = range(nfloors + 1)
            flr2flr_height = height / nfloors
            geometry = district_building_records.ix[name].geometry.simplify(
                simplification_params['zone_geometry'], preserve_topology=True)
        else:
            range_floors = [0, 1]
            flr2flr_height = height
            geometry = district_building_records.ix[name].geometry.simplify(
                simplification_params['surrounding_geometry'],
                preserve_topology=True)

        # burn buildings footprint into the terrain and return the location of the new face
        face_footprint = burn_buildings(geometry, terrain_intersection_curves)

        # create floors and form a solid
        bldg_solid = calc_solid(face_footprint, range_floors, flr2flr_height)

        # now get all surfaces and create windows only if the buildings are in the area of study
        window_list = []
        wall_list = []
        if (name in zone_building_names):
            if (simplification_params['consider_windows'] == True):
                # identify building surfaces according to angle:
                face_list = py3dmodel.fetch.faces_frm_solid(bldg_solid)
                facade_list_north, facade_list_west, \
                facade_list_east, facade_list_south, roof_list, footprint_list = identify_surfaces_type(face_list)

                # get window properties
                wwr_west = architecture_wwr.ix[name, "wwr_west"]
                wwr_east = architecture_wwr.ix[name, "wwr_east"]
                wwr_north = architecture_wwr.ix[name, "wwr_north"]
                wwr_south = architecture_wwr.ix[name, "wwr_south"]

                window_west, wall_west = calc_windows_walls(
                    facade_list_west, wwr_west)
                if len(window_west) != 0:
                    window_list.extend(window_west)
                wall_list.extend(wall_west)

                window_east, wall_east = calc_windows_walls(
                    facade_list_east, wwr_east)
                if len(window_east) != 0:
                    window_list.extend(window_east)
                wall_list.extend(wall_east)

                window_north, wall_north = calc_windows_walls(
                    facade_list_north, wwr_north)
                if len(window_north) != 0:
                    window_list.extend(window_north)
                wall_list.extend(wall_north)

                window_south, wall_south = calc_windows_walls(
                    facade_list_south, wwr_south)
                if len(window_south) != 0:
                    window_list.extend(window_south)
                wall_list.extend(wall_south)
                geometry_3D_zone.append({
                    "name": name,
                    "windows": window_list,
                    "walls": wall_list,
                    "roofs": roof_list,
                    "footprint": footprint_list
                })

            else:
                facade_list, roof_list, footprint_list = gml3dmodel.identify_building_surfaces(
                    bldg_solid)
                wall_list = facade_list
                geometry_3D_zone.append({
                    "name": name,
                    "windows": window_list,
                    "walls": wall_list,
                    "roofs": roof_list,
                    "footprint": footprint_list
                })
        else:
            facade_list, roof_list, footprint_list = gml3dmodel.identify_building_surfaces(
                bldg_solid)
            wall_list = facade_list
            geometry_3D_surroundings.append({
                "name": name,
                "windows": window_list,
                "walls": wall_list,
                "roofs": roof_list,
                "footprint": footprint_list
            })

    return geometry_3D_zone, geometry_3D_surroundings
コード例 #10
0
def building2d23d(locator, geometry_terrain, settings, height_col, nfloor_col):
    """
    :param locator: InputLocator - provides paths to files in a scenario
    :type locator: cea.inputlocator.InputLocator
    :param settings: parameters that configure the level of simplification of geometry
    :type settings: cea.config.Section
    :param height_col: name of the columns storing the height of buildings
    :param nfloor_col: name ofthe column storing the number of floors in buildings.
    :return:
    """

    consider_windows = True #legacy from config file. now it is always true
    district_shp_path = locator.get_district_geometry()

    # path to zone geometry database
    zone_shp_path = locator.get_zone_geometry()

    # path to database of architecture properties
    architecture_dbf_path = locator.get_building_architecture()

    # read district shapefile and names of buildings of the zone of analysis
    district_building_records = gdf.from_file(district_shp_path).set_index('Name')
    district_building_names = district_building_records.index.values
    zone_building_names = locator.get_zone_building_names()
    architecture_wwr = gdf.from_file(architecture_dbf_path).set_index('Name')

    #make shell out of tin_occface_list and create OCC object
    terrain_shell = construct.make_shell(geometry_terrain)
    terrain_intersection_curves = IntCurvesFace_ShapeIntersector()
    terrain_intersection_curves.Load(terrain_shell, 1e-6)

    #empty list where to store the closed geometries
    geometry_3D_zone = []
    geometry_3D_surroundings = []

    for name in district_building_names:
        print('Generating geometry for building %(name)s' % locals())
        height = float(district_building_records.loc[name, height_col])
        nfloors = int(district_building_records.loc[name, nfloor_col])

        # simplify geometry tol =1 for buildings of interest, tol = 5 for surroundings
        if (name in zone_building_names) and settings.consider_floors:
            range_floors = range(nfloors+1)
            flr2flr_height = height / nfloors
            geometry = district_building_records.ix[name].geometry.simplify(settings.zone_geometry,
                                                                            preserve_topology=True)
        else:
            range_floors = [0,1]
            flr2flr_height = height
            geometry = district_building_records.ix[name].geometry.simplify(settings.surrounding_geometry,
                                                                            preserve_topology=True)

        # burn buildings footprint into the terrain and return the location of the new face
        face_footprint = burn_buildings(geometry, terrain_intersection_curves)

        # create floors and form a solid
        building_solid = calc_solid(face_footprint, range_floors, flr2flr_height)

        # now get all surfaces and create windows only if the buildings are in the area of study
        window_list =[]
        wall_list = []
        orientation = []
        orientation_win = []
        normals_w = []
        normals_win = []
        if (name in zone_building_names):
            if (consider_windows):
                # identify building surfaces according to angle:
                face_list = py3dmodel.fetch.faces_frm_solid(building_solid)
                facade_list_north, facade_list_west, \
                facade_list_east, facade_list_south, roof_list, footprint_list = identify_surfaces_type(face_list)

                # get window properties
                wwr_west = architecture_wwr.ix[name, "wwr_west"]
                wwr_east = architecture_wwr.ix[name, "wwr_east"]
                wwr_north = architecture_wwr.ix[name, "wwr_north"]
                wwr_south = architecture_wwr.ix[name, "wwr_south"]

                window_west, wall_west, normals_windows, normals_walls = calc_windows_walls(facade_list_west, wwr_west)
                if len(window_west) != 0:
                    window_list.extend(window_west)
                    orientation_win.extend(['west'] * len(window_west))
                    normals_win.extend(normals_windows)
                wall_list.extend(wall_west)
                orientation.extend(['west']*len(wall_west))
                normals_w.extend(normals_walls)

                window_east, wall_east, normals_windows, normals_walls  = calc_windows_walls(facade_list_east, wwr_east)
                if len(window_east) != 0:
                    window_list.extend(window_east)
                    orientation_win.extend(['east'] * len(window_east))
                    normals_win.extend(normals_windows)
                wall_list.extend(wall_east)
                orientation.extend(['east'] * len(wall_east))
                normals_w.extend(normals_walls)

                window_north, wall_north, normals_windows_north, normals_walls_north  = calc_windows_walls(facade_list_north, wwr_north)
                if len(window_north) != 0:
                    window_list.extend(window_north)
                    orientation_win.extend(['north'] * len(window_north))
                    normals_win.extend(normals_windows_north)
                wall_list.extend(wall_north)
                orientation.extend(['north'] * len(wall_north))
                normals_w.extend(normals_walls_north)

                window_south, wall_south, normals_windows_south, normals_walls_south  = calc_windows_walls(facade_list_south, wwr_south)
                if len(window_south) != 0:
                    window_list.extend(window_south)
                    orientation_win.extend(['south'] * len(window_south))
                    normals_win.extend(normals_windows_south)
                wall_list.extend(wall_south)
                orientation.extend(['south'] * len(wall_south))
                normals_w.extend(normals_walls_south)


                geometry_3D_zone.append({"name": name, "windows": window_list, "walls": wall_list, "roofs": roof_list,
                                     "footprint": footprint_list, "orientation_walls":orientation, "orientation_windows":orientation_win,
                                         "normals_windows":normals_win, "normals_walls": normals_w })

            else:
                facade_list, roof_list, footprint_list = gml3dmodel.identify_building_surfaces(building_solid)
                wall_list = facade_list
                geometry_3D_zone.append({"name": name, "windows": window_list, "walls": wall_list, "roofs": roof_list,
                                     "footprint": footprint_list, "orientation_walls":orientation, "orientation_windows":orientation_win,
                                         "normals_windows":normals_win, "normals_walls": normals_w})

            # DO this to visualize progress while debugging!:
            # edges1 = calculate.visualise_face_normal_as_edges(wall_list,5)
            # edges2 = calculate.visualise_face_normal_as_edges(roof_list, 5)
            # edges3 = calculate.visualise_face_normal_as_edges(footprint_list, 5)
            # construct.visualise([wall_list, roof_list ,footprint_list , edges1, edges2, edges3],["WHITE","WHITE","WHITE","BLACK", "BLACK","BLACK"])
        else:
            facade_list, roof_list, footprint_list = urbangeom.identify_building_surfaces(building_solid)
            wall_list = facade_list
            geometry_3D_surroundings.append({"name": name, "windows": window_list, "walls": wall_list, "roofs": roof_list,
                                 "footprint": footprint_list, "orientation_walls":orientation, "orientation_windows":orientation_win,
                                  "normals_windows":normals_win, "normals_walls": normals_w})

            ## DO this to visualize progress while debugging!:
            # edges1 = calculate.visualise_face_normal_as_edges(wall_list,5)
            # edges2 = calculate.visualise_face_normal_as_edges(roof_list, 5)
            # edges3 = calculate.visualise_face_normal_as_edges(footprint_list, 5)
            # construct.visualise([wall_list, roof_list ,footprint_list , edges1, edges2, edges3],["WHITE","WHITE","WHITE","BLACK", "BLACK","BLACK"])
    return geometry_3D_zone, geometry_3D_surroundings