Move points to a '3D grid'
-
Hi,
I am trying to write a script for cleaning up geometery created from another program (IES VE). Essentially what I want to achieve is to move each vertex so it sits on a '3D grid'. I believe this could be achieved by applying a rounding function to the X,Y and Z coordinates of each point.
The attached image hopefully illustrates what I am trying to achieve. Ideally the degree of rounding would be a user input variable.
Any help on this would be greatly appreciated.
Ross
-
You can use the scale tool: begin to scale then type 400mm;400mm;400mm + enter.
Note that the separator may be "," for you .
-
-
This is a nice idea - I might implement such a feature in Vertex Tools.
Of the top of my head, something like this:
pt = Geom::Point3d.new( 3.976879, 3.970209, 1.002568 ) grid_pt = pt.to_a.map { |n| n.round() } v = pt.vector_to( grid_pt )
You can do something like that - iterate the vertices of a mesh, for each vertex find the nearest grid position to the vertex, collect the vertex and adjustment vector to each their array and use
Entities.transform_by_vectors
https://developers.google.com/sketchup/docs/ourdoc/entities#transform_by_vectorsNote that this simple example rounded to nearest whole number. Modifications is needed to account for grids fitted to decimal precision.
-
Actually, that example will round to nearest inch - which is SketchUp's internal unit...
-
<span class="syntaxdefault">pt </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> Geom</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">Point3d</span><span class="syntaxkeyword">.new(</span><span class="syntaxdefault"> 3.976879</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">m</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> 3.760209</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">m</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> 1.002568</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">m </span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">tolerance </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> 0.25</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">m<br />grid_pt </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> pt</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">to_a</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">map </span><span class="syntaxkeyword">{</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">|</span><span class="syntaxdefault">n</span><span class="syntaxkeyword">|<br /></span><span class="syntaxdefault"> b </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">(</span><span class="syntaxdefault"> n </span><span class="syntaxkeyword">/</span><span class="syntaxdefault"> tolerance </span><span class="syntaxkeyword">).</span><span class="syntaxdefault">to_i </span><span class="syntaxkeyword">*</span><span class="syntaxdefault"> tolerance<br /> r </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> n </span><span class="syntaxkeyword">%</span><span class="syntaxdefault"> tolerance<br /> </span><span class="syntaxkeyword">(</span><span class="syntaxdefault">r </span><span class="syntaxkeyword">></span><span class="syntaxdefault"> tolerance </span><span class="syntaxkeyword">/</span><span class="syntaxdefault"> 2</span><span class="syntaxkeyword">)</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">?</span><span class="syntaxdefault"> b </span><span class="syntaxkeyword">+</span><span class="syntaxdefault"> tolerance </span><span class="syntaxkeyword">;</span><span class="syntaxdefault"> b<br /></span><span class="syntaxkeyword">}<br /></span><span class="syntaxdefault">grid_pt </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> Geom</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">Point3d</span><span class="syntaxkeyword">.new(</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">*</span><span class="syntaxdefault">grid_pt </span><span class="syntaxkeyword">)<br /><br /></span><span class="syntaxdefault">puts </span><span class="syntaxstring">"Original; #{pt}"<br /></span><span class="syntaxdefault">puts </span><span class="syntaxstring">"Tolerance; #{tolerance}"<br /></span><span class="syntaxdefault">puts </span><span class="syntaxstring">"Grid Point; #{grid_pt}" </span><span class="syntaxdefault"></span>
Output:
Original: (3976,879mm, 3760,209mm, 1002,568mm) Tolerance: 250mm Grid Point: (4000mm, 3750mm, 1000mm)
-
Test module - adjust the vertices in the active context to grid.
<span class="syntaxdefault">module GridSnap<br /><br /> def self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">round_point</span><span class="syntaxkeyword">( </span><span class="syntaxdefault">point</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">tolerance </span><span class="syntaxkeyword">)<br /> </span><span class="syntaxdefault">grid_pt </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">point</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">to_a</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">map </span><span class="syntaxkeyword">{ |</span><span class="syntaxdefault">n</span><span class="syntaxkeyword">|<br /> </span><span class="syntaxdefault">b </span><span class="syntaxkeyword">= ( </span><span class="syntaxdefault">n </span><span class="syntaxkeyword">/ </span><span class="syntaxdefault">tolerance </span><span class="syntaxkeyword">).</span><span class="syntaxdefault">to_i </span><span class="syntaxkeyword">* </span><span class="syntaxdefault">tolerance<br /> r </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">n </span><span class="syntaxkeyword">% </span><span class="syntaxdefault">tolerance<br /> </span><span class="syntaxkeyword">(</span><span class="syntaxdefault">r </span><span class="syntaxkeyword">> </span><span class="syntaxdefault">tolerance </span><span class="syntaxkeyword">/ </span><span class="syntaxdefault">2</span><span class="syntaxkeyword">) ? </span><span class="syntaxdefault">b </span><span class="syntaxkeyword">+ </span><span class="syntaxdefault">tolerance </span><span class="syntaxkeyword">; </span><span class="syntaxdefault">b<br /> </span><span class="syntaxkeyword">}<br /> </span><span class="syntaxdefault">Geom</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">Point3d</span><span class="syntaxkeyword">.new( *</span><span class="syntaxdefault">grid_pt </span><span class="syntaxkeyword">)<br /> </span><span class="syntaxdefault">end<br /> <br /> def self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">test_it<br /> pt </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">Geom</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">Point3d</span><span class="syntaxkeyword">.new( </span><span class="syntaxdefault">3.976879</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">m</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">3.760209</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">m</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">1.002568</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">m </span><span class="syntaxkeyword">)<br /> </span><span class="syntaxdefault">tolerance </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">0.25</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">m<br /> grid_pt </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">round_point</span><span class="syntaxkeyword">( </span><span class="syntaxdefault">pt</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">tolerance </span><span class="syntaxkeyword">)<br /> <br /> </span><span class="syntaxdefault">puts </span><span class="syntaxstring">"Original; #{pt}"<br /> </span><span class="syntaxdefault">puts </span><span class="syntaxstring">"Tolerance; #{tolerance}"<br /> </span><span class="syntaxdefault">puts </span><span class="syntaxstring">"Grid Point; #{grid_pt}"<br /> </span><span class="syntaxdefault">end<br /> <br /> def self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">adjust_vertices</span><span class="syntaxkeyword">( </span><span class="syntaxdefault">tolerance </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">0.25</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">m </span><span class="syntaxkeyword">)<br /> </span><span class="syntaxdefault">model </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">Sketchup</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">active_model<br /> vertices </span><span class="syntaxkeyword">= []<br /> </span><span class="syntaxcomment"># Collect vertices.<br /> </span><span class="syntaxkeyword">for </span><span class="syntaxdefault">e in model</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">active_entities<br /> vertices </span><span class="syntaxkeyword"><< </span><span class="syntaxdefault">e</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">vertices </span><span class="syntaxkeyword">if </span><span class="syntaxdefault">e</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">is_a</span><span class="syntaxkeyword">?( </span><span class="syntaxdefault">Sketchup</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">Edge </span><span class="syntaxkeyword">)<br /> </span><span class="syntaxdefault">end<br /> vertices</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">flatten</span><span class="syntaxkeyword">!<br /> </span><span class="syntaxdefault">vertices</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">uniq</span><span class="syntaxkeyword">!<br /> </span><span class="syntaxcomment"># Calculate grid adjustments.<br /> </span><span class="syntaxdefault">vectors </span><span class="syntaxkeyword">= []<br /> </span><span class="syntaxdefault">entities </span><span class="syntaxkeyword">= []<br /> for </span><span class="syntaxdefault">vertex in vertices<br /> pt </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">vertex</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">position<br /> grid_pt </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">round_point</span><span class="syntaxkeyword">( </span><span class="syntaxdefault">pt</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">tolerance </span><span class="syntaxkeyword">)<br /> </span><span class="syntaxdefault">vector </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">pt</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">vector_to</span><span class="syntaxkeyword">( </span><span class="syntaxdefault">grid_pt </span><span class="syntaxkeyword">)<br /> </span><span class="syntaxdefault">next unless vector</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">valid</span><span class="syntaxkeyword">?<br /> </span><span class="syntaxdefault">entities </span><span class="syntaxkeyword"><< </span><span class="syntaxdefault">vertex<br /> vectors </span><span class="syntaxkeyword"><< </span><span class="syntaxdefault">vector<br /> end<br /> </span><span class="syntaxcomment"># Apply transformations<br /> </span><span class="syntaxdefault">model</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">active_entities</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">transform_by_vectors</span><span class="syntaxkeyword">( </span><span class="syntaxdefault">entities</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">vectors </span><span class="syntaxkeyword">)<br /> </span><span class="syntaxdefault">puts </span><span class="syntaxstring">"#{entities.size} adjusted to grid."<br /> </span><span class="syntaxdefault">end<br /><br />end<br /></span>
-
How about that ??
... from concept to module in under a hour.
-
Could this then be a tiny step towards a poly-reducer?
As the vertices are 'rationalized' onto a 'grid' some faces could become coplanar and therefore the superfluous shared edges could be removed.
The fineness/coarseness of this 'grid' removes less/more 'detailing'...
-
Cubificator?
I was thinking it might be usable to repair troublesome model imported from CAD drawings. Occasionally I run into models where splitting a face with an edge results in duplicate faces. I suspect its due to some precision errors. Maybe if the vertices where adjusted to fit to a finely grained 3D grid the troubles would go away... ?
-
ThomThom thanks so much for your support! I have had a go at running your test module. My understanding is that it should shift the points in the active selection to a 0.25m grid as specified in the code.
However I am having problems running the module. I have attempted to add it to the tools menu as below, but I am not 100% sure how to 'call' the routine. Appologies if I'm being an idiot - I am new to ruby scripting!
module GridSnap def self.round_point( point, tolerance ) grid_pt = point.to_a.map { |n| b = ( n / tolerance ).to_i * tolerance r = n % tolerance (r > tolerance / 2) ? b + tolerance ; b } Geom;;Point3d.new( *grid_pt ) end def self.test_it pt = Geom;;Point3d.new( 3.976879.m, 3.760209.m, 1.002568.m ) tolerance = 0.25.m grid_pt = self.round_point( pt, tolerance ) puts "Original; #{pt}" puts "Tolerance; #{tolerance}" puts "Grid Point; #{grid_pt}" end def self.adjust_vertices( tolerance = 0.25.m ) model = Sketchup.active_model vertices = [] # Collect vertices. for e in model.active_entities vertices << e.vertices if e.is_a?( Sketchup;;Edge ) end vertices.flatten! vertices.uniq! # Calculate grid adjustments. vectors = [] entities = [] for vertex in vertices pt = vertex.position grid_pt = self.round_point( pt, tolerance ) vector = pt.vector_to( grid_pt ) next unless vector.valid? entities << vertex vectors << vector end # Apply transformations model.active_entities.transform_by_vectors( entities, vectors ) puts "#{entities.size} adjusted to grid." end end # Menu Entry; UI.menu("Tools").add_item("GridSnap") { GridSnap } if not file_loaded?("GridSnap.rb") file_loaded("GridSnap.rb")
I think this could be a very useful tool for cleaning many types of imported geometry.
Ross
-
-
In case TT is away...
Inside the code making the menu use
{GridSnap**.adjust_vertices(1.cm)**}
It affects the whole model.
This example uses 1cm grid
Use another 'tolerance' if desired...
If you use()
it defaults to 0.25m anyway...
It's only some example code and could be better assembled into something working on a selection with warnings and an 'undo' ??? -
Not sure this reduced poly rock is so good ?'Cuboidalizer' is another name idea too... that or 'Discombobulizer'
-
Here's a beta version with an inputbox and undo operation...
It seemed to only change a cubes vertices in the Z axis ??
module GridSnap @@last_tolerance = 0.25.m class << self # PROXY CLASS def round_point( point, tolerance ) grid_pt = point.to_a.map { |n| b = ( n / tolerance ).to_i * tolerance r = n % tolerance (r > tolerance / 2) ? b + tolerance ; b } Geom;;Point3d.new( *grid_pt ) end def test_it pt = Geom;;Point3d.new( 3.976879.m, 3.760209.m, 1.002568.m ) tolerance = @@last_tolerance grid_pt = round_point( pt, tolerance ) puts "Original; #{pt}" puts "Tolerance; #{tolerance}" puts "Grid Point; #{grid_pt}" end def adjust_vertices( tolerance = @@last_tolerance ) model = Sketchup.active_model vertices = [] # Collect vertices. for e in model.active_entities vertices << e.vertices if e.is_a?( Sketchup;;Edge ) end vertices.flatten! vertices.uniq! # Calculate grid adjustments. vectors = [] entities = [] for vertex in vertices pt = vertex.position grid_pt = round_point( pt, tolerance ) vector = pt.vector_to( grid_pt ) next unless vector.valid? entities << vertex vectors << vector end # Apply transformations model.active_entities.transform_by_vectors( entities, vectors ) puts "#{entities.size} adjusted to grid." end def menu_command() title = 'Adjust Vertices' prompt = 'Tolerance' default = @@last_tolerance result = UI.inputbox([prompt],[@@last_tolerance],title) rescue @@last_tolerance if result begin ### Sketchup.active_model.start_operation("#{title} (#{Sketchup.format_length(result[0])})") # adjust_vertices( result[0] ) # ### Sketchup.active_model.commit_operation() rescue Sketchup.active_model.abort_operation() else @@last_tolerance = result[0] end end end end # PROXY CLASS #{# RUN ONCE # unless file_loaded?("GridSnap.rb") # Menu Entry; UI.menu("Tools").add_item("GridSnap") { menu_command() } file_loaded("GridSnap.rb") end #} end # module
-
@dan rathbun said:
It seemed to only change a cubes vertices in the Z axis ??
Should apply to X,Y and Z... Seemed to work correctly in my quick test...
-
@dan rathbun said:
@thomthom said:
Cubificator?
Polyhedronizer ?
Orthogonizer ?
Orthographizer ?
OrthograFixer ?
It's like Autotune for cad! They can make you sound good, even if you can't sing.
If you are editing digital music, and you need to make the drum beats perfect, you can move the beats to the nearest sixteenth note, or whatever. It's call "quantizing". -
@daiku said:
It's called "quantizing".
TRUE !!
Restriction to discrete values (or multiples thereof,) rather than any values in the set of possibles (real numbers, in this case.)
So.. the long term:
Vertex Positional QuantizationThe short form:
Vertex to Grid -
Hi guys, I have had a play with Dan's Beta version and for me it works really well. The verticies are adjusted in X,Y and Z directions and the undo function works fine!
The only slight problem: it adjusts all the geometry in the model, rather than just the active selection. The original module just adjusted the active selection.
Any ideas?
Again thanks for the support - this script should be a realy time saver!
Ross
-
Well .. I did not think I changed the context of what Thomas' code did... just tried to wrap the code properly and added the menu_command() method to handle an inputbox.
I'll have a look at it.. again.
(And it's not really MY edition just because I added the inputbox.. it's still Thomas' thing.)
Advertisement