Notifications
Clear all

[Closed] Exit loop when bitarray stops changing

Okay so I fixed my version to account for the things you mentioned denis. It sets the default if unsupplied, checks for editable mesh, gets the first object in selection for default object, and checks for if object is undefined. I also forgot to mention that I was trying to get this to work for edit mesh and mesh select also, which it should.

I tried comparing your while loop method with my for loop method for speed and memory using timestamp and heapfree.

Here’s new version with for loop method –


 	fn GetBordersUsingEdgeMesh Obj:selection[1] Sel: = 
 	(
 		if (Obj != undefined) then
 		(
 			if (iskindof Obj editable_mesh or iskindof Obj trimesh) do
 			(
 				if (Sel == unsupplied) do Sel = Obj.selectedEdges as bitarray -- Get edge Selection
 				if (Sel != undefined) do
 				(
 					local AllBorderSel = (meshop.getOpenEdges Obj) -- Get all borders
 					local BorderSel = Sel -- Select within borders
 					local VertToEdgeOp = meshop.getEdgesUsingVert -- Get vert to edge operation
 					local EdgeToVertOp = meshop.getVertsUsingEdge -- Get edge to vert operation
 					for i = 1 to (Obj.numFaces * 3) do
 					(
 						local OldNum = BorderSel.numberset -- Get past selection
 						BorderSel = ((meshop.getEdgesUsingVert Obj (meshop.getVertsUsingEdge Obj BorderSel)) * AllBorderSel) -- Grow edge selection once within border
 						if (BorderSel.numberset == OldNum) then exit -- Exit if selection doesn't change
 					) -- Convert edges to border
 					return BorderSel -- Get edges
 				) -- If selection exists
 			) -- If object is editable mesh
 		) -- If object exists
 	)
 

Here’s new version with while loop method –


 	fn GetBordersUsingEdgeMesh2 Obj:selection[1] Sel: = 
 	(
 		if (Obj != undefined) then
 		(
 			if (iskindof Obj editable_mesh or iskindof Obj trimesh) do
 			(
 				if (Sel == unsupplied) do Sel = Obj.selectedEdges as bitarray -- Get edge Selection
 				if (Sel != undefined) do
 				(
 					local AllBorderSel = (meshop.getOpenEdges Obj) -- Get all borders
 					local BorderSel = Sel -- Select within borders
 					local Sel1 = #{}
 					local VertToEdgeOp = meshop.getEdgesUsingVert -- Get vert to edge operation
 					local EdgeToVertOp = meshop.getVertsUsingEdge -- Get edge to vert operation
 					while (not (BorderSel - Sel1).isEmpty) do
 					(
 						Sel1 = BorderSel
 						BorderSel = Sel - AllBorderSel
 						Sel = VertToEdgeOp Obj (EdgeToVertOp Obj Sel)
 						BorderSel = Sel - BorderSel
 					)
 					return BorderSel -- Get edges
 				) -- If selection exists
 			) -- If object is editable mesh
 		) -- If object exists
 	)
 

I tried comparing a teapot with 64 segments and selecting one edge from each border, and I ran these functions for a 100 times, taking an average of time and memory. The for loop function took 2390 milliseconds and the while loop function took 6575 milliseconds, so the for loop is over 2.5 times faster. The for loop took about 3137 bytes and the while loop method took 4669 bytes.

I also tried testing your original function denis, resulting in similar time and memory.as my second function. It took 6574 milleseconds and used 4862 bytes.

I did the same tests on a couple other objects, and the results where pretty much the same, which is surprising because I thought using while loops were generally faster.

first of all my idea was not to find the fastest way to get a border of an element by its edge selection. i just showed an algorithm of how to leave a loop when a collection stopped grow…

i don’t have max or max help around but try as i think fastest way of … see above


(meshop.getedgesusingface mesh (meshop.getelementsusingface mesh (meshop.getfacesusingedge mesh edges)))*(meshop.getopenedges mesh)

…hope i didn’t forget anything

