0

I found a script that calculates 3D models and combines identical vertices. It has the following logic, where according to my understanding, vertices are hash maps of vertex class:

unless vertices.key?(vertex)
  new_vertices << vertex
  vertices[ vertex ] = @vertex_index
  @vertex_index += 1
end

If we find a vertex that is unique, we add it to the new_vertices array.

I'd like to modify this so that the key for the hash map is a combination of a vertex and a material (both are classes from Sketchup, which is the software this script runs in). What is the best way to do this so that each key is a combination of two classes instead of one? Some sort of duple or class holding both the vertex and the material? Is that supported by a hash map?

Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
user923
  • 559
  • 4
  • 12
  • 2
    Use an array `[vertex, material]` as a key. – Aleksei Matiushkin Aug 28 '18 at 09:52
  • *"Is that supported by a hash map?"* -- Yes. In ruby, you can use **any object** (including, for example, an `Array`) as a hash key. Unlike some other languages, with may only allow `String`s and `Integer`s as hash keys. – Tom Lord Aug 28 '18 at 10:28
  • Thanks guys. Never used a languages with this sort of flexibility before. In terms of code, would it literally just support using what @mudasobwa wrote in place of the vertex for the key? If so, that's awesome and if you answer it, I'll give you credit for the correct answer. – user923 Aug 28 '18 at 10:30

1 Answers1

1

In Ruby one might use whatever as hash key:

hash = {
  42 => "an integer",
  [42, "forty two"] => "an array",
  Class => "a class"
}
#⇒  {42=>"an integer", [42, "forty two"]=>"an array", Class=>"a class"}

hash[[42, "forty two"]]
#⇒ "an array"

That said, in your case you might use an array [vertex, material] as a key:

unless vertices.key?([vertex, material])
  new_vertices_and_materials << [vertex, material]
  vertices[[vertex, material]] = @vertex_index
  @vertex_index += 1
end

The more rubyish approach would be to call Enumerable#uniq on the input and do:

input = [ # example input data
  [:vertex1, :material1],
  [:vertex2, :material1],
  [:vertex2, :material1],
  [:vertex2, :material2],
  [:vertex2, :material2]
]
new_vertices_and_materials = input.uniq
vertices_and_materials_with_index =
  new_vertices_and_materials.
    zip(1..new_vertices_and_materials.size).
    to_h
#⇒ {[:vertex1, :material1]=>1,
#   [:vertex2, :material1]=>2,
#   [:vertex2, :material2]=>3}
Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160