Esempio n. 1
0
 def get_next_edge(self, ground_tin, tr, origin, destination):
     """
     Explanation: returns the next edge in the triangle which the path crosses
     ---------------
     Input:
         receiver : tuple(x,y,z) - the receiver point we walk from
         ground_tin : ground_Tin object - stores the whole tin
         tr : integer - id of the current triangle
     ---------------
     Output:
         list - two vertices of the edge.
     """
     edges = (
         (ground_tin.trs[tr][0], ground_tin.trs[tr][1]),
         (ground_tin.trs[tr][1], ground_tin.trs[tr][2]),
         (ground_tin.trs[tr][2], ground_tin.trs[tr][0])
         )
     # Go over the edges
     for i, edge in enumerate(edges):
         # Check if the orientation is correct
         if (misc.side_test(origin, destination, ground_tin.vts[edge[0]]) <= 0 and
                 misc.side_test(origin, destination, ground_tin.vts[edge[1]]) > 0):
             return i, edge
     
     print("something went wrong here")
     assert(False)
Esempio n. 2
0
    def intersection_point(self, edge, source, receiver):
        """
        Explanation:
        ---------------
        Input:
        edge: (vi, vj) - vi is the index of a vertex in the vertex list
        source: (x,y,z) - the source point we want to walk to
        receiver: (x,y,z) - the receiver point we walk from
        ---------------
        Output:
        np.array((x,y,z)) - intersection between edge and receiver-source segment
        """
        vertex_right = np.array(self.vts[edge[0]])
        vertex_left = np.array(self.vts[edge[1]])

        # get the absolute area of the 2* the triangle (the rectangle of length from source to receiver and width the perpendicular distance to point p)
        area_right = abs(misc.side_test(receiver, source, vertex_right))
        area_left = abs(misc.side_test(receiver, source, vertex_left))

        # quick check, debug:
        if ((area_left + area_right) < 0.1):
            # if edge and both triangles are collinear, put the point half way.
            part_right = 0.5
        else:
            # find where on the line (percentile) the cross section is.
            part_right = area_right / (area_left + area_right)

        # take vertex_right and append a part of the vector from right to left to it
        intersection_point = vertex_right + (vertex_left -
                                             vertex_right) * part_right

        return intersection_point
Esempio n. 3
0
    def get_offsets_perpendicular(self, start, end):
        """
        Explination:
            calculates the perpendicular distance from points to the the line
        ---------------
        Input: 
            Start: integer - id of the start point
            end: integer - id of the end point
        ---------------
        Output: 
            numpy array - array of the offsets of points along line segment
        """
        p_start = self.vts[start]
        p_end = self.vts[end]
        line_length = ((p_end[2] - p_start[2])**2 +
                       (p_end[0] - p_start[0])**2)**0.5
        offsets = []

        for id in range(start + 1, end):
            # do side test (return lenght of line x perpendicualr distace) so devide it by the length and voila
            diff = abs(
                misc.side_test(
                    (p_start[0], p_start[2]), (p_end[0], p_end[2]),
                    (self.vts[id, 0], self.vts[id, 2]))) / line_length
            offsets.append(diff)

        return np.array(offsets)
Esempio n. 4
0
    def find_receiver_triangle(self, tr_init, p_receiver):
        """
        Explanation: Find the triangle in which the p_source is located, by means of walking from tr_init to the right triangle
        ---------------
        Input:
            tr_init : integer - An (arbitrary) triangle id to start from.
            p_receiver : [x,y,z] - The receiver point.
        ---------------
        Output:
            integer - triangle id of triangle underneath source point
        """
        #print("=== find_receiver_triangle ===")
        tr = tr_init
        for i in range(1000):  # max 1000 triangles to walk.
            # do the side test for all sides, returns the value
            d1 = misc.side_test(self.vts[self.trs[tr][0]],
                                self.vts[self.trs[tr][1]], p_receiver)
            d2 = misc.side_test(self.vts[self.trs[tr][1]],
                                self.vts[self.trs[tr][2]], p_receiver)
            d3 = misc.side_test(self.vts[self.trs[tr][2]],
                                self.vts[self.trs[tr][0]], p_receiver)

            # If all side_tests are positive (point is either exactly on the edge, or on the inside)
            if d1 >= 0 and d2 >= 0 and d3 >= 0:
                return tr
            # when one the the tests returns negative, we have to go to the next triangle,
            # first find the direction to go to:
            # turn it into a list, and get the minimum
            d = [d1, d2, d3]
            d_min = d.index(min(d))

            # find the right neighbouring triangle to go to.
            nbs = [5, 3, 4]
            nb_index = nbs[d_min]

            # get the index of the neighbour triangle
            tr = self.trs[tr][nb_index]
        print("no tr found after 1000 loops")
        assert (False)
