How to update Actor after applying Transformation? - vtk

Currently I apply translation to an actor through below code:
vtkSmartPointer<vtkTransform> translation =
vtkSmartPointer<vtkTransform>::New();
translation->PostMultiply(); //this is the key line
translation->Translate(translationVector);
patella->getActor()->SetUserTransform(translation);
However, if I apply
patella->getActor()->SetUserTransform(translation);
again. The actor stays at the same position as if I applied it only once. I know it's because the origin is not updated. Thus, how can I update the origin/actor after each translation?

You want to concatenate the transforms. Something like:
vtkActor* patellaActor = patella->GetActor();
vtkTransform* patellaXfm = patellaActor->GetUserTransform();
if (!patellaXfm) {
patellaActor->SetUserTransform(translation);
} else {
patellaXfm->Concatenate(translation);
}

Related

Where is my error with my join in acumatica?

I want to get all the attributes from my "Actual Item Inventry" (From Stock Items Form) so i have:
PXResultset<CSAnswers> res = PXSelectJoin<CSAnswers,
InnerJoin<InventoryItem,
On<CSAnswers.refNoteID, Equal<Current<InventoryItem.noteID>>>
>
>.Select(new PXGraph());
But, this returns me 0 rows.
Where is my error?
UPDATED:
My loop is like this:
foreach (PXResult<CSAnswers> record in res)
{
CSAnswers answers = (CSAnswers)record;
string refnoteid = answers.RefNoteID.ToString();
string value = answers.Value;
}
... but i can not go inside foreach.
Sorry for the English.
You should use an initialized graph rather than just "new PXGraph()" for the select. This can be as simple as "this" or "Base" depending on where this code is located. There are times that it is ok to initialize a new graph instance, but also times that it is not ok. Not knowing the context of your code sample, let's assume that "this" and "Base" were insufficient, and you need to initialize a new graph. If you need to work within another graph instance, this is how your code would look.
InventoryItemMaint graph = PXGraph<InventoryItemMaint>.CreateInstance<InventoryItemMaint>();
PXResultset<CSAnswers> res = PXSelectJoin<CSAnswers,
InnerJoin<InventoryItem, On<CSAnswers.refNoteID, Equal<Current<InventoryItem.noteID>>>>>
.Select(graph);
foreach (PXResult<CSAnswers> record in res)
{
CSAnswers answers = (CSAnswers)record;
string refnoteid = answers.RefNoteID.ToString();
string value = answers.Value;
}
However, since you should be initializing graph within a graph or graph extension, you should be able to use:
.Select(this) // To use the current graph containing this logic
or
.Select(Base) // To use the base graph that is being extended if in a graph extension
Since you are referring to:
Current<InventoryItem.noteID>
...but are using "new PXGraph()" then there is no "InventoryItem" to be in the current data cache of the generic base object PXGraph. Hence the need to reference a fully defined graph.
Another syntax for specifying exactly what value you want to pass in is to use a parameter like this:
var myNoteIdVariable = ...
InventoryItemMaint graph = PXGraph<InventoryItemMaint>.CreateInstance<InventoryItemMaint>();
PXResultset<CSAnswers> res = PXSelectJoin<CSAnswers,
InnerJoin<InventoryItem, On<CSAnswers.refNoteID, Equal<Required<InventoryItem.noteID>>>>>
.Select(graph, myNoteIdVariable);
foreach (PXResult<CSAnswers> record in res)
{
CSAnswers answers = (CSAnswers)record;
string refnoteid = answers.RefNoteID.ToString();
string value = answers.Value;
}
Notice the "Required" and the extra value in the Select() section. A quick and easy way to check if you have a value for your parameter is to use PXTrace to write to the Trace that you can check after refreshing the screen and performing whatever action would execute your code:
PXTrace.WriteInformation(myNoteIdVariable.ToString());
...to see if there is a value in myNoteIdVariable to retrieve a result set. Place that outside of the foreach block or you will only get a value in the trace when you actually get records... which is not happening in your case.
If you want to get deep into what SQL statements are being generated and executed, look for Request Profiler in the menus and enable SQL logging while you run a test. Then come back to check the results. (Remember to disable the SQL logging when done or you can generate a lot of unnecessary data.)

Passing params to V93K test_suites.add method

