Пример #1
0
def _write_boat_area(pier, stg_manager, coords_transform: co.Transformation):
    if len(pier.nodes) < 3:
        return
    # Guess a possible position for realistic boat placement
    linear_ring = shg.LinearRing(pier.nodes)
    centroid = linear_ring.centroid
    # Simplify
    ring = linear_ring.convex_hull.buffer(
        40, cap_style=CAP_STYLE.square,
        join_style=JOIN_STYLE.bevel).simplify(20)
    for p in ring.exterior.coords:
        line_coords = [[centroid.x, centroid.y], p]
        target_vector = shg.LineString(line_coords)
        coords = linear_ring.coords
        for i in range(len(coords) - 1):
            segment = LineString(coords[i:i + 2])
            if segment.length > 20 and segment.intersects(target_vector):
                direction = math.degrees(
                    math.atan2(segment.coords[0][0] - segment.coords[1][0],
                               segment.coords[0][1] - segment.coords[1][1]))
                parallel = segment.parallel_offset(10, 'right')
                boat_position = parallel.interpolate(segment.length / 2)
                try:
                    pos_global = coords_transform.to_global(
                        (boat_position.x, boat_position.y))
                    _write_model(segment.length, stg_manager, pos_global,
                                 direction, pier.elevation)
                except AttributeError as reason:
                    logging.error(reason)
Пример #2
0
def process_details(coords_transform: co.Transformation,
                    lit_areas: Optional[List[shg.Polygon]],
                    fg_elev: utilities.FGElev,
                    file_lock: mp.Lock = None) -> None:
    stats = utilities.Stats()
    lmin, lmax = parameters.get_extent_local(coords_transform)
    clusters = ClusterContainer(lmin, lmax)

    # piers
    the_piers = piers.process_osm_piers(coords_transform)
    logging.info("number of piers: %i", len(the_piers))
    for pier in the_piers:
        clusters.append(pier.anchor, pier, stats)
    for pier in the_piers:
        pier.calc_elevation(fg_elev)

    # platforms
    the_platforms = platforms.process_osm_platform(coords_transform)
    logging.info("number of platforms: %i", len(the_platforms))
    for platform in the_platforms:
        clusters.append(platform.anchor, platform, stats)

    # -- initialize STGManager
    path_to_output = parameters.get_output_path()
    stg_manager = stg_io2.STGManager(path_to_output,
                                     stg_io2.SceneryType.details, OUR_MAGIC,
                                     parameters.PREFIX)

    for cl in clusters:
        if cl.objects:
            cluster_center_global = co.Vec2d(
                coords_transform.to_global(cl.center))
            ac_file_name = "%sd%i%i.ac" % (parameters.PREFIX, cl.grid_index.ix,
                                           cl.grid_index.iy)
            ac = ac3d.File(stats=stats)
            obj = ac.new_object('details',
                                'Textures/Terrain/asphalt.png',
                                default_mat_idx=mat.Material.unlit.value)
            for detail in cl.objects[:]:
                if isinstance(detail, piers.Pier):
                    detail.write(obj, cl.center)
                else:
                    detail.write(fg_elev, obj, cl.center)
            path = stg_manager.add_object_static(
                ac_file_name, cluster_center_global, 0, 0,
                parameters.get_cluster_dimension_radius())
            file_name = os.path.join(path, ac_file_name)
            f = open(file_name, 'w')
            f.write(str(ac))
            f.close()

    piers.write_boats(stg_manager, the_piers, coords_transform)

    # -- write stg
    stg_manager.write(file_lock)

    # trigger processing of pylon related details
    _process_pylon_details(coords_transform, lit_areas, fg_elev, stg_manager,
                           lmin, lmax, file_lock)
