Notifications
Clear all

[Closed] objects as line knots

Hello,

i was wondering if i could draw a line that would have as knots these boxes i have created in the image but the line would Start and End to the boxes that i would choose. But it needs to make it through the other box by travelling allong the boxes in 3D space and not 2D (like someone could guess from the image). I dont know in which theories is this based in order to code it in Maxscript bt if someone could tell me what do i need to know i could write it myself.

hope i made my point clear! i would appreciate any idea .
thank you
alex

ps: i assume that maybe the line would choose each time the closest box (or the box between a specified range) in order to climb till the other box

9 Replies

--Author: Mike Burgoyne
--www.burgoynedesign.com
(
global StructureFLOAT
local newOBJ
local splineArray = #()
try (cui.unregisterDialogBar StructureFLOAT) catch()  -- If already registered, then unregister.
try (closeRolloutFloater StructureFLOAT) catch() -- If already open, then close.
rollout Structure "Structure Maker"
(
group "Spline Controls"
 (
  spinner rth "Spline Thickness: " type:#float width:100 align:#right enabled:true
  spinner stepsSP "Int Steps: " type:#integer width:100 align:#right enabled:true
 )
button rScript "Run Script" enabled:true
button deleteS "Delete" enabled:false
 

on rScript pressed do (
 if $ == undefined then 
 (
  messagebox "No objects are selected, Please select some objeccts"
 )
 else
 (
deleteS.enabled = true
posArray = #() -- where to collect Point3 val's
-- step 1: collect object position
 count = selection.count
 temp = for i = 1 to count collect
 (
  selection[i].pos
 )
 append posArray temp
for data in posArray do
(
 sp = splineShape render_renderable:true render_displayRenderMesh:true
 sp.render_thickness.controller = rth.controller = bezier_float ()
 sp.steps = stepsSP.value
 addnewSpline sp
 append splineArray sp
 for k in data do
 (
  addKnot sp 1 #smooth #curve k
 )
 updateShape sp
)
completeRedraw()
)
)
 on deleteS pressed do 
 (
  for i = 1 to splineArray.count do delete splineArray[i]--loop through the array and delete each object in it
  splineArray = #() --empty the array
  
 )
)
 StructureFLOAT = newRolloutFloater "Structure Maker" 200 210
 addRollout Structure  StructureFLOAT
)

I created this to draw a spline connecting selected objects. You will have to modify it a bit but it should help you on to the right path I hope.

hi viro,
i have found the answer!
the problem was not how you could connect a group of objects together with lines but to test recursively for the shortest path between two objects that belong to a higher amount of objects . but thank you also for the script

Matter of speaking,
do you know (or someone else who reads this) what are the changes in Maxscript between 2010/2011, and 2012 ? i got a script written in 2010 or 11 and i was always having an Runtime error expression all the time when i run the script in 2012. but the code was completely correct.

1 Reply
(@denist)
Joined: 10 months ago

Posts: 0

see mxs help What is New in MAXScript in 3ds Max…

if you want to get someone’s help show your code and error messages…

i saw the documentation but as im studying maxscript for only 6 – 7 months, i cant really understand which things might have changed…
here is the code that i couldnt run.