This is in reference to this question. I checked our test interface and we are only passing the V93k primary params to the test_suites.add method.
V93K_PRIMARIES = [:lev_equ_set, :lev_spec_set, :timset, :tim_equ_set, :tim_spec_set, :seqlbl, :levset]
primary_tm_params = {}.tap do |primary_hash|
V93K_PRIMARIES.each do |param|
primary_hash[param] = tm_params.delete(param) unless tm_params[param].nil?
end
end
# Create the test suite
t = test_suites.add(test_name, primary_tm_params)
t.test_method = test_methods.amd93k.send(options[:tm].to_sym, tm_params)
V93K_PRIMARIES.each do |primary|
t.send("#{primary}=", primary_tm_params[primary]) unless primary_tm_params[primary].nil?
end
# Insert the test into the flow
test(t, tm_params)
When I set a breakpoint, I do see they were missing. Here they are after updating the code:
:ip=>:L2,
:testmode=>:speed,
:cond=>:pmax,
:if_failed=>:cpu_pmin,
:testtype=>:cpu,
:test_ip=>:bist,
:tm=>"Bist"}
And here is the .tf file generated from the original two tests in the original question:
run_and_branch(cpu_L2_speed_pmin_965EA18)
then
{
}
else
{
#CPU_PMIN_965EA18_FAILED = 1;
}
if #CPU_PMIN_965EA18_FAILED == 1 then
{
run(cpu_L2_speed_pmax_965EA18);
}
else
{
}
I think we have it figured out, thx very much!
The normal approach to this is just to pass everything to flow.test, rather than a subset of the options passed from the flow.
It will only act on the options it recognizes, which are basically the flow control parameters (:id, :if_failed, :unless_enabled, etc) and the test and bin number parameters, and it will just ignore the rest.

CRM PlugIn Pass Variable Flag to New Execution Pipeline

I have records that have an index attribute to maintain their position in relation to each other.
I have a plugin that performs a renumbering operation on these records when the index is changed or new one created. There are specific rules that apply to items that are at the first and last position in the list.
If a new (or existing changed) item is inserted into the middle (not technically the middle...just somewhere between start and end) of the list a renumbering kicks off to make room for the record.
This renumbering process fires in a new execution pipeline...We are updating record D. When I tell record E to change (to make room for D) that of course fires the plugin on update message.
This renumbering is fine until we reach the end of the list where the plugin then gets into a loop with the first business rule that maintains the first and last record differently.
So I am trying to think of ways to pass a flag to the execution context spawned by the renumbering process so the recursion skips the boundary edge business rules if IsRenumbering == true.
My thoughts / ideas:
I have thought of using the Depth check > 1 but that isn't a reliable value as I can't explicitly turn it on or off....it may happen to work but that is not engineering a solid solution that is hoping nothing goes bump. Further a colleague far more knowledgeable than I said that when a workflow calls a plugin the depth value is off and can't be trusted.
All my variables are scoped at the execute level so as to avoid variable pollution at the class level....However if I had a dictionary object, tuple, something at the class level and one value would be the thread id and the other the flag value then perhaps my subsequent execution context could check if the same owning thread id had any values entered.
Any thoughts or other ideas on how to pass context information to a new pipeline would be greatly appreciated.
Per Nicknow sugestion I tried sharedvariables but they seem to be going out of scope...:
First time firing post op:
if (base.Stage == EXrmPluginStepStage.PostOperation)
{
...snip...
foreach (var item in RenumberSet)
{
Context.ParentContext.SharedVariables[recordrenumbering] = "googly";
Entity renumrec = new Entity("abcd") { Id = item.Id };
#region We either add or subtract indexes based upon sortdir
...snip...
renumrec["abc_indexfield"] = TmpIdx + 1;
break;
.....snip.....
#endregion
OrganizationService.Update(renumrec);
}
}
Now we come into Pre-Op of the recursion process kicked off by the above post-op OrganizationService.Update(renumrec); and it seems based upon this check the sharedvariable didn't carry over...???
if (!Context.SharedVariables.Contains(recordrenumbering))
{
//Trace.Trace("Null Set");
//Context.SharedVariables[recordrenumbering] = IsRenumbering;
Context.SharedVariables[recordrenumbering] = "Null Set";
}
throw invalidpluginexception reveals:
Sanity Checks:
Depth : 2
Entity: ...
Message: Update
Stage: PreOperation [20]
User: 065507fe-86df-e311-95fe-00155d050605
Initiating User: 065507fe-86df-e311-95fe-00155d050605
ContextEntityName: ....
ContextParentEntityName: ....
....
IsRenumbering: Null Set
What are you looking for is IExecutionContext.SharedVariables. Whatever you add here is available throughout the entire transaction. Since you'll have child pipelines you'll want to look at the ParentContext for the value. This can all get a little tricky, so be sure to do a lot of testing - I've run into many issues with SharedVariables and looping operations in Dynamics CRM.
Here is some sample (very untested) code to get you started.
public static bool GetIsRenumbering(IPluginExecutionContext pluginContext)
{
var keyName = "IsRenumbering";
var ctx = pluginContext;
while (ctx != null)
{
if (ctx.SharedVariables.Contains(keyName))
{
return (bool)ctx.SharedVariables[keyName];
}
else ctx = ctx.ParentContext;
}
return false;
}
public static void SetIsRenumbering(IPluginExecutionContext pluginContext)
{
var keyName = "IsRenumbering";
var ctx = pluginContext;
ctx.SharedVariables.Add(keyName, true);
}
A very simple solution: add a bit field to the entity called "DisableIndexRecalculation." When your first plugin runs, make sure to set that field to true for all of your updates. In the same plugin, check to see if "DisableIndexRecalculation" is set to true: if so, set it to null (by removing it from the TargetEntity entirely) and stop executing the plugin. If it is null, do your index recalculation.
Because you are immediately removing the field from the TargetEntity if it is true the value will never be persisted to the database so there will be no performance penalty.