Dude, what are you talking about?? I didn’t mention anything about elements or faces… The whole point of this thread was to find a faster / better method for converting an edge selection to a border selection for editable mesh. My last post was trying to compare methods to achieve that goal… I assumed you were trying to give me a faster method. If someone gives me another method I’ll compare the performance with that. If I didn’t care about the performance of my function, I wouldn’t have asked for a better one…

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0
hey, dude...
I'm talking about that I'm trying to teach new mxs scripters how to write good code... some students listen and learn quickly, some don't...

if you want to battle with my code OK:

    fn convertEdgesToBorder node:selection[1] edges: show:on = if iskindof node editable_mesh or iskindof node trimesh do
(
	if edges == unsupplied do edges = node.selectededges as bitarray
	fn getElements node faces = 
	(
		elements = #{}
		while not faces.isEmpty do
		(
			out = off
			for f in faces while not out do 
			(
				faces -= join elements (meshop.getelementsusingface node f)
				out = on
			)
		)
		elements
	)
	border = #{}
	opened = meshop.getopenedges node
	if not (edges *= opened).isEmpty do
	(
		border = (meshop.getedgesusingface node (getElements node (meshop.getfacesusingedge node edges)))*opened
	)
	if show do node.selectededges = border
	border
)

fn GetBordersUsingEdgeMesh Obj:selection[1] Sel: = 
  (
  	if (Obj != undefined) then
  	(
  		if (iskindof Obj editable_mesh or iskindof Obj trimesh) do
  		(
  			if (Sel == unsupplied) do Sel = Obj.selectedEdges as bitarray -- Get edge Selection
  			if (Sel != undefined) do
  			(
  				local AllBorderSel = (meshop.getOpenEdges Obj) -- Get all borders
  				local BorderSel = Sel -- Select within borders
  				local VertToEdgeOp = meshop.getEdgesUsingVert -- Get vert to edge operation
  				local EdgeToVertOp = meshop.getVertsUsingEdge -- Get edge to vert operation
  				for i = 1 to (Obj.numFaces * 3) do
  				(
  					local OldNum = BorderSel.numberset -- Get past selection
  					BorderSel = ((meshop.getEdgesUsingVert Obj (meshop.getVertsUsingEdge Obj BorderSel)) * AllBorderSel) -- Grow edge selection once within border
  					if (BorderSel.numberset == OldNum) then exit -- Exit if selection doesn't change
  				) -- Convert edges to border
  				return BorderSel -- Get edges
  			) -- If selection exists
  		) -- If object is editable mesh
  	) -- If object exists
  )
  
  delete objects 
  (
  	t = converttomesh (plane widthsegs:64 lengthsegs:64)
  	edges = #{((meshop.getopenedges t) as array)[1]}
  	
  	gc()
  	t1 = timestamp()
  	m1 = heapfree
  	for k=1 to 100 do
  	(
  		t.selectededges = edges
  		convertEdgesToBorder node:t
  	)
  	format "method:% time:% memory:%
" "denisT" (timestamp() - t1) (m1 - heapfree)
  
  	gc()
  	t1 = timestamp()
  	m1 = heapfree
  	for k=1 to 100 do
  	(
  		t.selectededges = edges
  		GetBordersUsingEdgeMesh obj:t
  	)
  	format "method:% time:% memory:%
" "Ian31R" (timestamp() - t1) (m1 - heapfree)
  )
   

result:


   method:denisT time:766 memory:99384L
   method:Ian31R time:11200 memory:4210984L
   
as you see for the time being my algorithm is ~15 times faster than yours and eats ~40 times less memory.

Hey I appreciated the general coding advice. But what did you think I was asking for? I wasn’t really concerned with much else, but what I asked for. I didn’t really want to get off subject that much. In fact I was mainly trying to figure out the best method for knowing how to stop looping a selection when the bitarray stops changing, to save on speed. This main point of this thread was to figure that out, not necessarily the method for getting the borders, which I would consider extra help. There are other cases where I would use this method, to convert a face selection to elements in patches, by growing the selection until it fills the elements.

I wasn’t asking for a “battle”. Why would I even try to compete with you? I was trying to get people to come up with better alternative solutions to the one I had. Again that’s what I thought you were trying to help me with. It seems like you are misunderstanding a lot of what I am saying…

