def generate_outer_arms(v4a_ss_enu_file, num_clusters_outer,
                        stations_per_outer_cluster,
                        outer_arm_cluster_radius, station_radius_m,
                        num_tries):
    v4a_ss_enu = numpy.loadtxt(v4a_ss_enu_file)
    v4a_ss_enu = v4a_ss_enu[:, 1:]
    v4a_ss_r = (v4a_ss_enu[:, 0]**2 + v4a_ss_enu[:, 1]**2)**0.5
    sort_idx = numpy.argsort(v4a_ss_r)
    v4a_ss_enu = v4a_ss_enu[sort_idx[::-1], :]
    cluster_x = v4a_ss_enu[:num_clusters_outer, 0]
    cluster_y = v4a_ss_enu[:num_clusters_outer, 1]

    # Generate stations at the cluster positions.
    num_stations = num_clusters_outer * stations_per_outer_cluster
    arm_x = numpy.zeros(num_stations)
    arm_y = numpy.zeros(num_stations)
    for i in range(num_clusters_outer):
        for t in range(num_tries):
            x, y, _ = gridgen(stations_per_outer_cluster,
                              outer_arm_cluster_radius * 2.0,
                              station_radius_m * 2.0, 10000)
            if x.shape[0] == stations_per_outer_cluster:
                break
            else:
                print('.', end='')
        if not x.shape[0] == stations_per_outer_cluster:
            raise RuntimeError('Did not generate enough stations in outer arm '
                               'cluster. %i / %i'
                               % (x.shape[0], stations_per_outer_cluster))
        i0 = i * stations_per_outer_cluster
        i1 = i0 + stations_per_outer_cluster
        arm_x[i0:i1] = x + cluster_x[i]
        arm_y[i0:i1] = y + cluster_y[i]

    return arm_x, arm_y, cluster_x, cluster_y
def generate_core_arms_2(num_arms, core_arm_count, stations_per_cluster,
                         arm_cluster_radius, station_radius_m,
                         a, b, delta_theta, arm_offsets, num_tries):
    # Position of station clusters. (generate single arm and rotate to position
    # with stride 3)
    num_clusters = num_arms * core_arm_count
    t = numpy.arange(num_clusters) * delta_theta
    tmp = a * numpy.exp(b * t)
    cluster_x = tmp * numpy.cos(t)
    cluster_y = tmp * numpy.sin(t)
    # cluster_x, cluster_y = rotate_coords(cluster_x, cluster_y, 90.0)
    # cluster_x, cluster_y = rotate_coords(cluster_x, cluster_y, 90.0 + 120.0)
    # cluster_x, cluster_y = rotate_coords(cluster_x, cluster_y, 90.0 + 120.0 + 120.0)
    for i in range(num_arms):
        cluster_x[i::3], cluster_y[i::3] = \
            rotate_coords(cluster_x[i::3], cluster_y[i::3],
                          math.degrees(arm_offsets[i]))

    # Generate stations at the cluster positions.
    num_stations = num_clusters * stations_per_cluster
    arm_x = numpy.zeros(num_stations)
    arm_y = numpy.zeros(num_stations)
    for i in range(num_clusters):
        for t in range(num_tries):
            x, y, _ = gridgen(stations_per_cluster, arm_cluster_radius * 2.0,
                              station_radius_m * 2.0, 30000)
            if x.shape[0] == stations_per_cluster:
                break
            else:
                print('.', end='')
        if not x.shape[0] == stations_per_cluster:
            raise RuntimeError('Did not generate enough stations in arm '
                               'cluster. %i / %i'
                               % (x.shape[0], stations_per_cluster))
        i0 = i * stations_per_cluster
        i1 = i0 + stations_per_cluster
        arm_x[i0:i1] = x + cluster_x[i]
        arm_y[i0:i1] = y + cluster_y[i]

    return arm_x, arm_y, cluster_x, cluster_y
def generate_core_arms(num_arms, core_arm_count, stations_per_cluster,
                       arm_cluster_radius, station_radius_m,
                       a, b, delta_theta, arm_offsets, num_tries):
    # Position of station clusters.
    num_clusters = num_arms * core_arm_count
    cluster_x = numpy.zeros(num_clusters)
    cluster_y = numpy.zeros(num_clusters)
    for i in range(num_arms):
        t = numpy.arange(1, core_arm_count + 1) * delta_theta
        tmp = a * numpy.exp(b * t)
        cx = tmp * numpy.cos(t + arm_offsets[i])
        cy = tmp * numpy.sin(t + arm_offsets[i])
        i0 = i * core_arm_count
        i1 = i0 + core_arm_count
        cluster_x[i0:i1] = cx
        cluster_y[i0:i1] = cy

    # Generate stations at the cluster positions.
    num_stations = num_clusters * stations_per_cluster
    arm_x = numpy.zeros(num_stations)
    arm_y = numpy.zeros(num_stations)
    for i in range(num_clusters):
        for t in range(num_tries):
            x, y, _ = gridgen(stations_per_cluster, arm_cluster_radius * 2.0,
                              station_radius_m * 2.0, 10000)
            if x.shape[0] == stations_per_cluster:
                break
            else:
                print('.', end='')
        if not x.shape[0] == stations_per_cluster:
            raise RuntimeError('Did not generate enough stations in arm '
                               'cluster. %i / %i'
                               % (x.shape[0], stations_per_cluster))
        i0 = i * stations_per_cluster
        i1 = i0 + stations_per_cluster
        arm_x[i0:i1] = x + cluster_x[i]
        arm_y[i0:i1] = y + cluster_y[i]

    return arm_x, arm_y, cluster_x, cluster_y