how come I replace a CALayer's position implicit animation and it still kicks in just before my own?

I'm doing something like this:
CABasicAnimation* translateA = [CABasicAnimation animation];
translateA.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
translateA.fillMode = kCAFillModeBoth;
translateA.duration = 1;
CALayer* nextLayer = <some layer...>
[nextLayer addAnimation:translateA forKey:#"position.y"];
newPos = nextLayer.position;
newPos.y += someDelta;
nextLayer.position = newPos;
And what happens is I see the layer almost "jump" to its final position and then my animation kicks in. My guess is the "almost jump" actually is the original implied animation for "position" (which is very short in duration). I also tried replacing for position instead of position.y and also tried replacing the whole actions dictionary in the layer (just to add this animation). But I always get the same result.
How would I go about it so that effectively I only see the layer translate for 1 sec.?
Can you show more code? I was getting this problem when using custom properties in drawInContext:
I had this in my own layer:
+ (BOOL)needsDisplayForKey:(NSString *)key
{
if ([key isEqualToString:#"progress"])
return YES;
else
return [super needsDisplayForKey:key];
}
And when doing this:
[self.layer setValue:#1 forKey:#"progress"];
And then:
[self.layer addAnimation:animation forKey:#"progress"];
drawInContext: was being called with progress 1 before the animation kicked in. Turns out the problem was that I was synthesizing the property (progress) with #dynamic. Removing this actually solved my problem :-)

Increase Hashmap Index Without Looping

I have working on clustering algorithm. I decided to use hashmap to store the points because thinking that i can use as clusterID and as the point. I do a dfs fashion search to identify nearest and my calculation related work and all the looping on data take place outside of the method that I identify the clusters.
Also the intention of this clustering is that, if a point belongs to a same cluster its id remain the same. What I want to find out is that once i enter value in the hash map how can increase the index for the next value (Key would be same) with out using loop.
Here is how my method looks like, I took up some content of the algorithm out of since it really not relevant to the question.
public void dfsNearest(double point) {
double aPointInCluster = point;
if(!cluster.contains(aPointInCluster)) {
...
this.setNumOfClusters(this.getNumOfClusters() + 1);
mapOfCluster.put(this.getNumOfClusters(), aPointInCluster);
//after this i want to increase the index so no override happens
}
...
if(newNeighbor != 0.0) {
cluster.add(newNeighbor);
mapOfCluster.put(this.getNumOfClusters(), newNeighbor);
//want to increase the index....
...
if (!visitedMap.containsKey(newNeighbor)) {
dfsNearest(newNeighbor);
}
}
...
}
Thanks for any suggestions, also please let me know if rest of the code is necessary to make a good decision. Just wanted to keep it simple.

Resources