Class: MeshAnalyzer

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby3mf/mesh_analyzer.rb

Class Method Summary collapse

Class Method Details

.validate(model_doc, includes_material) ⇒ Object



74
75
76
77
78
# File 'lib/ruby3mf/mesh_analyzer.rb', line 74

def self.validate(model_doc, includes_material)
  model_doc.css('model/resources/object').select { |object| ['model', 'solidsupport', ''].include?(object.attributes['type'].to_s) }.each do |object|
    validate_object(object, includes_material)
  end
end

.validate_object(object, includes_material) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/ruby3mf/mesh_analyzer.rb', line 3

def self.validate_object(object, includes_material)
  Log3mf.context "verifying object" do |l|
    children = object.children.map { |child| child.name }
    have_override = object.attributes["pid"] or object.attributes["pindex"]
    l.error :object_with_components_and_pid if have_override && children.include?("components")
  end

  Log3mf.context "validating geometry" do |l|
    list = EdgeList.new

    # if a triangle has a pid, then the object needs a pid
    has_triangle_pid = false

    meshs = object.css('mesh')
    meshs.each do |mesh|

      num_vertices = mesh.css("vertex").count
      triangles = mesh.css("triangle")
      l.error :not_enough_triangles if triangles.count < 4

      if triangles
        triangles.each do |triangle|

          v1 = triangle.attributes["v1"].to_s.to_i
          v2 = triangle.attributes["v2"].to_s.to_i
          v3 = triangle.attributes["v3"].to_s.to_i

          l.error :invalid_vertex_index if [v1, v2, v3].select{|vertex| vertex >= num_vertices}.count > 0

          unless includes_material
            l.context "validating property overrides" do |l|
              property_overrides = []
              property_overrides << triangle.attributes['p1'].to_s.to_i if triangle.attributes['p1']
              property_overrides << triangle.attributes['p2'].to_s.to_i if triangle.attributes['p2']
              property_overrides << triangle.attributes['p3'].to_s.to_i if triangle.attributes['p3']

              property_overrides.reject! { |prop| prop.nil? }
              l.error :has_base_materials_gradient unless property_overrides.uniq.size <= 1
            end
          end

          if v1 == v2 || v2 == v3 || v3 == v1
            l.error :non_distinct_indices
          end

          list.add_edge(v1, v2)
          list.add_edge(v2, v3)
          list.add_edge(v3, v1)
          unless has_triangle_pid
            has_triangle_pid = triangle.attributes["pid"] != nil
          end
        end

        if has_triangle_pid && !(object.attributes["pindex"] && object.attributes["pid"])
          l.error :missing_object_pid
        end

        result = list.verify_edges
        if result == :bad_orientation
          l.error :resource_3dmodel_orientation
        elsif result == :hole
          l.error :resource_3dmodel_hole
        elsif result == :nonmanifold
          l.error :resource_3dmodel_nonmanifold
        end

      end
    end
  end
end