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

1 Like

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)}
3 Likes

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)
2 Likes