Trying to draw a point cloud with ruby

I have a cloud point taken with my iPhone and I exported to a txt file with all the points.
The txt file contents somethig like this:

0.4400,0.2284,-5.0440
0.4575,0.2299,-5.0422
0.4666,0.2298,-5.0432
0.4701,0.2288,-5.0401
0.4592,0.2300,-5.0404
0.4684,0.2300,-5.0469
0.4735,0.2300,-5.0465
0.4832,0.2304,-5.0459
0.4957,0.2310,-5.0458
0.5261,0.2307,-5.0441
0.5342,0.2318,-5.0453
0.5480,0.2386,-5.0401
0.5576,0.2378,-5.0449

I work with sketchup for mac so I can’t use Sketchup Essentials extension.
I tried this but it’s a lot of information and sketchup crash

class String
    def numeric?
        Float(self) != nil rescue false
    end
end

model = Sketchup.active_model
entities = model.active_entities
File.foreach(UI.openpanel("Open Text File", "c:/", "Text Files|*.txt||")) { |line|
        a = line.split(',')
        if a[0].numeric? 
        point1 = Geom::Point3d.new(a[0].to_f,a[1].to_f,a[2].to_f)
        constpoint = entities.add_cpoint point1
        end
        }

Is there a better way to draw a point? I couldn’t imagine that drawing a point could be so difficult.
I’m attaching the original file in case someone needs it.
Untitled_Scan_08_11_02.txt (15.3 MB)

Do NOT modify Ruby Core Classes nor SketchUp API modules and classes.

You can use String#start_with? and pass a Regexp as an argument to test a string if it begins with a numeric character:

t.start_with?(/\A[0-9.+-]/)

In the regular expression, \A means match at beginning of string.
The [0-9.+-] is a character class meaning any characters between "0" and "9", or "." or "+" or "-".

1 Like

Never use user input without validation.

In this case if the user cancels the openpanel, then nil is returned.
This will cause File.foreach to raise an exception, …

Error: #<TypeError: no implicit conversion of nil into String>

So validate what is returned from the openpanel.

path = UI.openpanel("Open Text File", "c:/", "Text Files|*.txt||")
if path
  # do the file operation ...
end

Normally this would all be done within a method, so you could just return from the method unless path evaluated truthy …

return unless path
2 Likes

Changed. Sorry for the inconvenience

1 Like

718898 points is a lot.

I guess it is not a crash, but SU busy with the processing.

I was able to import the first ~18k points with this plugin : SketchUp Plugins | PluginStore | SketchUcation
within about 5 minutes, so I guess the full file will take 3-4 hours to process.

Otherwise, I don’t know how to deal with the point clouds further…(or at all) :blush:

1 Like

Thanks for the corrections. I will replace in my code.

Thanks @dezmo. It’s true, I have to force sketchup to exit. I will try to find an algorithm to avoid points that are very closed each other in order to reduce the number of them. Also I will take into account the plugin you mentioned.

My 1st suggestion would be a method like …

def import_point_cloud
  path = UI.openpanel("Open Text File", "c:/", "Text Files|*.txt||")
  return unless path
  text = File.readlines(path)
  points = text.map {|line|
    next nil unless line.start_with?(/\A[0-9.+-]/)
    coords = line.strip.split(',').map(&:to_f)
    Geom::Point3d.new(coords)
  }
  points.compact! # remove nil members
  model = Sketchup.active_model
  entities = model.active_entities
  t = Time.now.to_i
  model.start_operation("Point Cloud",true)
    grp = entities.add_group
    gents = grp.entities
    points.each { |pt| gents.add_cpoint(pt) }
  model.commit_operation
  puts "Elapsed time: #{Time.now.to_i - t} secs"
end

But as @dezmo says a very large file will cause SketchUp to go into “not Responding” mode.

The task of iterating the text array could be broken up into smaller chunks. (More on this later.)

This is bad because in your code, the file is open whilst you are iterating it and adding geometry.
Ruby does not have a chance to close the file handle. I would suggest rebooting the computer whenever you have to force quit an application.

1 Like

1M cpoints is no problem for Sketchup on windows (as long as you use start/commit). There was some kind of bottleneck on mac back in the 2017/2018 days as documented in this thread, maybe it’s still the case…

1 Like

I just tested the OP’s points file with my example method (above) after inserting time marks around the operation. (Updated the example accordingly.)

It took a whopping 4 seconds !

1 Like

No longer, evidently, as it also took 4 seconds on my MBP using @DanRathbun 's code.

1 Like

Is it okayish practice to create 1 million control points with all the overhead of SketchUp entities?

While it’s maybe too complex in the scope of this question and simple code snippet, I think the Scan Essentials just displays them as OpenGL points without creating entities. The advantage is also that with sophisticated file formats (hierarchical, spatially chunked) and loading only points needed for display, one can actually visualize almost an infinite number points.

1 Like

This is the problem with mac. It doesn’t use openGL. Nevertheless there are softwares like Cloudcompare that takes advantage of the M1 chip on mac. I hope Sketchup will use something similar soon.
Point clouds are very common with BIM

Amazing!!! It only took 2 seconds in my Macbook Pro with M1
Thank you very much!!

1 Like

There is not much of an overhead. The cpoints don’t participate in the computational expensive Sketchup “magic” (sticky geometry and so forth). If the cloud is on its own layer it can be turned off as to not bloat the inference engine. Graphics wise, 1 million points is on the heavy side (on my dated computer) - 500 000 is perfectly smooth. The biggest drawback with cpoints is that the assigned material is not shown so you have to resort to color by layer.

2 Likes

Where did you get that idea? Although Apple has deprecated OpenGL - meaning they no longer develop new versions and could drop it from some future version of macOS - as of Monterey 12.4 it still comes with macOS and SketchUp still uses it.

1 Like

I thought that OpenGL doesn’t work on mac with M1 chips

See for example OpenGL on Big Sur? | Apple Developer Forums

1 Like

Gosh we did a similar exercise in my office a few years back for land surveying. Without detracting from SU we went for a spreadsheet via CAD process. The spreadsheet handled basic conversions from Lat Long to metres. The metres were then exported to *.dxf (I think) which we were able to import into CAD. It could just as easily be imported in SU. I don’t remember that any coding was necessary. Maybe this is a slightly different application but just thought I’d mention it.

Uh, yea, the example points are thousandths of an inch apart, so equating them to a scenario with LatLong coordinates is way off the mark (pun intended).

Then again, this is the Ruby API category and the OP specifically indicates that Ruby is to be used.

The example points file looks like something output by a laser scanner.
The resultant point cloud looks to be describing something rather organic.

Why ( rhetorical ), when a text points file can be directly imported (as shown above) would the OP want to involve another application (spreadsheet) and export to a different file format (dxf) ?

This would just add time and complexity to a simple problem. (Also, SketchUp’s native dwg/dxf importer has it’s own open issues that may need fixing, so this may add in more complexity.)