–code written by Garp
(
global rltBestVerticalPath
try destroyDialog rltBestVerticalPath catch()

– MOST OF THE WORK IS DONE IN THIS STRUCT
struct path_data (

– PUBLIC:
obj1, obj2, – end objects
tol = 0.5, – min z value between levels

– PRIVATE:
– sanity check
fn is_valid = (
return case of (
(NOT obj1.isSelected): (
messageBox (obj1.name + ” not in selection”)
false
)
(NOT obj2.isSelected): (
messageBox (obj2.name + ” not in selection”)
false
)
(abs(obj1.center.z – obj2.center.z) < tol): (
messageBox (obj1.name + ” and ” + obj2.name + ” on same level”)
false
)
default: true
)
),

– sort object list by z position
obj_arr = selection as array,
fn zcomp obj1 obj2 = ( obj1.center.z – obj2.center.z ),
fn sort_obj_arr = ( qsort obj_arr zcomp ),

– helper
fn get_pos i = ( obj_arr[i].center ),

– split object list into levels
levels_arr = #(),
fn fill_levels_arr = (
local cnt = obj_arr.count
local ind = 1
while ind <= cnt do (
local curr_z = (get_pos ind).z
local curr_level = #{}
while ind <= cnt AND (get_pos ind).z < curr_z + tol do
(
append curr_level ind
ind += 1
)
append levels_arr curr_level
)
),

– index of level in levels_arr from index in obj_arr
fn which_level i = (
for ba = 1 to levels_arr.count do
if findItem levels_arr[ba] i != 0 do
return ba
return 0 – should never get there
),

best_path = #{},
bottom_ind = 0,
top_ind = 0,
bottom_level = 0,
top_level = 0,
min_dist = 1000000,

– initialize data needed to find path
fn init_data = (
sort_obj_arr()
fill_levels_arr()
best_path = #{findItem obj_arr obj1, findItem obj_arr obj2}
bottom_ind = (best_path as array)[1]
top_ind = (best_path as array)[2]
bottom_level = which_level bottom_ind
top_level = which_level top_ind
),

– search recursively for shortest path
fn find_path path dist = (
local last_ind = (path as array)[path.numberSet – 1]
local last_pos = get_pos last_ind
local last_level = which_level last_ind
if path.numberSet != top_level – bottom_level + 1 then (
for i in levels_arr[last_level + 1] do
find_path (path + #{i}) (dist + distance last_pos (get_pos i))
) else (
dist += distance last_pos (get_pos top_ind)
if dist < min_dist do (
min_dist = dist
best_path = path + #{top_ind}
)
)
),

– PUBLIC:
– do it, finally
fn pos_list = (
if is_valid() do (
init_data()
if top_level – bottom_level > 1 do
find_path best_path 0
return for i in best_path collect get_pos i
)
return #()
)

) – end struct best_path

– find best path and create it
fn make_path obj1 obj2 tol smooth:true = (
local knots_arr = (path_data obj1 obj2 tol).pos_list()
if knots_arr.count != 0 do (
local sh = splineShape pos:((obj1.center + obj2.center) / 2)
addNewSpline sh
if smooth then (
knot_type = #smooth
seg_type = #curve
) else (
knot_type = #corner
seg_type = #line
)
for kn in knots_arr do
addKnot sh 1 knot_type seg_type kn
updateShape sh
)
)

rollout rltBestVerticalPath “Vertical Path”
(
fn filt obj = obj.isSelected
pickButton pb1 “Pick Object 1” filter:filt autoDisplay:true
pickButton pb2 “Pick Object 2” filter:filt autoDisplay:true
spinner tol “Tolerance:” range:[0, 100, 0.5]
button make “Make Path”
radioButtons sh_type labels:#(“Smooth”, “Linear”)

on make pressed do (
local obj1 = pb1.object
local obj2 = pb2.object
if NOT obj1.isSelected OR NOT obj2.isSelected then
messageBox “Do not deselect!”
else make_path obj1 obj2 tol.value smooth:(sh_type.state == 1)
)
)
createDialog rltBestVerticalPath
)

and the error messages:
– Error occurred in init_data(); filename: G:…; position: 2609; line: 80

– called in pos_list(); filename: G:…; position: 3534; line: 105

– called in make_path(); filename: G:…; line: 118

– called in make.pressed(); filename: G:…; position: 5080; line: 150

>> MAXScript Rollout Handler Exception:
– Unknown system exception <<

i run you code in max 2010 and 2012. it doesn’t crash. i didn’t test its functionality but at least it loads without any error message.

PS. Please put your code between “code” tags…

i dont know how iits done…

about the code. yes its not a problem to load it. once you press the button it throws the errors i posted.

1 Reply
(@denist)
Joined: 10 months ago

Posts: 0

in MAX 2012 return expression is broken. avoid using it.
see http://forums.cgsociety.org/showpost.php?p=7028955&postcount=2

oh right! thanks alot.