예제 #1
0
    def add_intermediate_point(self):
        """If last and first points are not the same we need to compute an intermediate point location."""
        """The point is used to close the polygon."""
        coordBegin = OSMCoord.coordDictionnary[self.ref[0]]
        coordEnd = OSMCoord.coordDictionnary[self.ref[-1]]
        distance = length2D(coordBegin.x - coordEnd.x,
                            coordBegin.z - coordEnd.z)
        angle = math.atan2(coordBegin.z - coordEnd.z,
                           coordBegin.x - coordEnd.x)

        # there is two possible 'optimal' intermediate points
        # we select the one that is the farthest from all the other coord (=>inside the lake)
        x1 = math.cos(math.pi / 2 + angle) * (distance / 2) + (coordBegin.x +
                                                               coordEnd.x) / 2
        z1 = math.sin(math.pi / 2 + angle) * (distance / 2) + (coordBegin.z +
                                                               coordEnd.z) / 2
        x2 = -math.cos(math.pi / 2 + angle) * (distance / 2) + (coordBegin.x +
                                                                coordEnd.x) / 2
        z2 = -math.sin(math.pi / 2 + angle) * (distance / 2) + (coordBegin.z +
                                                                coordEnd.z) / 2
        distanceSum1 = OSMMultipolygon.sum_distances_to_coords(
            OSMCoord.coordDictionnary, x1, z1, 2000)
        distanceSum2 = OSMMultipolygon.sum_distances_to_coords(
            OSMCoord.coordDictionnary, x2, z2, 2000)
        if distanceSum1 < distanceSum2:
            x = x1
            z = z1
        else:
            x = x2
            z = z2
        self.ref.append(OSMCoord.add_new_coord_to_list(x, z))
예제 #2
0
 def sum_distances_to_coords(coordlist, x, z, threshold):
     """Return the sum of the distances to each point closer than the threshold."""
     total = 0
     for index in coordlist:
         distance = length2D(coordlist[index].x - x, coordlist[index].z - z)
         if distance <= threshold:
             total = total + distance
     return total
예제 #3
0
 def length(self):
     """Return the length of a barrier."""
     length = 0
     for index in range(len(self.ref)):
         if index > 0:
             x = OSMCoord.coordDictionnary[self.ref[index]].x - OSMCoord.coordDictionnary[self.ref[index - 1]].x
             z = OSMCoord.coordDictionnary[self.ref[index]].z - OSMCoord.coordDictionnary[self.ref[index - 1]].z
             length = length + length2D(x, z)
     return length
예제 #4
0
 def get_tilt(self, p1, p2):
     """Return tilt at p1 in direction of p2."""
     x1 = p1['x'] - p2['x']
     z1 = p1['z'] - p2['z']
     x2 = -z1
     z2 = x1
     len = length2D(x2, z2)
     if len == 0:
         return 0
     x2 = x2 / len
     z2 = z2 / len
     h1 = self.interpolate_height(p1['x'], p2['z'])
     h2 = self.interpolate_height(p1['x'] + x2, p2['z'] + z2)
     return math.atan2(h1 - h2, 1)
예제 #5
0
    def interpolate_height(self, X, Z):
        """Interpolate the height at a given position."""
        xMinus = -float('inf')
        zMinus = -float('inf')
        xPlus = float('inf')
        zPlus = float('inf')
        heights = [0, 0, 0, 0]
        # get the 'boundary' box:
        #        zMinus
        #        0---1
        # xMinus | c | xPlus
        #        3---2
        #        zPlus
        distance = []
        for elevation in self.elevationArray:
            currentX = elevation['x']
            currentZ = elevation['z']
            distance.append(length2D(X - currentX, Z - currentZ))
            if currentX < X:
                if currentX > xMinus:
                    xMinus = currentX
            else:
                if currentX < xPlus:
                    xPlus = currentX
            if currentZ < Z:
                if currentZ > zMinus:
                    zMinus = currentZ
            else:
                if currentZ < zPlus:
                    zPlus = currentZ

        for elevation in self.elevationArray:
            if elevation['x'] == xMinus and elevation['z'] == zMinus:
                heights[0] = elevation['height']
            elif elevation['x'] == xMinus and elevation['z'] == zPlus:
                heights[3] = elevation['height']
            elif elevation['x'] == xPlus and elevation['z'] == zMinus:
                heights[1] = elevation['height']
            elif elevation['x'] == xPlus and elevation['z'] == zPlus:
                heights[2] = elevation['height']

        # compute the ration to determine in which of the two triangle of the box the point lies
        ratio1 = (zPlus - zMinus) / (xPlus - xMinus)
        ratio2 = (Z - zMinus) / (X - xMinus)

        # use a barycentric coordinate system in order to interpolate the value in the triangle
        # http://en.wikipedia.org/wiki/Barycentric_coordinate_system
        x1 = xMinus
        z1 = zMinus
        if ratio2 < ratio1:  # use triangle 0-1-2
            x2 = xPlus
            x3 = xPlus
            z2 = zMinus
            z3 = zPlus
        else:  # use triangle 0-2-3
            x2 = xPlus
            x3 = xMinus
            z2 = zPlus
            z3 = zPlus
        denominator = (z2 - z3) * (x1 - x3) + (x3 - x2) * (z1 - z3)
        lambda1 = ((z2 - z3) * (X - x3) + (x3 - x2) * (Z - z3)) / denominator
        lambda2 = ((z3 - z1) * (X - x3) + (x1 - x3) * (Z - z3)) / denominator
        lambda3 = 1 - lambda1 - lambda2
        if ratio2 < ratio1:
            height = lambda1 * heights[0] + lambda2 * heights[
                1] + lambda3 * heights[2]
        else:
            height = lambda1 * heights[0] + lambda2 * heights[
                2] + lambda3 * heights[3]
        if math.isnan(height) or height == float(
                'inf') or height == -float('inf'):
            return 0
        else:
            return height