[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
--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.
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.
in MAX 2012 return expression is broken. avoid using it.
see http://forums.cgsociety.org/showpost.php?p=7028955&postcount=2