Your method is a lot different, do you care to explain how it works using elements? I’ll try to test it myself and see if its doing what I wanted it to.

Okay, so I think were having some miscommunication here… The problem with your function is that it gets all the borders within the same element as the edge selection. The operation I’m trying to recreate is the poly operation “node.ConvertSelection #Edge #Border” but for mesh.

The method I’m using to duplicate this is by growing the edge selecting within all open edges until the selected borders fill up. I plan on trying to make a similar function for patches and I want to make sure its efficient.

Please don’t think I’m trying to compete with you denis… I just wanted everyone to share alternatives, and come up with one that’s the most efficient. If no one wants to help, or I can’t find a better solution, I’ll just stick with what I have, its not a big deal…

Party is over, but,
While I won’t offer a better solution(code) than the OP,which is probably as good as it gets, (not much better using that kind of code). I’ll only say the next, for anybody who needs an explicit answer to the question if there are possible faster methods. That the test-results I get, are 25x+ faster on one mesh, and on another 50x faster, and it can be way faster depending on the case…
But the solution is complex and does not relate with anything I’ve seen in the internet, so I won’t share it for now, but I have the feel that most if not all compiled plugins are unoptimized too…

About heapfree memory . the eternal myth
Everytime I see memory vs memory, I smell nonsense:
On x test maxscript memory says it took 185352/1024^2 == 0.176765 MB(MiB)
But the system reports that 252+ MB(MiB) were used, and it’s not difficult to figure, why…
Any way, it’s very vague, to give heapfree enough importance or reliability.

For the case of 50x faster result,
maxscript tells me I used 2x memory, but the system only uses around 10MB (vs 252MB, OP solution)

Threads like this one, are related with threads like this:
http://forums.cgsociety.org/showthread.php?p=7563749

i don’t know why but i don’t believe you… i remember samples of your code on this forum those worked differently to an expectation and your declaration.

I don’t lie. NOT how I am.
absurd to even think about it, considering that I participate in this forum for years.

I don’t remember posting similar code here because i’m sure, i’ve never…
I remember posting a .mse for subdivision reversed, very unoptimized too.
(In case you un-encrypted it)

I’ve known this fact, for quite a long time. about radical speed increases…
For this very reason, if this turn out a lie…
Then THIS WOULD BE A BIG LIE. that will be recorded forever in internet.

I thought you knew since long ago, but you simply don’t. many thinks you don’t…
I did write a little about this, in the past, now that I remember…
That’s why I don’t like when people like youo post direct answers that others copy. Then when someone says something, there’s people who can’t understand the meaning…

I bet the people who designed editable poly would know or figure it out. and computer scientists, because it’s not exactly a secret.

i don’t say that you lies. you probably confuse an expectation with the actuality. i like a challenge. here is the deal. make a sample mesh and give us what you do with this mesh and what does it take with your algorithm. and we will try to compete.

Well in my opinion now, I think this thread may have been a mistake… I probably should have just asked for different ways of getting a border from an edge with edit mesh, that way I can decide which might be better for me.

Actually, I do find it useful when denis posts a whole function or script as a response, because I can learn a lot of from it, such as general coding practice or learning how to be more efficient. Sometimes though, like in this case, I would rather have a breakdown of a technique, followed by a code snippet, not try to figure out how to make the whole script generally faster. Also, its true that answering with a whole script or function can be confusing sometimes, because you have to go through, and figure out where the specific solution is. Either way, I think its important to post a breakdown of what your code is doing.

Well, challenges are great and all, but I’m not trying to compete in this thread, nor have I ever tried to compete with anyone, because like I said I’m not a titan of mxs. If anything, I was trying to compete with myself, by making variations of my method, and seeing which was faster.

I did notice that in some of my threads, you replied to denis, you thought I was competing with you, when that’s far from true. I’m not sure why, maybe its due to miscommunication. When I ask for help on here, I try to get a variety of solutions, and hopefully some breakdowns of those solutions, and try to compare them, so we can all come together and decide which might be the best solution.

Page 2 / 2