Problem scripting a 'trim' operation
 1-20  21-38

Next
 From:  Dave Morrill (DMORRILL)
3541.1 
Michael,

I'm having some difficulty using the MoI API to programmatically perform a 'trim' operation. The error I get is: "Invalid pointer" when I attempt to execute 'trimmer.generateFragments();', where 'trimmer' is a trim factory object I created previously.

I'm assuming the error is being generated by some internal C++ code catching a bad input to one of the trim factory object inputs, but I've been scratching my head trying to figure out which one is causing it fits. The actual code I'm trying to execute is:

function trim ( objects, cutters, extend_lines, project_intersections ) {
var trimmer = factory( 'trim', as_list( objects ), as_list( cutters ), null,
'keep', arg( extend_lines, false ),
arg( project_intersections, true ) );
trimmer.generateFragments();
trimmer.setInput( 2, object_list() );
trimmer.finishedPickingFragments();

return trimmer.calculate()
}

Now obviously it is difficult for you to tell what this code is doing without access to the rest of the code, but basically, each argument to the 'factory' function results in a 'setInput' call on the factory object being created, a 'null' argument means skip setting that positional input, the 'as_list' function makes sure its input argument is a MoI ObjectList, and the 'arg' function returns either the first argument (if it is specified by the caller), or the second argument (if it is not).

In this case, I have verified that the 'objects' and 'cutters' arguments are lists ('objects' is a list of 3 'curve' objects, and 'cutters' is a list containing a single 'curve' object).

I've studied the MoI 'Trim.js' file and I can't see any significant difference between what I am trying to do and what you are doing (excluding all the interactive picking logic).

In general, I have used this 'factory' method successfully in a lot of other procedural code to do various boolean and geometry creation operations, so I know that the basic premise it uses is more or less correct. The main difference is that after the setup step I usually just call 'calculate' on the factory object to produce the resulting geometry.

In the case of 'trim', that was not doing anything useful. So I studied 'Trim.js' in more detail and saw the call to 'generateFragments', which I assume is calculating the trim fragments both to allow further user picking and to produce the final result set. And that's where the trouble began :-)

On a related note, I'm not too clear on the subtleties of the factory 'calculate', 'update' and 'commit' methods. I've been working on the assumption that 'calculate' causes the factory to use its inputs to calculate a set of geometry objects, but does not update the screen or commit the results to the MoI geometry database. The 'update' method does something similar but does update the screen to show the user what the factory is currently producing, and that 'commit' adds the results that the factory produces to the MoI geometry database.

I bring this up because I've noticed that sometimes after performing a procedural operation that creates some (later discarded) intermediate geometry (using the factory 'calculate' method) on the way to producing a final result, the intermediate geometry will sometimes show up on the display at the end of the script, but will often disappear once you start manipulating the display view in various ways. This leads me to believe that my above assumptions are somewhat flawed, since there seems to be some cases where the geometry has not been committed to the database, but can still show up on the display. In some of these cases, I've also noticed that I often get the 'wait' hourglass cursor for a while as well.

Finally, another question I have is whether factory methods can only work on 'committed' geometry, or can they also work on any valid geometry passed to them. I've been assuming they can work on any geometry, but would like to have that point clarified.

Sorry for the long post, but if you can provide any answers, I'll make sure that they are used to improve the API documentation I've been working on for a while...

- Dave Morrill
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Michael Gibson
3541.2 In reply to 3541.1 
Hi Dave, first a quick description of how calculate / update / commit / cancel is supposed to work.

The factory system is set up primarily to support interactive commands where the user may be changing parameters interactively and wanting to see some feedback on the screen while the command is running.

In order to show an object changing, what actually happens is the existing object is hidden (but still in the geometry database), then the edited object is created by the factory, and added to the geometry database so that it will render on the screen when the geometry database is drawn, because that's how all things are drawn, by drawing the geometry database. This happens during calls to .update(), which can be called either directly by a command script, or if the is a binding set up the binding mechanism will automatically call update when the other partner of the bind is triggered. So for example when UI control is bound to a factory input, when the UI control changes it will stuff the new value into the factory and call update(), that's what the binders handle.