Пример #3
0
def match_local_coords_with_global_nodes(
        local_list: List[Tuple[float, float]],
        ref_list: List[int],
        all_nodes: Dict[int, op.Node],
        coords_transform: co.Transformation,
        osm_id: int,
        create_node: bool = False) -> List[int]:
    """Given a set of coordinates in local space find matching Node objects in global space.
    Matching is using a bit of tolerance (cf. parameter), which should be enough to account for conversion precision
    resp. float precision.
    If a node cannot be matched: if parameter create_node is False, then a ValueError is thrown - else a new
    Node is created and added to the all_nodes dict.
    """
    matched_nodes = list()
    nodes_local = dict(
    )  # key is osm_id from Node, value is Tuple[float, float]
    for ref in ref_list:
        node = all_nodes[ref]
        nodes_local[node.osm_id] = coords_transform.to_local(
            (node.lon, node.lat))

    for local in local_list:
        closest_distance = 999999
        found_key = -1
        for key, node_local in nodes_local.items():
            distance = co.calc_distance_local(local[0], local[1],
                                              node_local[0], node_local[1])
            if distance < closest_distance:
                closest_distance = distance
            if distance < parameters.TOLERANCE_MATCH_NODE:
                found_key = key
                break
        if found_key < 0:
            if create_node:
                lon, lat = coords_transform.to_global(local)
                new_node = op.Node(
                    op.get_next_pseudo_osm_id(
                        op.OSMFeatureType.building_relation), lat, lon)
                all_nodes[new_node.osm_id] = new_node
                matched_nodes.append(new_node.osm_id)
            else:
                raise ValueError(
                    'No match for parent with osm_id = %d. Closest: %f' %
                    (osm_id, closest_distance))
        else:
            matched_nodes.append(found_key)

    return matched_nodes
Пример #4
0
def _write_boat_line(pier, stg_manager, coords_transform: co.Transformation):
    line_string = LineString(pier.nodes)
    right_line = line_string.parallel_offset(4,
                                             'left',
                                             resolution=8,
                                             join_style=1,
                                             mitre_limit=10.0)
    if isinstance(right_line, LineString):  # FIXME: what to do else?
        coords = right_line.coords
        for i in range(len(coords) - 1):
            segment = LineString(coords[i:i + 2])
            boat_position = segment.interpolate(segment.length / 2)
            try:
                pos_global = coords_transform.to_global(
                    (boat_position.x, boat_position.y))
                direction = math.degrees(
                    math.atan2(segment.coords[0][0] - segment.coords[1][0],
                               segment.coords[0][1] - segment.coords[1][1]))
                if segment.length > 5:
                    _write_model(segment.length, stg_manager, pos_global,
                                 direction, pier.elevation)
            except AttributeError as reason:
                logging.error(reason)
Пример #5
0
def _create_pseudo_stg_entries_for_exclude_areas(
        areas: Optional[List[List[Tuple[float, float]]]],
        transform: Transformation) -> List[STGEntry]:
    """Create a list of faked STGEntries for exclude areas.

    We cannot control the data quality of the user provided input, so no recovery on error -> fail fast.
    """
    if areas is None or len(areas) == 0:
        return list()
    faked_entries = list()
    for i, list_of_tuples in enumerate(areas):
        my_coordinates = list()
        for lon_lat in list_of_tuples:
            x, y = transform.to_local((lon_lat[0], lon_lat[1]))
            my_coordinates.append((x, y))
        if len(my_coordinates) >= 3:
            my_polygon = shg.Polygon(my_coordinates)
            if my_polygon.is_valid and not my_polygon.is_empty:
                lon, lat = transform.to_global(
                    (my_polygon.centroid.x, my_polygon.centroid.y))
                my_entry = STGEntry(STGVerbType.object_static.name,
                                    'exclude area', 'fake', lon, lat, 0, 0)
                my_entry.convex_hull = my_polygon
                faked_entries.append(my_entry)
            else:
                raise ValueError(
                    'Resulting exclude area polygon is not valid or empty: Entry: %i',
                    i + 1)
        else:
            raise ValueError(
                'There must be at least 3 coordinate tuples per exclude area polygon. Entry: %i',
                i + 1)
    logging.info(
        'Added %i fake static STGEntries for OVERLAP_CHECK_EXCLUDE_AREAS',
        len(faked_entries))
    return faked_entries