Class: Topolys::Model
- Inherits:
-
Object
- Object
- Topolys::Model
- Defined in:
- lib/topolys/model.rb
Overview
The Topolys Model contains many Topolys Objects, a Topolys Object can only be connected to other Topolys Objects in the same Topolys Model. To enforce this Topolys Objects should not be constructed directly, they should be retrieved using the Topolys Model get_* object methods.
Instance Attribute Summary collapse
-
#cells ⇒ Object
readonly
Returns the value of attribute cells.
-
#directed_edges ⇒ Object
readonly
Returns the value of attribute directed_edges.
-
#edges ⇒ Object
readonly
Returns the value of attribute edges.
-
#faces ⇒ Object
readonly
Returns the value of attribute faces.
-
#shells ⇒ Object
readonly
Returns the value of attribute shells.
-
#tol ⇒ Object
readonly
Returns the value of attribute tol.
-
#tol2 ⇒ Object
readonly
Returns the value of attribute tol2.
-
#vertices ⇒ Object
readonly
Returns the value of attribute vertices.
-
#wires ⇒ Object
readonly
Returns the value of attribute wires.
Class Method Summary collapse
Instance Method Summary collapse
- #all_objects ⇒ Object
-
#find_existing_directed_edge(v0, v1) ⇒ DirectedEdge
DirectedEdge.
-
#find_existing_edge(v0, v1) ⇒ Edge
Edge or nil.
-
#find_existing_vertex(point) ⇒ Vertex
Vertex or nil.
-
#get_directed_edge(v0, v1) ⇒ DirectedEdge
DirectedEdge.
-
#get_edge(v0, v1) ⇒ Edge
Edge.
-
#get_face(outer, holes) ⇒ Face
Face Returns Face or nil if wires are not in model.
-
#get_reverse(object) ⇒ Object
Returns reversed object.
-
#get_shell(faces) ⇒ Shell
Returns Shell or nil if faces are not in model or not connected.
-
#get_vertex(point) ⇒ Vertex
Vertex.
-
#get_vertices(points) ⇒ Array
Array of Vertex.
-
#get_wire(vertices) ⇒ Wire
Wire.
-
#initialize(tol = nil) ⇒ Model
constructor
A new instance of Model.
- #save(file) ⇒ Object
- #save_graphviz(file) ⇒ Object
- #to_graphviz ⇒ Object
- #to_json ⇒ Object
- #to_s ⇒ Object
-
#vertex_intersect_edge(vertex, edge) ⇒ Point3D
Point3D of vertex projected on edge or nil.
Constructor Details
#initialize(tol = nil) ⇒ Model
Returns a new instance of Model.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/topolys/model.rb', line 70 def initialize(tol=nil) # changing tolerance on a model after construction would be very complicated # you would have to go through and regroup points, etc if !tol.is_a?(Numeric) tol = 0.01 end @tol = tol @tol2 = @tol**2 @vertices = [] @edges = [] @directed_edges = [] @wires = [] @faces = [] @shells = [] @cells = [] end |
Instance Attribute Details
#cells ⇒ Object (readonly)
Returns the value of attribute cells.
67 68 69 |
# File 'lib/topolys/model.rb', line 67 def cells @cells end |
#directed_edges ⇒ Object (readonly)
Returns the value of attribute directed_edges.
67 68 69 |
# File 'lib/topolys/model.rb', line 67 def directed_edges @directed_edges end |
#edges ⇒ Object (readonly)
Returns the value of attribute edges.
67 68 69 |
# File 'lib/topolys/model.rb', line 67 def edges @edges end |
#faces ⇒ Object (readonly)
Returns the value of attribute faces.
67 68 69 |
# File 'lib/topolys/model.rb', line 67 def faces @faces end |
#shells ⇒ Object (readonly)
Returns the value of attribute shells.
67 68 69 |
# File 'lib/topolys/model.rb', line 67 def shells @shells end |
#tol ⇒ Object (readonly)
Returns the value of attribute tol.
68 69 70 |
# File 'lib/topolys/model.rb', line 68 def tol @tol end |
#tol2 ⇒ Object (readonly)
Returns the value of attribute tol2.
68 69 70 |
# File 'lib/topolys/model.rb', line 68 def tol2 @tol2 end |
#vertices ⇒ Object (readonly)
Returns the value of attribute vertices.
67 68 69 |
# File 'lib/topolys/model.rb', line 67 def vertices @vertices end |
#wires ⇒ Object (readonly)
Returns the value of attribute wires.
67 68 69 |
# File 'lib/topolys/model.rb', line 67 def wires @wires end |
Class Method Details
.from_json(obj) ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/topolys/model.rb', line 106 def self.from_json(obj) model = Model.new id_map = {} obj[:vertices].each do |v| p = v[:point] point = Point3D.new(p[:x], p[:y], p[:z]) vertex = model.get_vertex(point) set_id(vertex, v[:id]) vertex.attributes = v[:attributes] if v[:attributes] id_map[v[:id]] = vertex end obj[:edges].each do |e| v0 = id_map[e[:v0]] v1 = id_map[e[:v1]] edge = model.get_edge(v0, v1) set_id(edge, e[:id]) edge.attributes = e[:attributes] if e[:attributes] id_map[e[:id]] = edge end obj[:directed_edges].each do |de| edge = id_map[de[:edge]] inverted = de[:inverted] directed_edge = nil if inverted directed_edge = model.get_directed_edge(edge.v1, edge.v0) else directed_edge = model.get_directed_edge(edge.v0, edge.v1) end set_id(directed_edge, de[:id]) directed_edge.attributes = de[:attributes] if de[:attributes] id_map[de[:id]] = directed_edge end obj[:wires].each do |w| vertices = [] w[:directed_edges].each do |id| directed_edge = id_map[id] vertices << directed_edge.v0 end wire = model.get_wire(vertices) set_id(wire, w[:id]) wire.attributes = w[:attributes] if w[:attributes] id_map[w[:id]] = wire end obj[:faces].each do |f| outer = id_map[f[:outer]] holes = [] f[:holes].each do |id| holes << id_map[id] end face = model.get_face(outer, holes) set_id(face, f[:id]) face.attributes = f[:attributes] if f[:attributes] id_map[f[:id]] = face end obj[:shells].each do |s| faces = [] s[:faces].each do |id| faces << id_map[id] end shell = model.get_shell(faces) set_id(shell, s[:id]) shell.attributes = s[:attributes] if s[:attributes] id_map[s[:id]] = shell end return model end |
.schema ⇒ Object
184 185 186 187 |
# File 'lib/topolys/model.rb', line 184 def self.schema s = File.read(schema_file) return JSON.parse(s) end |
.schema_file ⇒ Object
180 181 182 |
# File 'lib/topolys/model.rb', line 180 def self.schema_file return File.join(File.dirname(__FILE__), "./schema/topolys.json") end |
Instance Method Details
#all_objects ⇒ Object
89 90 91 |
# File 'lib/topolys/model.rb', line 89 def all_objects @vertices + @edges + @directed_edges + @wires + @faces + @shells + @cells end |
#find_existing_directed_edge(v0, v1) ⇒ DirectedEdge
Returns DirectedEdge.
349 350 351 352 353 354 355 356 357 |
# File 'lib/topolys/model.rb', line 349 def find_existing_directed_edge(v0, v1) # search for directed edge and return if it exists @directed_edges.each do |de| if (de.v0.id == v0.id) && (de.v1.id == v1.id) return de end end return nil end |
#find_existing_edge(v0, v1) ⇒ Edge
Returns Edge or nil.
314 315 316 317 318 319 320 321 322 323 |
# File 'lib/topolys/model.rb', line 314 def find_existing_edge(v0, v1) @edges.each do |e| if (e.v0.id == v0.id) && (e.v1.id == v1.id) return e elsif (e.v0.id == v1.id) && (e.v1.id == v0.id) return e end end return nil end |
#find_existing_vertex(point) ⇒ Vertex
Returns Vertex or nil.
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
# File 'lib/topolys/model.rb', line 266 def find_existing_vertex(point) # search for point and return corresponding vertex if it exists # otherwise create new vertex @vertices.each do |v| p = v.point ## L1 norm #if ((p.x-point.x).abs < @tol) && # (p.y-point.y).abs < @tol) && # (p.z-point.z).abs < @tol)) # return v #end # L2 norm if ((p.x-point.x)**2 + (p.y-point.y)**2 + (p.z-point.z)**2) < @tol2 return v end end return nil end |
#get_directed_edge(v0, v1) ⇒ DirectedEdge
Returns DirectedEdge.
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 |
# File 'lib/topolys/model.rb', line 328 def get_directed_edge(v0, v1) # search for directed edge and return if it exists de = find_existing_directed_edge(v0, v1) return de if de # otherwise create new directed edge edge = get_edge(v0, v1) inverted = false if (edge.v0.id != v0.id) inverted = true end directed_edge = DirectedEdge.new(edge, inverted) @directed_edges << directed_edge return directed_edge end |
#get_edge(v0, v1) ⇒ Edge
Returns Edge.
297 298 299 300 301 302 303 304 305 306 307 308 309 |
# File 'lib/topolys/model.rb', line 297 def get_edge(v0, v1) # search for edge and return if it exists e = find_existing_edge(v0, v1) return e if e # otherwise create new edge @vertices << v0 if !@vertices.find {|v| v.id == v0.id} @vertices << v1 if !@vertices.find {|v| v.id == v1.id} edge = Edge.new(v0, v1) @edges << edge return edge end |
#get_face(outer, holes) ⇒ Face
Returns Face Returns Face or nil if wires are not in model.
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 |
# File 'lib/topolys/model.rb', line 395 def get_face(outer, holes) # search for face and return if exists # otherwise create new face hole_ids = holes.map{|h| h.id}.sort @faces.each do |face| if face.outer.id == outer.id if face.holes.map{|h| h.id}.sort == hole_ids return face end end end # all the wires have to be in the model return nil if @wires.index{|w| w.id == outer.id}.nil? holes.each do |hole| return nil if @wires.index{|w| w.id == outer.id}.nil? end face = nil begin face = Face.new(outer, holes) @faces << face rescue => exception puts exception end return face end |
#get_reverse(object) ⇒ Object
Returns reversed object
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 |
# File 'lib/topolys/model.rb', line 456 def get_reverse(object) if object.is_a?(Vertex) return object elsif object.is_a?(Edge) return object elsif object.is_a?(DirectedEdge) return get_directed_edge(object.v1, object.v0) elsif object.is_a?(Wire) return get_wire(object.vertices.reverse) elsif object.is_a?(Face) reverse_outer = get_wire(object.outer.vertices.reverse) reverse_holes = [] object.holes.each do |hole| reverse_holes << get_wire(hole.vertices.reverse) end return get_face(reverse_outer, reverse_holes) elsif object.is_a?(Shell) # can't reverse a shell return nil end return nil end |
#get_shell(faces) ⇒ Shell
Returns Shell or nil if faces are not in model or not connected
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 |
# File 'lib/topolys/model.rb', line 427 def get_shell(faces) # all the faces have to be in the model faces.each do |face| return nil if @faces.index{|f| f.id == face.id}.nil? end # check if we already have this shell face_ids = faces.map{|f| f.id}.sort @shells.each do |shell| if shell.faces.map{|f| f.id}.sort == face_ids return shell end end # create a new shell shell = nil begin shell = Shell.new(faces) @shells << shell rescue => exception puts exception end return shell end |
#get_vertex(point) ⇒ Vertex
Returns Vertex.
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/topolys/model.rb', line 233 def get_vertex(point) # search for point and return corresponding vertex if it exists v = find_existing_vertex(point) return v if v # otherwise create new vertex v = Vertex.new(point) @vertices << v # check if this vertex needs to be inserted on any edge updated = false @edges.each do |edge| if new_point = vertex_intersect_edge(v, edge) # point might need to be added to multiple edges # point can be updated to project it onto edge, don't update multiple times if !updated # simulate friend access to set point on vertex v.instance_variable_set(:@point, new_point) v.recalculate updated = true end # now split the edge with this vertex split_edge(edge, v) end end return v end |
#get_vertices(points) ⇒ Array
Returns Array of Vertex.
290 291 292 |
# File 'lib/topolys/model.rb', line 290 def get_vertices(points) points.map {|p| get_vertex(p)} end |
#get_wire(vertices) ⇒ Wire
Returns Wire.
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 |
# File 'lib/topolys/model.rb', line 361 def get_wire(vertices) # search for wire and return if exists # otherwise create new wire # insert any existing model vertices that should be inserted on the edges in vertices vertices = insert_vertices_on_edges(vertices) n = vertices.size directed_edges = [] vertices.each_index do |i| directed_edges << get_directed_edge(vertices[i], vertices[(i+1)%n]) end # see if we already have this wire @wires.each do |wire| if wire.circular_equal?(directed_edges) return wire end end wire = nil begin wire = Wire.new(directed_edges) @wires << wire rescue => exception puts exception end return wire end |
#save(file) ⇒ Object
193 194 195 196 197 |
# File 'lib/topolys/model.rb', line 193 def save(file) File.open(file, 'w') do |file| file.puts self.to_s end end |
#save_graphviz(file) ⇒ Object
211 212 213 214 215 |
# File 'lib/topolys/model.rb', line 211 def save_graphviz(file) File.open(file, 'w') do |file| file.puts to_graphviz end end |
#to_graphviz ⇒ Object
199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/topolys/model.rb', line 199 def to_graphviz result = "digraph model {\n" result += " rankdir=LR\n" all_objects.each do |obj| obj.children.each { |child| result += " #{child.short_name} -> #{obj.short_name}\n" } #obj.parents.each { |parent| result += " #{parent.short_name} -> #{obj.short_name}\n" } end result += " }" return result end |
#to_json ⇒ Object
93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/topolys/model.rb', line 93 def to_json result= { vertices: @vertices.map { |v| v.to_json }, edges: @edges.map { |e| e.to_json }, directed_edges: @directed_edges.map { |de| de.to_json }, wires: @wires.map { |w| w.to_json }, faces: @faces.map { |f| f.to_json }, shells: @shells.map { |s| s.to_json }, cells: @cells.map { |c| c.to_json } } return result end |
#to_s ⇒ Object
189 190 191 |
# File 'lib/topolys/model.rb', line 189 def to_s JSON.pretty_generate(to_json) end |
#vertex_intersect_edge(vertex, edge) ⇒ Point3D
Returns Point3D of vertex projected on edge or nil.
220 221 222 223 224 225 226 227 228 229 |
# File 'lib/topolys/model.rb', line 220 def vertex_intersect_edge(vertex, edge) if vertex.id == edge.v0.id || vertex.id == edge.v1.id return nil end # new_point, length - length unused here new_point, _ = project_point_on_edge(edge.v0.point, edge.v1.point, vertex.point) return new_point end |