Esempio n. 5
0
    def check_validity(self, building_id, building_manager, tin,
                       reflection_point, building_height,
                       minimal_height_difference):
        triangle_index_building = np.where(tin.attributes == building_id)
        triangle_index_building = triangle_index_building[0][0]
        #print("random tr index of building: {}".format(triangle_index_building))
        # find the triangle where the reflection point is in (it is on the line though.)
        reflection_triangle = tin.find_receiver_triangle(
            triangle_index_building, reflection_point)
        #print("correct tr of building: {}".format(tin.attributes[reflection_triangle]))

        # can be either on the building side, or on the outerside
        # If the triangle is on the inside, get the triangle on the outside
        if (tin.attributes[reflection_triangle] == building_id):
            #print("triangle is on inside")
            # the triangle is on the inside of the building
            # now get neighbor
            edges = ((tin.vts[tin.trs[reflection_triangle][0]],
                      tin.vts[tin.trs[reflection_triangle][1]]),
                     (tin.vts[tin.trs[reflection_triangle][1]],
                      tin.vts[tin.trs[reflection_triangle][2]]),
                     (tin.vts[tin.trs[reflection_triangle][2]],
                      tin.vts[tin.trs[reflection_triangle][0]]))
            # find which edge intersects with the point.
            neighbor = -1
            for i, edge in enumerate(edges):
                # side the side test is very much close to 0, it is the right edge
                if (abs(misc.side_test(edge[0], edge[1], reflection_point)) <
                        0.05):
                    neighbor = i
            assert (neighbor != -1)
            nbs = [5, 3, 4]
            reflection_triangle = tin.trs[reflection_triangle][nbs[neighbor]]

        #print("triangle type on outside: {}".format(tin.attributes[reflection_triangle]))
        # we should have the correct triangle at hand
        if (tin.attributes[reflection_triangle][0] == 'b'):
            #print("other triangle is building")
            # it is a building
            outside_building_height = building_manager.buildings[
                tin.attributes[reflection_triangle]].roof_level
            if (building_height - outside_building_height >
                    minimal_height_difference):
                # building is atleast 20 centimeters higher then
                return True
            else:
                return False
        else:
            # not a building, so its fine (should be, there should not be buildings below ground level in the dataset)
            return True
Esempio n. 6
0
    def point_in_triangle(self, pt, tr):
        """
        Explanation: Do a side test for all edges with the pt, if they are all positive.
        ---------------
        Input:
        pt : [x,y,z] - The point to check.
        tr : integer - triangle ID.
        ---------------
        Output:
            Boolean - True if the point is inside the triangle.
        """
        e = 10**(-4)
        d1 = misc.side_test(self.vts[self.trs[tr][0]],
                            self.vts[self.trs[tr][1]], pt)
        d2 = misc.side_test(self.vts[self.trs[tr][1]],
                            self.vts[self.trs[tr][2]], pt)
        d3 = misc.side_test(self.vts[self.trs[tr][2]],
                            self.vts[self.trs[tr][0]], pt)

        if d1 >= -e and d2 >= -e and d3 >= -e:
            return True  # the point is in the triangle
        else:
            return False
Esempio n. 7
0
    def get_first_order_reflection(self,
                                   building_manager,
                                   tin,
                                   minimal_height_difference,
                                   radius_buffer=2000):
        """
        Explanation: A function that reads a buildings_dict and computes all possible first-ORDER reflection paths,
        according to the receivers and sources that are provided from main.py
        ---------------
        Input:
        buildings_dict : BuildingManager object - stores all the building objects
        ---------------
        Output:
        Stores reflection points, and their corresponding heights in the class.
        return True if reflections are found, False if not
        """
        query_geom = Point(self.receiver).buffer(
            radius_buffer)  # 2000 m buffer around receiver
        chosen_buildings = building_manager.buildings_tree.query(query_geom)
        for chosen_building in chosen_buildings:
            building_id = building_manager.polygon_id_to_building_id[id(
                chosen_building)]
            building = building_manager.buildings[building_id]

            if building.underground:
                continue

            number_of_walls = len(building.walls)

            for wall_id, wall in enumerate(building.walls):
                test_r = misc.side_test(wall[0], wall[1], self.receiver)
                test_s = misc.side_test(wall[0], wall[1],
                                        self.source.source_coords)

                # COS: Not sure if this is actually true!!!!
                if test_r > 0 and test_s > 0:  # This statement guarantees that the source and receiver are both on the outer side of the wall
                    # Get the mirrored source over the wall segment
                    s_mirror = self.get_mirror_point(
                        misc.parametric_line_equation(wall[0], wall[1]))
                    # find the intersection point, returns False is they do not intersect.
                    reflection_point = misc.line_intersect(
                        wall, [s_mirror, self.receiver])
                    # ref is false if there is no reflection.
                    if reflection_point:
                        angle = 0.01745329252  # Hardcoded Angle in radians (1 degree or 2.pi / 360)

                        # take the mirror point and check if reflection path is longer than 2Km
                        receiver_array = np.array(self.receiver)
                        mirrored_source_array = np.array(s_mirror)

                        # check distance between reflection point and mirrored source
                        reflection_point_array = np.array(reflection_point)
                        dist = np.linalg.norm(reflection_point_array -
                                              mirrored_source_array)
                        if dist <= 2000:

                            # rotate the mirrored point 1 degree to the left and look for an intersection with the building
                            left_point = misc.get_rotated_point(
                                receiver_array, mirrored_source_array, angle)
                            wall_adjusted_order_left = np.array(
                                range(wall_id, number_of_walls + wall_id,
                                      1)) % number_of_walls
                            is_left_valid = self.check_relative_size(
                                wall_adjusted_order_left, building, left_point)

                            if is_left_valid:
                                # rotate the mirrored point 1 degree to the right and look for an intersection with the building
                                right_point = misc.get_rotated_point(
                                    receiver_array, mirrored_source_array,
                                    -angle)
                                wall_adjusted_order_right = np.array(
                                    range(number_of_walls + wall_id, wall_id,
                                          -1)) % number_of_walls
                                is_right_valid = self.check_relative_size(
                                    wall_adjusted_order_right, building,
                                    right_point)

                                if is_right_valid:
                                    # Check if reflection is valid, ie if there is no other taller building in front.
                                    if (self.check_validity(
                                            building_id, building_manager, tin,
                                            reflection_point,
                                            building.roof_level,
                                            minimal_height_difference)):
                                        # If the reflection object is of sufficient size, and the reflection is valid, store it
                                        self.reflection_points.append(
                                            [reflection_point])
                                        self.reflection_heights.append(
                                            [building.roof_level])

        if len(self.reflection_points) > 0:
            return True
        return False