But the original objects, and newly created objects are kept track of by the factory in some internal lists. If the factory is canceled (which can happen by the command script itself calling .cancel() or also by the system if the factory is forcibly pulled down), then it restores the original objects visibility and removes the new objects from the geometry database.

During the command ending cleanup step, any active factories that have not had .commit() called on them are also canceled.

So in order to signal that the command script was fully executed, it calls .commit() before it ends to signal that the command's whole process was executed, and at that point the original objects (that up until now were just hidden) are actually removed from the database.


Some commands also have what are called "UI objects" that are things like additional lines or points added to the geometry database while the command is running for additional illustration purposes.


The .calculate() method is added to this factory system to help with someone who wants to use the factory procedurally in a script rather than in an interactive command. It runs the factory and generates the new objects, but the new objects are not automatically added to the geometry database, they are just returned in a list so they could be used for additional calculations without necessarily showing up on the screen, and the original objects are not hidden.

During .calculate() there is a flag set to disable the creation of "UI geometry" by the factory, but possibly some older commands need to be updated to respect that. If you are seeing some left-over bits of lines or points or stuff like that, let me know what commands you see them in and they probably need to be updated to not generate UI geometry when the flag is set.


So I hope that description helps a bit at least, I'll take a look at Trim and see if I can figure anything out there.

- Michael
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Michael Gibson
3541.3 In reply to 3541.1 
Hi Dave, then also some factories have custom properties or methods exposed on them which the command script can call in order to get some value to put in the UI, or to trigger some particular stage of the command.

As you noticed, Trim has a couple of these.

- Michael
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Michael Gibson
3541.4 In reply to 3541.1 
Trim could be a good example where you would probably want a different script interface to it rather than the current factory one which is so set up to cater to the way the interactive command works.

When the interactive command works in some distinct stages like Trim does (with the fragment picking stage), that becomes somewhat awkward to replicate in procedural code.

Other more typical commands where it's just a matter of filling out all the inputs tends to be a better direct fit.

- Michael
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Michael Gibson
3541.5 In reply to 3541.1 
Hi Dave, so I looked at the .generateFragments() method on the trim factory, and it should only return E_POINTER (which translates to a message of "Invalid pointer") if it was given a NULL pointer for it to write its return value out to.

It wants to return a boolean true/false value for whether any fragments were generated.

Is it possible that the way you are calling it is not providing the pointer for a return value?

This would be the pointer named "pVarResult" in IDispatch::Invoke()
http://msdn.microsoft.com/en-us/library/aa912367.aspx


But if you are calling it through regular JavaScript, the whole JavaScript system is supposed to be providing that pointer for the return value to be written to.

- Michael
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Michael Gibson
3541.6 In reply to 3541.1 
Hi Dave, I'm not sure if I answered this question:

quote:
Finally, another question I have is whether factory methods can only work on 'committed' geometry, or can they also work on any valid geometry passed to them. I've been assuming they can work on any geometry, but would like to have that point clarified.


But I may need some clarification - which factory methods are you referring to here, do you mean a custom method that a particular factory implements like those special ones on Trim, or do you mean one of the regular methods common to all factories?

So one thing to note is that geometry itself does not really have a "committed" state, it's actually the factory that has that state.

When a factory is being used in an interactive command, the newly created geometry (created during a call to .update() ) is actually added to the geometry database as well, otherwise it would not show up on the screen. But when you do a factory.commit(), it then knows not to remove that geometry during the cleanup stages when a command exits, otherwise that geometry is removed if a factory is torn down before a commit() happened.

If you do a factory.calculate(), then that generates a list of output objects but does not process them in any of the other ways that happen during the normal interactive update/commit/cancel type stuff. That's so you could potentially use those objects for other intermediate calculations instead of forcing them to be displayed on the screen.

So the results of .calculate() are not added automatically to the geometry database. But you should be able to use them for inputs into other factories, however if you need them to be selected and show up in the geometry database you will need to add them to the geometry database yourself.


Geometry does have a flag for whether it is "in the database" or not in the database list, but that's a different thing than a factory's committed state.

