Comparing two Point3d arrays

I have an Array (facepoints) with various Vertex positions of a face. I would like to check which points from the checkpoints Array correspond to a Vertex position of the face.

facepoints = [Point3d(109.803, 0, 0), Point3d(0, 0, 0), Point3d(10, 9.25197, 0), Point3d(119.803, 9.25197, 0)]
checkpoints = [Point3d(109.803, 0, 0), Point3d(10, 0, 0)]

In situations like this I often use the AND operator to see which values match between both Arrays.

facepoints = [1, 2, 3, 4]
checkpoints = [2, 5]
samepoint = facepoints & checkpoints
# samepoint = [2]

But when I apply this for the Point3d arrays I get the following error in SketchUp.

Error: #<NoMethodError: undefined method `Point3d' for main:Object>

How would you compare these two arrays?

Hi,
Use point1 == point2 ⇒ Boolean as a test instead of a and operator which doesn’t work with point3d objects.

The == method is used to compare two points for equality.

samepoint = facepoints.map(&:to_a) & checkpoints.map(&:to_a)

john

The first issue is that you are not calling a constructor for your Point3d…

facepoints = [Geom::Point3d.new(109.803, 0, 0), Geom::Point3d.new(0, 0, 0), Geom::Point3d.new(10, 9.25197, 0), Geom::Point3d.new(119.803, 9.25197, 0)]
checkpoints = [Geom::Point3d.new(109.803, 0, 0), Geom::Point3d.new(10, 0, 0)]

the second I was going to answer the same as @john_drivenupthewall => map them to arrays first.

I noticed OP stated this as the answer, but it is incomplete:

facepoints = [Point3d(109.803, 0, 0), Point3d(0, 0, 0), Point3d(10, 9.25197, 0), Point3d(119.803, 9.25197, 0)]
checkpoints = [Point3d(109.803, 0, 0), Point3d(10, 0, 0)]
samepoint = facepoints.map(&:to_a) & checkpoints.map(&:to_a)

will still throw

Error: #<NoMethodError: undefined method `Point3d' for main:Object>

because, OP is lacking the usage of a valid constructor for the Point3d, this fixes it:

facepoints = [Geom::Point3d.new(109.803, 0, 0), Geom::Point3d.new(0, 0, 0), Geom::Point3d.new(10, 9.25197, 0), Geom::Point3d.new(119.803, 9.25197, 0)]
checkpoints = [Geom::Point3d.new(109.803, 0, 0), Geom::Point3d.new(10, 0, 0)]
samepoint = facepoints.map(&:to_a) & checkpoints.map(&:to_a)

EDIT.

  • @nnijmeijer if in the end you still need a Point3d, you should map them back to points, so this would solve it all:
facepoints = [Geom::Point3d.new(109.803, 0, 0), Geom::Point3d.new(0, 0, 0), Geom::Point3d.new(10, 9.25197, 0), Geom::Point3d.new(119.803, 9.25197, 0)]
checkpoints = [Geom::Point3d.new(109.803, 0, 0), Geom::Point3d.new(10, 0, 0)]
samepoint = (facepoints.map(&:to_a) & checkpoints.map(&:to_a)).map{|a| Geom::Point3d.new(a)}

Comparison needs to be done using the API’s tolerance for coordinates.
Also it is not necessary to collect the face’s vertex point positions into an array for this exercise, ie …

def get_points_on_vertices(face, checkpoints)
  checkpoints.find_all { |pt| 
    face.classify_point(pt) == Sketchup::Face::PointOnVertex
  }
end

# Then later in code  ...
vert_pts = get_points_on_vertices(face, checkpoints)