Class: GD::GIS::Ontology

Inherits:
Object
  • Object
show all
Defined in:
lib/gd/gis/ontology.rb

Overview

Classifies features into semantic layers using rule-based matching.

An Ontology maps feature properties to logical layer identifiers (e.g. :water, :road, :park) based on a YAML rule definition.

The ontology is intentionally simple and heuristic-based:

  • Rules are evaluated in order

  • The first matching rule wins

  • Matching is case-insensitive and substring-based

This design favors robustness and flexibility over strict schema enforcement.

Instance Method Summary collapse

Constructor Details

#initialize(path = nil) ⇒ Ontology

Creates a new ontology.

Parameters:

  • path (String, nil) (defaults to: nil)

    path to a YAML ontology file; defaults to ‘ontology.yml` shipped with the gem

Raises:

  • (Errno::ENOENT)

    if the file does not exist

  • (Psych::SyntaxError)

    if the YAML is invalid



29
30
31
32
# File 'lib/gd/gis/ontology.rb', line 29

def initialize(path = nil)
  path ||= File.expand_path("ontology.yml", __dir__)
  @rules = YAML.load_file(path)
end

Instance Method Details

#classify(properties, geometry_type: nil) ⇒ Symbol?

Classifies a feature into a semantic layer.

Properties are matched against ontology rules using case-insensitive substring comparison.

Examples:

ontology.classify({ "waterway" => "river" })
#=> :water
ontology.classify({}, geometry_type: "Point")
#=> :points

Parameters:

  • properties (Hash)

    feature attributes / tags

  • geometry_type (String, nil) (defaults to: nil)

    GeoJSON geometry type

Returns:

  • (Symbol, nil)

    semantic layer identifier, or nil if no rule matches



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/gd/gis/ontology.rb', line 68

def classify(properties, geometry_type: nil)
  @rules.each do |layer, sources|
    sources.each_value do |rules|
      rules.each do |key, values|
        v = (properties[key.to_s] || properties[key.to_sym]).to_s.strip.downcase
        values = values.map { |x| x.to_s.downcase }

        return layer.to_sym if values.any? { |x| v.include?(x) }
      end
    end
  end

  # Fallback classification
  case geometry_type
  when "Point"
    :points
  when "LineString", "MultiLineString"
    :minor
  when "Polygon", "MultiPolygon"
    :area
  else
    nil
  end
end


34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/gd/gis/ontology.rb', line 34

def print_rules
  @rules.each do |layer, sources|
    puts "\n=== #{layer.to_s.upcase} ==="

    sources.each do |source, rules|
      puts "  [#{source}]"

      rules.each do |key, values|
        puts "    #{key}#{values.join(', ')}"
      end
    end
  end
end