class Model3mf
Constants
- KNOWN_EXTENSIONS
- MATERIAL_EXTENSION
- PRODUCTION_EXTENSION
- SLICE_EXTENSION
- VALID_CORE_METADATA_NAMES
Public Class Methods
find_model_object(model_doc, id, type)
click to toggle source
# File lib/ruby3mf/model3mf.rb, line 124 def self.find_model_object(model_doc, id, type) model_doc.css('model/resources/object').select do |item| item.attributes['id'].to_s == id && item.attributes['type'] && item.attributes['type'].value == type end end
parse(document, zip_entry)
click to toggle source
# File lib/ruby3mf/model3mf.rb, line 15 def self.parse(document, zip_entry) model_doc = nil Log3mf.context "parsing model" do |l| begin model_doc = XmlVal.validate_parse(zip_entry, SchemaFiles::SchemaTemplate) rescue Nokogiri::XML::SyntaxError => e l.fatal_error :model_invalid_xml, e: e end l.context "verifying supported extensions" do |l| model_doc.css("//model").first.namespaces.each do |prefix, uri| unless prefix == "xmlns" ext = KNOWN_EXTENSIONS[uri] if ext.nil? || !ext[:supported] l.warning :unsupported_extension, ext: (ext.nil? ? uri : ext[:name]) end end end end l.context "verifying requiredextensions" do |l| model_doc.css("//model").map { |node| node.attributes["requiredextensions"] }.compact.each do |required_extension| required_extension.value.split(" ").each do |ns| namespace_uri = model_doc.namespaces["xmlns:#{ns}"] l.error :missing_extension_namespace_uri, ns: ns unless namespace_uri end end end l.context "verifying 3D payload required resources" do |l| # results = model_doc.css("model resources m:texture2d") required_resources = model_doc.css("//model//resources//*[path]").collect { |n| n["path"] } required_resources += model_doc.css("//model//resources//object[thumbnail]").collect { |n| n["thumbnail"] } # for each, ensure that they exist in m.relationships relationship_resources = [] rel_file = "#{Pathname(zip_entry.name).dirname.to_s}/_rels/#{File.basename(zip_entry.name)}.rels" relationships = document.relationships[rel_file] unless (relationships.nil?) relationship_resources = relationships.map { |relationship| relationship[:target] } end missing_resources = (required_resources - relationship_resources) if missing_resources.empty? l.info "All model required resources are defined in .rels relationship files." else missing_resources.each { |mr| l.error :model_resource_not_in_rels, mr: mr } end end l.context 'verifying resources' do |l| resources = model_doc.root.css("resources") if resources ids = resources.children.map { |child| child.attributes['id'].to_s if child.attributes['id'] } l.error :resource_id_collision if ids.uniq.size != ids.size pids = resources.children.map { |child| child.attributes['pid'].to_s } missing_pids = pids.select { |pid| !pid.empty? and !ids.include? pid } missing_pids.each do |p| l.error :resource_pid_missing, pid: p end end end l.context "verifying build items" do |l| build_items = model_doc.css('build/item') object_ids = build_items.map { |x| x.attributes["objectid"].value } other_build_items = object_ids.map { |id| find_model_object(model_doc, id, 'other') }.flatten l.error :build_with_other_item if other_build_items.any? end l.context "checking metadata" do |l| metadata_names = model_doc.root.css("metadata").map { |met| met['name'] } l.error :metadata_elements_with_same_name unless metadata_names.uniq!.nil? unless (metadata_names - VALID_CORE_METADATA_NAMES).empty? extra_names = metadata_names - VALID_CORE_METADATA_NAMES ns_names = extra_names.select { |n| n.include? ':' } l.error :invalid_metadata_under_defaultns unless (extra_names - ns_names).empty? unless ns_names.empty? prefixes = model_doc.root.namespace_definitions.map { |defs| defs.prefix }.reject { |pre| pre.nil? } l.error :invalid_metadata_name unless (ns_names.collect { |i| i.split(':').first } - prefixes).empty? end end end includes_material = model_doc.namespaces.values.include?(MATERIAL_EXTENSION) MeshAnalyzer.validate(model_doc, includes_material) l.context "verifying triangle normal" do |l| model_doc.css('model/resources/object').select { |object| ['model', 'solidsupport', ''].include?(object.attributes['type'].to_s) }.each do |object| meshes = object.css('mesh') meshes.each do |mesh| processor = MeshNormalAnalyzer.new(mesh) l.error :inward_facing_normal if processor.found_inward_triangle end end end end model_doc end