Raytest is failing me (or the other way around, probably)

I have two (solid) intersecting components shown in the image; let’s call them “post” and “peg” (the peg is the cylinder). I wish to place contruction points as new entities of the post. The points are to be placed where the center line of the peg intersects the post.

For what’s it worth, the post in the model is 8"x8"x6’ and the peg is 3/4" diameter, 10" long and protrudes from the post 1" on each side. The axes of the two components are oriented the same. The peg’s origin is at the end of the peg on the left side of the post (and displaced 1" from the post axis in the y-direction).

The code below mostly works but after the transformation from the peg space to the post space, the y-coordinate is not what I expect.

Here’s the output from the ruby console:

Found Peg face: #<Sketchup::Face:0x007f931f103010>, area: 0.4367571386105076, center:
Peg face #<Sketchup::Face:0x007f931f103010> intersected component #developers <Sketchup::ComponentInstance:0x007f931e4323b8> at (0.375", 8", 0.375"), (d=8")
pc2:(6.5", 6.979575", 51.782654")
Found Peg face: #<Sketchup::Face:0x007f931f101e18>, area: 0.4367571386105075, center: (0.375", 10", 0.375")
Peg face #<Sketchup::Face:0x007f931f101e18> intersected component #<Sketchup::ComponentInstance:0x007f931e4323b8> at (0.375", 8", 0.375"), (d=2")
pc2:(6.5", 6.979575", 51.782654")

Notice that the two peg faces with centers at (0.375", 0", 0.375") and (0.375", 10", 0.375") are expected results. Why would mod.raytest return the same point on two difference faces? That point3d location doesn’t reference anything in the rays path (from what I can tell).

Any hints on what I’m doing wrong are welcome.

Thanks!

              faces = peg.definition.entities.grep(Sketchup::Face)
              areas = faces.map { |f| f.area }
              min, max = areas.minmax
              peg_faces = faces.select { |f| (f.area - min).abs < 0.001 }
              if peg_faces.size != 2
                print("Odd, ", peg_faces.size, " peg faces, only expected two!\n")
              end

              mod = Sketchup.active_model
              peg_faces.each { |f|
                pc = Geom::Point3d.new(f.bounds.center)
                pv = Geom::Vector3d.new(f.normal.reverse)
                print("Found Peg face: ", f.to_s, ", area: ", f.area, ", center: ", pc.to_s, "\n")
                item = mod.raytest([pc, pv], true)
                if item
                  pc = item[0]
                  c = item[1][0]
                  d = f.bounds.center.distance(item[0])
                  
                  print("Peg face ", f, " intersected component ", c.to_s, " at ", pc, ", (d=", d, ")\n")
                  tr = c.transformation.inverse * peg.transformation
                  pc.transform!(tr)
                  print("pc2:" + pc.to_s + "\n")
                else
                  print("raytest failed!\n")
                end

SU 2017 (17.3.116)

The basic error is that face.bounds.center for a face within a component definition returns the value in the local coordinates of that component definition, not in the global coordinates of the model. But raytest wants the Point3d and Vector3d to be in the model’s global coordinates. That’s why, for example, you see a face with center at (3/8,10,3/8) when in model coordinates the end of the peg is not at that location. You need to transform to global coordinates before doing the raytest, then transform the “hit point” back into the post’s local coordinates.

Edit: yes, the API documentation does not make that clear!

2 Likes

Why thank you slbaumgartner! Now I’ll start researching how to transform to model coordinates.

Forum Search: “transform to model coordinates”

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.