- Michael
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  BurrMan
3541.7 In reply to 3541.6 
Well....THAT explains it!!! And I thought it was going to be something I didnt understand :o
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Dave Morrill (DMORRILL)
3541.8 In reply to 3541.2 
Michael,

Thanks for the detailed explanation of the factory execution model! I hope you don't mind if I use bits and pieces of your explanation in the API documentation I am writing?

For the most part, it sounds like the mental model I had developed in the course of reading through a lot of the MoI command scripts was more or less correct, but having it spelled out is really very helpful. The bit about the binders automatically calling 'update' helps clarify how the binders operate quite a bit, since deducing how they worked just from the Javascript code examples was quite a bit of guesswork on my part (although it turns out the actual function as you described it is nearly identical to the mechanism I use in the Python Traits framework I wrote that I'm using to do a lot of the external scripting of MoI with).

Now, just to nail this thing down a little better, let me summarize what I think I understand about MoI geometry and its life cycle:

- In order to be displayed on the screen, all geometry must be in the geometry database.
- It is possible to create, maintain and use geometry that is not displayed to the user (i.e. not in the geometry database).
- Factories can work with any geometry objects, whether or not they are in the geometry database.

Now, the big question: when/how are geometry objects destroyed?

Since C++ does not do automatic garbage collection, my guess is that you are using some form of reference counting, probably based upon the geometry objects being added to/removed from ObjectList objects. Based upon this assumption, adding geometry to the geometry database automatically keeps geometry alive, because it become part of one or more lists that the database manages. Sub-objects are kept alive by lists maintained by parent objects. Geometry that is not in the database is kept alive by being part of one or more ObjectLists maintained outside of the database.

Destruction of geometry not in the database can be accomplished by the removal of the geometry objects from all ObjectLists being maintained by a script (talking from a scripting perspective).

If you can confirm or clarify this description, I think it will go a long way towards helping me to understand the MoI internals better...

- Dave Morrill
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Dave Morrill (DMORRILL)
3541.9 In reply to 3541.3 
>Hi Dave, then also some factories have custom properties or methods exposed on them
>which the command script can call in order to get some value to put in the UI, or to trigger
>some particular stage of the command.

>As you noticed, Trim has a couple of these.

Yes, so I discovered from reading the Trim code yesterday :-) This caused me to refactor the way I was creating factory objects. Previously, there was just a single 'create' function, which took the factory type and all of the inputs to the factory as arguments. It would then create the factory, do a 'setInput' for each provided argument, then call 'factory.calculate()' and return the result.

Now I have added a separate 'factory' function (shown in the example code I posted previously) which simply returns the factory object without calling 'calculate'. This allows the caller to issue some of the 'special' methods (like 'generateFragments') first.

I do not believe the IDL file contains anything for these special methods (since they are not showing up in the documentation I am automatically generating). There only seems to be descriptions for the base GeometryFactory class. Does that mean the only way to discover them is to pore over the xxx.js files looking for them?

- Dave Morrill
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Dave Morrill (DMORRILL)
3541.10 In reply to 3541.4 
> Trim could be a good example where you would probably want a different
> script interface to it rather than the current factory one which is so set up
> to cater to the way the interactive command works.

> When the interactive command works in some distinct stages like Trim does
> (with the fragment picking stage), that becomes somewhat awkward to replicate
> in procedural code.

> Other more typical commands where it's just a matter of filling out all the inputs
> tends to be a better direct fit.

Well, I certainly agree, which is part of the reason I have been trying to create a procedural interface to MoI which encapsulates the MoI API into a more procedural approach. For example, I have a 'line' function which takes two Point objects as input and returns the expected curve object as the result.

BTW, I have been taking the approach that all geometry creating functions return objects that are not part of the geometry database. If the caller wants the user to see them, then a separate function must be called to register them. This makes it simpler to create intermediate results used to generate other final geometry.

At this point I have not completely encapsulated every MoI factory type using this approach. In fact, I just wrote the 'trim' function yesterday, which is why this question just came up now.

I'm still not completely clear on using the 'trim' factory. If I just want to create a set of trim fragments from the set of objects and cutters, do I need to call 'generateFragments' after initializing the factory object (I assume so). This returns a boolean, which means the factory must be keeping the fragment list internally at that point. So which method will return me the fragment list?

