How to generate a random convex polygon?

前端 未结 6 1172
南旧
南旧 2021-02-05 11:19

I\'m trying to devise a method for generating random 2D convex polygons. It has to have the following properties:

  • coordinates should be integers;
  • the poly
6条回答
  •  温柔的废话
    2021-02-05 11:26

    I've made the ruby port as well thanks to both @Mangara's answer and @Azat's answer:

    #!/usr/bin/env ruby
    # frozen_string_literal: true
    
    module ValtrAlgorithm
      module_function def random_polygon(length)
        raise ArgumentError, "length should be > 2" unless length > 2
    
        min_x, *xs, max_x = Array.new(length) { rand }.sort
        min_y, *ys, max_y = Array.new(length) { rand }.sort
        # Divide the interior points into two chains and
        # extract the vector components.
        vec_xs = to_random_vectors(xs, min_x, max_x)
        vec_ys = to_random_vectors(ys, min_y, max_y).
          # Randomly pair up the X- and Y-components
          shuffle
        # Combine the paired up components into vectors
        vecs = vec_xs.zip(vec_ys).
          # Sort the vectors by angle, in a counter clockwise fashion. Remove the
          # `-` to make it clockwise.
          sort_by { |x, y| - Math.atan2(y, x) }
    
        # Lay them end-to-end
        point_x = point_y = 0
        min_polygon_x = min_polygon_y = 0
        points = []
        vecs.each do |vec_x, vec_y|
          points.append([vec_x, vec_y])
          point_x += vec_x
          point_y += vec_y
          min_polygon_x = [min_polygon_x, point_x].min
          min_polygon_y = [min_polygon_y, point_y].min
        end
        shift_x = min_x - min_polygon_x
        shift_y = min_y - min_polygon_y
        result = points.map { |point_x, point_y| [point_x + shift_x, point_y + shift_y] }
        # Append first point to make it a valid linear ring
        result << result.first
      end
    
      private def to_random_vectors(coordinates, min, max)
        last_min = last_max = min
        ary = []
        coordinates.each do |coordinate|
          if rand > 0.5
            ary << coordinate - last_min
            last_min = coordinate
          else
            ary << last_max - coordinate
            last_max = coordinate
          end
        end
        ary << max - last_min << last_max - max
      end
    end
    

提交回复
热议问题