Class: MSPhysics::JointConnectionTool
- Defined in:
- RubyExtension/MSPhysics/joint_connection_tool.rb
Overview
Class Method Summary collapse
-
.activate ⇒ Boolean
Activate joint connection tool.
-
.active? ⇒ Boolean
Determine whether joint connection tool is active.
-
.connect_joint_id(body, id) ⇒ Set<Integer>
Connect joint ID to a group/component.
-
.deactivate ⇒ Boolean
Deactivate joint connection tool.
-
.disconnect_joint_id(body, id) ⇒ Set<Integer>
Disconnect joint ID from a group/component.
-
.get_all_connections(consider_world) ⇒ Array<Array>
Get all joint connections.
-
.get_conections_from_data(fbdata, fjdata) ⇒ Object
Get all joint connections from connection data.
-
.get_connected_bodies(joint, joint_parent) ⇒ Array
Get all bodies connected to a joint.
-
.get_connected_joint_ids(body) ⇒ Set<Integer>
Get all joint IDs connected to a group/component.
-
.get_connected_joints(body) ⇒ Array<Array>
Get all joints connected to a body.
-
.get_connection_data(consider_world) ⇒ Array<(Hash, Hash)>
Get all connection data.
-
.get_curve_length(joint, joint_parent, loop = false) ⇒ Numeric
Get curve length of a CurvySlider or a CurvyPiston joint.
-
.get_joints_by_id(joint_id) ⇒ Array
Get joint by its id.
-
.get_points_on_curve(joint, joint_parent) ⇒ Array<Geom::Point3d>
Get all points on a CurvySlider or a CurvyPiston joint.
-
.set_connected_joint_ids(body, ids) ⇒ Object
Set connected joint IDs of a group/component.
-
.toggle_connect_joint_id(body, id) ⇒ Set<Integer>
Toggle connect joint ID to a group/component.
Instance Method Summary collapse
-
#initialize ⇒ JointConnectionTool
constructor
class << self.
Methods inherited from Entity
Constructor Details
#initialize ⇒ JointConnectionTool
class << self
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 |
# File 'RubyExtension/MSPhysics/joint_connection_tool.rb', line 450 def initialize # Initialize variables @color = { :picked => Sketchup::Color.new(0, 0, 255), :identical => Sketchup::Color.new(0, 0, 255), :connected => Sketchup::Color.new(0, 225, 0), :potential => Sketchup::Color.new(200, 40, 250), :curve => Sketchup::Color.new(250, 250, 15) } @line_width = { :picked => 2, :identical => 2, :connected => 2, :potential => 2, :curve => 3 } @line_stipple = { :picked => '', :identical => '-', :connected => '', :potential => '_', :curve => '' } @text_opts = { :font => 'Ariel', :size => 11, :bold => false, :align => TextAlignLeft, :color => Sketchup::Color.new(255, 255, 255), :hratio => 0.6, :vratio => 1.5, :padding => 10 } @note = { :bg_color => Sketchup::Color.new(0, 180, 255, 230), :time => nil, :duration => 20, :text => nil, :pos => Geom::Point3d.new(0,0,0), :min => Geom::Point3d.new(0,0,0), :max => Geom::Point3d.new(0,0,0), } @warn = { :time => nil, :duration => 3, :bg_color => Sketchup::Color.new(255, 10, 10, 200), :text => nil, :pos => Geom::Point3d.new(0,0,0), :min => Geom::Point3d.new(0,0,0), :max => Geom::Point3d.new(0,0,0), } @cursor_pos = Geom::Point3d.new(0,0,0) @pins = [0,1,1,3,3,2,2,0, 4,5,5,7,7,6,6,4, 0,4,1,5,2,6,3,7] @scale = 1.03 @control_down = false @shift_down = false @cursor_id = MSPhysics::CURSORS[:select] @parent = nil @picked = nil @picked_type = nil @identical = [] @connected = [] @potential = [] @fbdata = {} @fjdata = {} @all_connections = nil end |
Class Method Details
.activate ⇒ Boolean
Activate joint connection tool.
11 12 13 14 15 |
# File 'RubyExtension/MSPhysics/joint_connection_tool.rb', line 11 def activate return false if @@instance Sketchup.active_model.select_tool(self.new) true end |
.active? ⇒ Boolean
Determine whether joint connection tool is active.
27 28 29 |
# File 'RubyExtension/MSPhysics/joint_connection_tool.rb', line 27 def active? @@instance ? true : false end |
.connect_joint_id(body, id) ⇒ Set<Integer>
Connect joint ID to a group/component.
309 310 311 312 313 314 315 316 317 318 |
# File 'RubyExtension/MSPhysics/joint_connection_tool.rb', line 309 def connect_joint_id(body, id) ids = get_connected_joint_ids(body) if Sketchup.version.to_i < 14 ids.insert(id) else ids.add(id) end body.set_attribute('MSPhysics Body', 'Connected Joints', ids.to_a) ids end |
.deactivate ⇒ Boolean
Deactivate joint connection tool.
19 20 21 22 23 |
# File 'RubyExtension/MSPhysics/joint_connection_tool.rb', line 19 def deactivate return false unless @@instance Sketchup.active_model.select_tool(nil) true end |
.disconnect_joint_id(body, id) ⇒ Set<Integer>
Manually wrap the operation.
Disconnect joint ID from a group/component.
325 326 327 328 329 330 |
# File 'RubyExtension/MSPhysics/joint_connection_tool.rb', line 325 def disconnect_joint_id(body, id) ids = get_connected_joint_ids(body) ids.delete(id) body.set_attribute('MSPhysics Body', 'Connected Joints', ids.to_a) ids end |
.get_all_connections(consider_world) ⇒ Array<Array>
Get all joint connections.
223 224 225 226 |
# File 'RubyExtension/MSPhysics/joint_connection_tool.rb', line 223 def get_all_connections(consider_world) data = get_connection_data(consider_world) get_conections_from_data(data[0], data[1]) end |
.get_conections_from_data(fbdata, fjdata) ⇒ Object
Get all joint connections from connection data.
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 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'RubyExtension/MSPhysics/joint_connection_tool.rb', line 118 def get_conections_from_data(fbdata, fjdata) # Map all bodies with their connected joint IDs jid_to_connected_bodies = {} # { joint_id => { child_body => [ptra, ptra_inv, loc_bb_min, loc_bb_max, loc_bb_center, flag], ... }, ... } fbdata.each { |body, bdata| bdata[0].each { |jid| next unless fjdata[jid] data = jid_to_connected_bodies[jid] unless data data = {} jid_to_connected_bodies[jid] = data end data[body] = [bdata[2], bdata[3], bdata[4].to_a, bdata[5].to_a, bdata[6], false] } } # Make connections connections = [] jid_to_connected_bodies.each { |jid, connected_bodies| fjdata[jid].each { |jdata| closest_body = nil closest_dist = nil closest_binside = false jorigin = jdata[1].origin connected_bodies.each { |body, bdata| next if body == jdata[2] # compute joint origin in local body's coordinates ljpt = jorigin.transform(bdata[1]) # compute ljpt closest distance to body bounding box min = bdata[2] max = bdata[3] rfpt = Geom::Point3d.new(ljpt) binside = true for i in 0..2 if (ljpt[i] < min[i]) rfpt[i] = min[i] binside = false elsif (ljpt[i] > max[i]) rfpt[i] = max[i] binside = false end end if binside dist = bdata[4].distance(ljpt).to_f else dist = rfpt.distance(ljpt).to_f end if closest_body.nil? || (binside && !closest_binside) || (binside == closest_binside && dist < closest_dist) closest_body = body closest_dist = dist closest_binside = binside end } next unless closest_body connections << [jdata[0], jdata[1], closest_body, jdata[2], jid] connected_bodies[closest_body][5] = true pbdata = connected_bodies[jdata[2]] pbdata[5] = true if pbdata } connected_bodies.each { |body, bdata| next if bdata[5] closest_jdata = nil closest_dist = nil closest_binside = false min = bdata[2] max = bdata[3] fjdata[jid].each { |jdata| next if body == jdata[2] # compute joint origin in local body's coordinates ljpt = jdata[1].origin.transform(bdata[1]) # compute ljpt closest distance to body bounding box rfpt = Geom::Point3d.new(ljpt) binside = true for i in 0..2 if (ljpt[i] < min[i]) rfpt[i] = min[i] binside = false elsif (ljpt[i] > max[i]) rfpt[i] = max[i] binside = false end end if binside dist = bdata[4].distance(ljpt).to_f else dist = rfpt.distance(ljpt).to_f end if closest_jdata.nil? || (binside && !closest_binside) || (binside == closest_binside && dist < closest_dist) closest_jdata = jdata closest_dist = dist closest_binside = binside end } next unless closest_jdata connections << [closest_jdata[0], closest_jdata[1], body, closest_jdata[2], jid] } } # Return all connections connections end |
.get_connected_bodies(joint, joint_parent) ⇒ Array
Get all bodies connected to a joint.
246 247 248 249 250 251 252 253 254 |
# File 'RubyExtension/MSPhysics/joint_connection_tool.rb', line 246 def get_connected_bodies(joint, joint_parent) data = [] get_all_connections(false).each { |jdata| if jdata[0] == joint && jdata[3] == joint_parent data << jdata[2] end } data end |
.get_connected_joint_ids(body) ⇒ Set<Integer>
Get all joint IDs connected to a group/component.
286 287 288 289 290 291 292 293 294 295 296 |
# File 'RubyExtension/MSPhysics/joint_connection_tool.rb', line 286 def get_connected_joint_ids(body) ids = body.get_attribute('MSPhysics Body', 'Connected Joints') ids = [] unless ids.is_a?(Array) ids_set = ::Set.new if Sketchup.version.to_i < 14 ids.each { |id| ids_set.insert(id) if id.is_a?(Integer) } else ids.each { |id| ids_set.add(id) if id.is_a?(Integer) } end ids_set end |
.get_connected_joints(body) ⇒ Array<Array>
Get all joints connected to a body.
232 233 234 235 236 237 238 239 240 |
# File 'RubyExtension/MSPhysics/joint_connection_tool.rb', line 232 def get_connected_joints(body) data = [] get_all_connections(false).each { |jdata| if jdata[2] == body data << [jdata[0], jdata[1], jdata[3]] end } data end |
.get_connection_data(consider_world) ⇒ Array<(Hash, Hash)>
Get all connection data.
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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'RubyExtension/MSPhysics/joint_connection_tool.rb', line 40 def get_connection_data(consider_world) if consider_world sim_inst = MSPhysics::Simulation.instance unless sim_inst raise(StandardError, "Simulation must be active in order to obtain body connection data!", caller) end end # Gather all bodies, joints, and their data. fbdata = {} # { body => [loc_bb, ptra, ptra_inv, connected_ids_set], ... } fjdata = {} # { joint_id => [[joint_ent, joint_tra, parent_body], ...], ... } bb_map = {} Sketchup.active_model.entities.each { |ent| next if !ent.is_a?(Sketchup::Group) && !ent.is_a?(Sketchup::ComponentInstance) ent_type = ent.get_attribute('MSPhysics', 'Type', 'Body') if ent_type == 'Body' next if ent.get_attribute('MSPhysics Body', 'Ignore', false) if consider_world body = sim_inst.find_body_by_group(ent) next unless body else body = ent end d = AMS::Group.get_definition(ent) bb = bb_map[d] unless bb bb = AMS::Group.get_bounding_box_from_faces(ent, true, nil, &MSPhysics::Collision::ENTITY_VALIDATION_PROC) bb_map[d] = bb end ptra = ent.transformation fbdata[body] = [get_connected_joint_ids(ent), d, ptra, ptra.inverse, bb.min, bb.max, bb.center] cents = ent.is_a?(Sketchup::ComponentInstance) ? ent.definition.entities : ent.entities cents.each { |cent| next if !cent.is_a?(Sketchup::Group) && !cent.is_a?(Sketchup::ComponentInstance) next if cent.get_attribute('MSPhysics', 'Type', 'Body') != 'Joint' jtype = cent.get_attribute('MSPhysics Joint', 'Type') next if !jtype.is_a?(String) || !MSPhysics::JOINT_NAMES.include?(jtype) jid = cent.get_attribute('MSPhysics Joint', 'ID', nil) next unless jid.is_a?(Integer) jtra = ptra * cent.transformation next unless AMS::Geometry.is_matrix_uniform?(jtra) xaxis = jtra.xaxis xaxis.reverse! if AMS::Geometry.is_matrix_flipped?(jtra) jtra = Geom::Transformation.new(xaxis, jtra.yaxis, jtra.zaxis, jtra.origin) jdata = [cent, jtra, body] jdatas = fjdata[jid] if jdatas jdatas << jdata else fjdata[jid] = [jdata] end } elsif ent_type == 'Joint' jtype = ent.get_attribute('MSPhysics Joint', 'Type') next if !jtype.is_a?(String) || !MSPhysics::JOINT_NAMES.include?(jtype) jid = ent.get_attribute('MSPhysics Joint', 'ID', nil) next unless jid.is_a?(Integer) jtra = ent.transformation next unless AMS::Geometry.is_matrix_uniform?(jtra) xaxis = jtra.xaxis xaxis.reverse! if AMS::Geometry.is_matrix_flipped?(jtra) jtra = Geom::Transformation.new(xaxis, jtra.yaxis, jtra.zaxis, jtra.origin) jdata = [ent, jtra, nil] jdatas = fjdata[jid] if jdatas jdatas << jdata else fjdata[jid] = [jdata] end end } return [fbdata, fjdata] end |
.get_curve_length(joint, joint_parent, loop = false) ⇒ Numeric
Get curve length of a CurvySlider or a CurvyPiston joint.
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 |
# File 'RubyExtension/MSPhysics/joint_connection_tool.rb', line 432 def get_curve_length(joint, joint_parent, loop = false) length = 0.0 last_pt = nil pts = get_points_on_curve(joint, joint_parent) pts.each { |pt| if last_pt length += last_pt.distance(pt) end last_pt = pt } if loop && last_pt length += pts[0].distance(last_pt) end length end |
.get_joints_by_id(joint_id) ⇒ Array
Get joint by its id.
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'RubyExtension/MSPhysics/joint_connection_tool.rb', line 261 def get_joints_by_id(joint_id) data = [] Sketchup.active_model.entities.each { |ent| next if !ent.is_a?(Sketchup::Group) && !ent.is_a?(Sketchup::ComponentInstance) type = ent.get_attribute('MSPhysics', 'Type', 'Body') if type == 'Body' next if ent.get_attribute('MSPhysics Body', 'Ignore', false) cents = ent.is_a?(Sketchup::ComponentInstance) ? ent.definition.entities : ent.entities cents.each { |cent| next if !cent.is_a?(Sketchup::Group) && !cent.is_a?(Sketchup::ComponentInstance) next if cent.get_attribute('MSPhysics', 'Type', 'Body') != 'Joint' id = cent.get_attribute('MSPhysics Joint', 'ID') data << [cent, ent] if id == joint_id } elsif type == 'Joint' id = ent.get_attribute('MSPhysics Joint', 'ID') data << [ent, nil] if id == joint_id end } data end |
.get_points_on_curve(joint, joint_parent) ⇒ Array<Geom::Point3d>
Get all points on a CurvySlider or a CurvyPiston joint.
356 357 358 359 360 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 391 392 393 394 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 424 425 |
# File 'RubyExtension/MSPhysics/joint_connection_tool.rb', line 356 def get_points_on_curve(joint, joint_parent) # Find the closest edge closest_dist = nil closest_edge = nil AMS::Group.get_entities(joint).each { |e| next unless e.is_a?(Sketchup::Edge) dist1 = e.start.position.distance(ORIGIN) dist2 = e.end.position.distance(ORIGIN) dist = dist1 < dist2 ? dist1 : dist2 if closest_dist.nil? || dist < closest_dist closest_dist = dist closest_edge = e break if closest_dist < 1.0e-8 end } # Verify return Array.new() unless closest_edge # Preset data edges = { closest_edge => 0 } edges[closest_edge] = 0 vertices = {} # Get all preceding edge vertices edge = closest_edge v = edge.start vertices[0] = v count = -1 while true next_edge = v.edges[0] if next_edge == edge if v.edges[1] next_edge = v.edges[1] else break end end break if edges.has_key?(next_edge) v = next_edge.other_vertex(v) vertices[count] = v edges[next_edge] = count edge = next_edge count -= 1 end # Get all consequent edge vertices edge = closest_edge v = edge.end vertices[1] = v count = 2 while true next_edge = v.edges[0] if next_edge == edge if v.edges[1] next_edge = v.edges[1] else break end end break if edges.has_key?(next_edge) v = next_edge.other_vertex(v) vertices[count] = v edges[next_edge] = count edge = next_edge count += 1 end # Return sorted vertices tra = joint.transformation if joint_parent tra = joint_parent.transformation * tra end vertices.keys.sort.map { |i| vertices[i].position.transform(tra) } end |
.set_connected_joint_ids(body, ids) ⇒ Object
Set connected joint IDs of a group/component.
301 302 303 |
# File 'RubyExtension/MSPhysics/joint_connection_tool.rb', line 301 def set_connected_joint_ids(body, ids) body.set_attribute('MSPhysics Body', 'Connected Joints', ids.to_a) end |
.toggle_connect_joint_id(body, id) ⇒ Set<Integer>
Manually wrap the operation.
Toggle connect joint ID to a group/component.
337 338 339 340 341 342 343 344 345 346 347 348 349 350 |
# File 'RubyExtension/MSPhysics/joint_connection_tool.rb', line 337 def toggle_connect_joint_id(body, id) ids = get_connected_joint_ids(body) if ids.include?(id) ids.delete(id) else if Sketchup.version.to_i < 14 ids.insert(id) else ids.add(id) end end body.set_attribute('MSPhysics Body', 'Connected Joints', ids.to_a) ids end |