- Dave Morrill
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Dave Morrill (DMORRILL)
3541.11 In reply to 3541.5 
> Hi Dave, so I looked at the .generateFragments() method on the trim factory,
> and it should only return E_POINTER (which translates to a message of "Invalid pointer")
> if it was given a NULL pointer for it to write its return value out to.

> It wants to return a boolean true/false value for whether any fragments were generated.

> Is it possible that the way you are calling it is not providing the pointer for a return value?

> This would be the pointer named "pVarResult" in IDispatch::Invoke()
> http://msdn.microsoft.com/en-us/library/aa912367.aspx

> But if you are calling it through regular JavaScript, the whole JavaScript system is supposed
> to be providing that pointer for the return value to be written to.

Eureka! That was the problem...thank you so much for continuing to think about this!

If you noticed in the code I posted yesterday, I had written:

factory.generateFragments();

instead of something like:

var result = factory.generateFragments();

Apparently the Javascript API to the COM interface is actually sensitive to that, and was not providing anything useful for the 'pVarResult' value in the case where the result was not being consumed. Once I added code to do something with the result, the problem went away (although I am still having problems get useful results from the 'trim' factory).

That's a huge issue to be aware of! Thanks again for sticking with me on this problem...

- Dave Morrill
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Dave Morrill (DMORRILL)
3541.12 In reply to 3541.6 
> Hi Dave, I'm not sure if I answered this question:

> But I may need some clarification - which factory methods...

> ...Geometry does have a flag for whether it is "in the database" or not
> in the database list, but that's a different thing than a factory's committed state.

Thanks again for continuing to clarify this. I think a clearer picture of how the factories work is starting to emerge :-)

- Dave Morrill
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Michael Gibson
3541.13 In reply to 3541.8 
Hi Dave,

> I hope you don't mind if I use bits and pieces of your
> explanation in the API documentation I am writing?

Sure, feel free to use it!


> The bit about the binders automatically calling 'update'
> helps clarify how the binders operate quite a bit <...>

Also I should mention that there are a few of varieties of binders, there is one that goes on HTML elements in the UI, which are set up with a bindingx="" attribute.

Then there's one that can be set up with moi.ui.bindUIToInput(), which hooks up a UI control to a factory input, and handles copying the control's value to the input and calling update() on the factory when the control's value has changed.

Also the point picker has its own binding methods where you can tell it to connect to a factory input, and when the pointpicker has a new point from a mouse move, it sends the point (or the point + cplane frame, or just the cplane frame) to the factory input and calls update().

quote:

- In order to be displayed on the screen, all geometry must be in the geometry database.
- It is possible to create, maintain and use geometry that is not displayed to the user (i.e. not in the geometry database).
- Factories can work with any geometry objects, whether or not they are in the geometry database.

Yup, that's all correct!

Or should be anyway - the last one should be correct but let me know if you run into instances with a particular command where it does not seem to work properly. One thing is that objects do not get their ID guid assigned to them until they are added into the geometry database. So it could be possible that something is sensitive to that, but it is not supposed to be.


> Now, the big question: when/how are geometry objects destroyed?

They are reference counted just like you suspected.

So you never really explicitly destroy it, but if you remove it from any list that was holding a reference to it, your script will then hold the last reference and the object will be destroyed when your script itself gets garbage collected or terminated.


> Based upon this assumption, adding geometry to the geometry
> database automatically keeps geometry alive, because it become
> part of one or more lists that the database manages.

Yup, that's correct - the geometry database list holds a reference count open on the objects in it.


> Sub-objects are kept alive by lists maintained by parent objects.

Yup.


> Geometry that is not in the database is kept alive by being part of
> one or more ObjectLists maintained outside of the database.

Yup, or you can also have an individual object all by itself referenced by script - the script engine itself will keep an open reference count on the object in that case.


> Destruction of geometry not in the database can be accomplished
> by the removal of the geometry objects from all ObjectLists being
> maintained by a script (talking from a scripting perspective).

Yup, the object itself will be destroyed when the last reference is released.

- Michael
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Michael Gibson
3541.14 In reply to 3541.9 
Hi Dave,

> I do not believe the IDL file contains anything for
> these special methods (since they are not showing
> up in the documentation I am automatically generating).

Yeah, that's right - those are not declared in the IDL and are just implemented dynamically by some factories.

But most of the time they are things that are used by the UI, like for instance when doing a rotation the UI wants to show the current angle that the factory is rotating by if it was just given points as the inputs. So the rotate factory has a custom "angle" property that the UI can access to get put that number into the UI.

Or some things might analyze the input and tell the UI whether certain controls should be enabled or disabled.

Most of the time it's stuff more like that, Trim is kind of an exception.


> Does that mean the only way to discover them is to pore over
> the xxx.js files looking for them?

Yeah, that's the only way you would be able to find them right now.

But Trim may be the only thing that has a custom method that is needed to be triggered for the thing to actually do its work. The vast majority of those things are just for querying stuff to put in the UI for feedback while you are moving the mouse around.

- Michael
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Michael Gibson
3541.15 In reply to 3541.10 
Hi Dave, re: scripting Trim

> So which method will return me the fragment list?

So the way the command works is you put an object list for objects to trim in input 0.

Then you put in an object list for cutting objects in input 1.

Then run the generateFragments() method, this will create an internal list of fragments, and those fragments are added to the geometry database and then the next step of the regular Trim command is to pick which pieces you want to discard.

Once the selection of pieces to discard (or keep depending on the mode) is finished, then those go into a "selected fragments" list which goes into input 2. You can put in an object list there that is empty which will be the same as selecting nothing in the Trim command which splits everything up.

After that I think you should be able to call .calculate() to get the split up pieces.

So the key thing is you have to have an object list in input 2, even if it does not have any objects in it. That's just a quirk of how Trim happened to be written, it fails if it could not retrieve the object list holding the selected fragments that came from the object picker in the regular trim workflow.

- Michael
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Dave Morrill (DMORRILL)
3541.16 In reply to 3541.14 
> But Trim may be the only thing that has a custom method that is needed to
> be triggered for the thing to actually do its work. The vast majority of those
> things are just for querying stuff to put in the UI for feedback while you are
> moving the mouse around.

OK, sounds like from a procedural point of view, 'trim' is the only one that might require some additional documentation.

For completeness, it might be nice to document the other stragglers as well, but since I have not got complete explanations done yet for all the methods documented in the IDL, I guess I won't worry about them until everything else has been documented.

Thanks...

- Dave Morrill
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Dave Morrill (DMORRILL)
3541.17 In reply to 3541.15 
> So the key thing is you have to have an object list in input 2, even if it does
> not have any objects in it. That's just a quirk of how Trim happened to be written,
> it fails if it could not retrieve the object list holding the selected fragments that
> came from the object picker in the regular trim workflow.

Hmm...after reading this encouraging response, I re-examined my 'trim' function and found that this was more or less what I was doing. However, it did take quite a bit more experimentation to get it to work (more or less) correctly. After much additional fiddling around and testing, I found that the following code seems to work (from a procedural perspective):

function trim ( objects, cutters, extend_lines, project_intersections ) {
var trimmer = factory( 'trim', as_list( objects ), as_list( cutters ),
object_list(), 'remove', arg( extend_lines, false ),
arg( project_intersections, true ) );
var result = trimmer.generateFragments();
var result = trimmer.calculate();
trimmer.reset();

return result;
}

The things to note about this code are:

- I bind an empty ObjectList to input 2 (fragments), but never look at it again.
- The call to 'calculate' produces the expected 'fragments' list to return.
- You MUST call 'reset' on the trim factory, otherwise the internal state of MoI gets really messed up (but doesn't crash). What I got was some fragments that could never be deleted using the UI, but moving them created new clones that could be deleted (weird). Putting the 'reset' call in fixed that behavior.

After my experience with finding that it was necessary to call 'reset' to get 'trim' to behave correctly, I began to investigate the problem I was seeing with weird 'ghost' objects when using other factories. What I found there was that the following code seems to work well for other factories (such as 'line'):

...set up factory and initialize it...
var result = f.calculate();
f.cancel();

return result;

Note that (at least in the case of 'line', which I've been doing the testing on), the call to 'cancel' seems to cure the problem with weird ghost objects showing up on the display (but a call to 'reset' did not fix the problem in this case).

In any case, this exercise seems to have made my procedural interface a little more reliable in the results it produces, so thanks again for all the explanations...

- Dave Morrill
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Michael Gibson
3541.18 In reply to 3541.17 
Hi Dave, so what kind of ghost objects are you seeing with the line, is it an extra point object?

Are you possibly calling update() at some time before you call calculate() ?

If so then you probably should leave out the call to update() because that's meant to be used for an interactive command, so things like UI objects are created during that call, in the case of Line there is a point object created to mark the beginning point.

If you do call update(), then you could call cancel() to erase the interactive stuff like the UI geometry though.

But if you call calculate() only and avoid calling update() the UI geometry should be suppressed.


But it sounds like you may be currently getting the regular "interactive mode" stuff created by a call to update() - if you just want to generate output objects directly and have them returned to your script then call calculate() _instead_ of calling update().


- Michael
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Dave Morrill (DMORRILL)
3541.19 In reply to 3541.18 
> Hi Dave, so what kind of ghost objects are you seeing with the line, is it an extra point object?

I never use 'update' calls in my code. Previously, when I was still seeing the 'ghost' objects, the only factory call I was using was 'calculate'. Now, in addition to 'calculate', I also call 'cancel' after the call to 'calculate', which seems to eliminate the 'ghost' objects when creating things like lines.

What I mean by a 'ghost' object is a copy of a created object (like a line) that was never explicitly added to the geometry database (i.e. because only 'calculate' was used to create it), but which nevertheless shows up in the viewport.

The situation is usually as follows:

- Run a script that creates a line (using 'calculate'), but which never gets added to the geometry database.
- The viewport looks OK at this point (i.e. the created line is not visible, since it was not added to the geometry database).
- Now, using the UI (not a script), start an interactive operation, like creating another line. Click with the mouse to set the line's start point.
- At this point, the original line (created by the script in step 1), appears in all viewports.
- Complete the drawing of the interactive line by clicking to set the end point.
- At this point, the interactively created line is visible, and the 'ghost' line from step 1 disappears, never to be seen again.

Another attribute of 'ghost' geometry is that it can never be selected by clicking (no pre-selection highlight, no selection highlight), but can be selected by box dragging (normal pre-selection highlight and final selection highlight). However, once selected, the object cannot be moved, deleted, etc., although it does eventually go away, as described in the preceding series of steps. You would see this behavior immediately after running the script, when attempting to click or drag select on the empty space in the viewport where the created line should be.

So it looks like there are some circumstances where 'calculate' does put created geometry into a state where it may be displayed for a short while (usually during the extent of the next command). As I mentioned, placing a 'cancel' call after the call to 'calculate' does seem to clear up the problem (in most cases, although 'reset' seems to do a better job when using the 'trim' factory, as I mentioned before).

At this point, with the 'reset' (for 'trim') and 'cancel' (for everything else) calls in place, I have not seen any 'ghost' geometry at all. The only anomalous behavior I am seeing at this point is that when running a fairly complex script that creates lots of intermediate geometry, using a mixture of different factory operations, MoI sometimes ends up in a state that seems like it is waiting for a command to end. That is, the viewports all look fine, and may contain correctly selected objects (created by the script), but I cannot deselect existing objects or select new ones. Pressing 'enter' or 'esc' seems to exit whatever state is in in, and things are back to normal after that. I'm still investigating this, and it may be due to some other error in my script...

- Dave Morrill
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Dave Morrill (DMORRILL)
3541.20 In reply to 3541.19 
Michael,

Let me know if you want me to send you some Javascript code that can reproduce the 'ghost' object behavior. But I think you can get the behavior I described by writing a simple script that:

- Creates a 'line' factory object and sets all its inputs.
- Run the 'calculate' method on the factory object.

At that point I think you should be able to see the 'ghost' line behavior I described...

- Dave Morrill
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged
 

Reply to All Reply to All

 

 
Show messages:  1-20  21-38