how to combine multiple instances of vtkImageData? - vtk

I have multiple instances of vtkImageData representing a window of one large dataset. The instances are adjacent and non-overlapping.
I would like to slice through all the imageData with a single vtkPlaneWidget, so I have to somehow combine the imageData into a single input connection. I also want to be able to efficiently add or remove any instance of vtkImageData from the connection.
Right now I have the vtkImageData in a vtkMultiBlockDataSet. I thought I could filter the data using a filter with the executive vtkCompositeDataPipeline as in the Tcl snippet below.
# propogate the multiblock
MultiBlockDataSet mb
mb SetNumberOfBlocks [llength $image_data_list]
for {set i 0} {$i < [llength $image_data_list]} {incr i} {
mb SetBlock $i [lindex $image_data_list $i]}
}
vtkSimpleToSimpleImageFilter fltr
vtkCompositeDataPipeline cdp
fltr SetExecutive cdp
fltr SetInput cdp
vtkImagePlaneWidget plane
plane SetInputConnection [fltr GetOutputPort]
However, the plane doesn't seem like the input connection, and moreover I'm not terribly familiar with Vtk, so I'm wondering if this is the most suitable way to do this. Any suggestions?

By not knowing your code and how you read in your data ... one possible way would be to initialize a new vtkImageData object and add your slice data.
(quick example assuming three vtkImageData objects mySlice1, mySlice2 and myTotalSlices)
myTotalSlices->GetPointData->AddArray(mySlice1->GetPointData()->GetScalars());
myTotalSlices->GetPointData->AddArray(mySlice2->GetPointData()->GetScalars());
myTotalSlices->SetExtent(0, 511, 0, 511, 0, 1);
myTotalSlices->Update();
The values in SetExtent are just a example, of course you need to adjust them to fit to your data extent.
It would be also possible to remove an array i.e. index based
myTotalSlices->GetPointData->RemoveArray(0);

Related

How to pick random element of a certain class | GreenSock - GSAP

I would like to animate only certain elements of a certain class from an SVG image with GreenSock (GSAP).
To animate all the elements of a class, I would do:
gsap.to(".class", {duration: 5, rotate: 180, transformOrigin: 'center center', repeat: -1});
Now, how can I pick one (or more) random element(s) of and animate them like so.
What I want to do is animate them randomly by turn and indefinitely.
If you really need to create individual tweens, you would have to have a list (array) of all of your elements, keep track of which ones you've started to animate already, and sequentially fire off new tweens for them. Something like this:
// Get your elements in array form
const elems = gsap.utils.toArray(".class");
// Shuffle the array
const shuffled = (elems) => elems.sort(() => Math.random() - 0.5);
// Then fire of a new tween for each one, removing it from the array
while (shuffled.length > 0) {
let elem = shuffled.pop();
gsap.to(elem, {...}); // optionally keep track of the count to offset it or whatever
}
However, GSAP can do this sort of thing for you using staggers! How you do so depends on your needs. Since you haven't made those clear, here's a general idea of how to so this sort of thing:
gsap.to(".class", {
duration: 5,
rotate: 180,
transformOrigin: 'center center',
stagger: {
each: 0.1, // or even a negative value if you want them to all be started initially
repeat: -1
}
});
By the way, you're more likely to get an even faster response and additional opinions on your requests like this by posting in GreenSock's official forums.

how to write multiple vtkUnstructuredGrid in one .vtu file

I want to write multiple unstructured grids in one .vtu file.
I tried below. MakeHexagonalPrism() and MakeHexahedron() return vtkSmartPointer type.
The result is there was only one unstructured grid in the output file.
vtkSmartPointer<vtkXMLUnstructuredGridWriter> writer =
vtkSmartPointer<vtkXMLUnstructuredGridWriter>::New();
writer->SetFileName(filename.c_str());
writer->SetInputData(MakeHexagonalPrism());
writer->SetInputData(MakeHexahedron());
writer->Write();
I also tried below. The type of cellArray1 and cellArray2 is vtkSmartPointer. The result is there was only one type of unstructured grid in the output file.
vtkSmartPointer<vtkUnstructuredGrid> unstructuredGrid =
vtkSmartPointer<vtkUnstructuredGrid>::New();
unstructuredGrid->SetPoints(points);
unstructuredGrid->SetCells(VTK_TETRA, cellArray1);
unstructuredGrid->SetCells(VTK_WEDGE, cellArray2);
I do not know how to write multiple unstructured grids in one .vtu file.
I'd be grateful for any hints.
Quoting from the documentation for vtkXMLUnstructuredGridWriter available here
One unstructured grid input can be written into one file in any number
of streamed pieces (if supported by the rest of the pipeline).
So I think it is not possible to write multiple unstructured grid datasets to one file using this writer class.
Do you want multiple types of cells inside the same unstructured grid (which can be written to a single .vtu file) rather than multiple unstructured grids in the same .vtu file? If yes, you must first combine the two cell arrays into a single cell array and also create a int array which contains type of each cell in the total cell array. For example,
// Create a Type vector to store cell types
std::vector<int> types;
// Create a new cell array composed of cellArray1 and cellArray2
vtkSmartPointer<vtkCellArray> allCells =
vtkSmartPointer<vtkCellArray>::New();
// Traverse cellArray1 and add it's cells to allCells
vtkSmartPointer<vtkIdList> nextCell =
vtkSmartPointer<vtkIdList>::New();
cellArray1->InitTraversal()
while( cellArray1->GetNextCell( nextCell ) ){
allCells->InsertNextCell( nextCell );
types.push_back( VTK_TETRA );
}
// Traverse cellArray2 and add it's cells to allCells
cellArray2->InitTraversal()
while( cellArray2->GetNextCell( nextCell ) ){
allCells->InsertNextCell( nextCell );
types.push_back( VTK_WEDGE );
}
//Finally, set allCells to unstructuredGrid
unstructuredGrid->SetCells( &(types[0]), allCells );
Now when you write this unstructured grid to a .vtu file, I think you should have both wedge type and tetra type of cells in one file.
As described by the documentation, the vtkUnstructuredGrid class is very versatile.
dataset represents arbitrary combinations of all possible cell types
You could use the vtkAppendFilter in order to append different data sets into one then write the output as a vtkUnstructuredGrid result in a .vtu file.
// create the append filter
vtkSmartPointer<vtkAppendFilter> append =
vtkSmartPointer<vtkAppendfilter>::New();
// add each data set
append->AddInputData(MakeHexagonalPrism());
append->AddInputData(MakeHexahedron());
append->Update();
// write the result
vtkSmartPointer<vtkXMLUnstructuredGridWriter> writer =
vtkSmartPointer<vtkXMLUnstructuredGridWriter>::New();
writer->SetFileName(filename.c_str());
writer->SetInputData(append->GetOutput());
EDIT: I added the missing Update() function call as suggested by Amit Singh
As of #Gruillaume Faveiler's suggestion, using "vtkAppendFilter", the attributes would be filtered under the rule that: only those attribute existing in all inserted unstructuredGrid can be kept in the saved data (e.g., ug1 and ug2 are two appended unstructuredGrid, attribute "hight" exists in the pointData of both ug1 and ug2, then "hight" will be still in append->GetOutPut() which is also an unstructuredGrid, otherwise not)
In most cases when you have some attributes not in common for all inserted unstructuredGrid (in paraview, they call them "partial" attributes), which will be erased by vtkAppendFilter.
Better way for these cases is to use vtkMultiBlockDataSet in companion with vtkXMLMultiBlockDataWriter. One vtu file will be there for each UnstructedGrid, and a vtm file (containing no data) will be created to collect all vtu files into a structure. borrowing the example from #Guillaume Favelier, there will be:
vtkSmartPointer<vtkMultiBlockDataSet> multiBlockDataSet = vtkSmartPointer<vtkMultiBlockDataSet>::New();
// add each data set
vtkSmartPointer<vtkUnstructuredGrid> ug1 = MakeHexagonalPrism();
vtkSmartPointer<vtkUnstructuredGrid> ug2 = MakeHexahedron();
multiBlockDataSet->SetBlock(0, ug1);
multiBlockDataSet->SetBlock(1, ug2);
// write the result
vtkSmartPointer<vtkXMLMultiBlockDataWriter> writer = vtkSmartPointer<vtkXMLMultiBlockDataWriter>::New();
writer->SetFileName(filename.c_str());
writer->SetInputData(multiBlockDataSet);
writer->Write();

Create Dimensions from edge of wall, to sides of openings, to other edge of wall

I've been struggling with this issue off and on for the better part of a year.
As the title says, i wish to dimension from one side of a wall, to both sides of openings (door openings), then terminate at the other end of the wall (vertically and horizontally). I also wish to dimension to all families hosted in the wall, but i have been able to accomplish this using ScottWilson's voodo magic helper class. Found Here: http://thebuildingcoder.typepad.com/blog/2016/04/stable-reference-string-magic-voodoo.html
foreach (ElementId ele in selSet) {
FamilyInstance fi = doc.GetElement(ele) as FamilyInstance;
Reference reference = ScottWilsonVoodooMagic.GetSpecialFamilyReference(fi,ScottWilsonVoodooMagic.SpecialReferenceType.CenterLR,doc);
refs.Append(reference);
pts[i] = ( fi.Location as LocationPoint ).Point;
i++;
}
XYZ offset = new XYZ(0,0,4);
Line line = Line.CreateBound( pts[0]+offset, pts[selSet.Count - 1]+offset );
using( Transaction t = new Transaction( doc ) )
{
t.Start( "dimension embeds" );
Dimension dim = doc.Create.NewDimension(doc.ActiveView, line, refs );
t.Commit();
}
The problem lies in determining the appropriate stable references to the wall faces. I am able to find all faces on a wall, but this gives me 100+ faces to sort through.
If anyone can help me it would be greatly appreciated!
Side note: The closest of gotten is using a casting a ray trace through my panel, then using a reference intersector method to determine references. But i'm really struggling with implementation: http://thebuildingcoder.typepad.com/blog/2015/12/retrieving-wall-openings-and-sorting-points.html
These two posts should provide more than enough to solve all your issues:
Dimension walls by iterating their faces
Dimension walls by shooting a ray
Basically, you need to obtain references to the faces or edges that you wish to attach the dimensioning to. These references can be obtained in several ways. Two common and easy approaches are:
Retrieve the element geometry using the option ComputeReferences set to true and extract the specific face required.
Shoot a ray through the model to determine the required element and its face using the 2017
ReferenceIntersector Class.

Flot data serie with specific color per data element?

being new to Flot i am struggling a bit. My goal is the present a bar with different data elements in it that must have a different color per element. I want to provide the color per data element.
Any hints on how this can be done?
Example:
[0,100][0,200][0,100][0,200]
All elements with value 100 should be blue and all elements with 200 should be green.
A nice one would be,
[0,100,blue][0,200,green][0,100,blue][0,200,green]
But this off course does not work, it is just an explanation what i want to achieve!
Doing this with multiple data series seems does not work in my case.
Any hints on how this can be done?
You can do it with multiple series, as this is how I have done something like this :)
So in your plot method you would have something like this:
$.plot($('#placeholder'), []); // The array would hold your data
You can also further extend this to provide some options to flot to tell it what to make your chart look like. To do that you pass an object of options after the array.
However, im not quite sure what you need in terms of the Graph, your example gave some numbers but the x coordinate was all 0, im not sure if you just want a bar graph?
Anyway, heres the code of how you would get it to display a bar graph, with one green line and one blue line:
var flotOptions = {
series: {
lines: { show: true, fill: false, lineWidth: 15 }
}
},
var data = [{
color: '#001EFF',
data: [[0, 0], [0, 100]]
}, {
color: '#00FF0E',
data: [[5, 0], [5, 200]]
}];
$.plot($('#placeholder'), data, flotOptions);
I would recommend making it so that the data is automatically generated on a server side, then you can check in javascript, and add the color depending on the y value in the data array of each series.
I have also created a jsFiddle of this for you, so you can go take a look and play around with it. As I have said im not quite sure what you want but this is a good start for you. Good luck!!

Receiving reply from Redis ZRANGE

I currently have two sorted sets and I am trying to get all scores and members from one set and use it to remove members from the other set. The module that I am using is node_redis.
Right now I am trying to get the members and scores by calling client.zrange() and storing the reply in an array.
Am I correct in assuming the reply would be in array form? I realize the redis api says it returns a "Multi-bulk reply" but what does that mean exactly and how would I go about using it if it isn't an array?
I also have another question and that is can I use an array when using zadd()?
An example would be like this.
client.zadd(historyKey, scores, members, function(err, reply){});
Where scores and members are arrays.
EDIT:
I am working with receiving and parsing SNMP Traps. Basically I receive a trap and check its alarm type. The useful information in these traps are the alarm type and the full trap name. I check to see if the alarm is a 0,1, or 2.
If it's a 1, then I store it in my Current sorted set at the unix time I received it. If it's a 0 or 2 I know that type of alarm is done and that I need to remove all traps like it from the Current set and put them into the History set along with the one I just received.
In order to remove the traps from the Current and put them into the History I had to create a separate set for each individual trap in order to keep track of where they would be located in the Current set.
That is if I receive the trap "RGB Gamut Error( ----Bb )" at time 1346276537 and store it in Current, I also store the exact score and member in a separate set with key "IPAddress:RGB Gamut Error".
That way when I receive alarm type 0 or 2 with the name "RGB Gamut Error" I can just append the IP Address to the front of it, go do zrange on that set, then add to History and remove from Current. And lastly delete the "IPAddress:RGB Gamut Error" set so I can start fresh.
Sidenote: My members actually have two numbers added to the end in order to make each member unique and not overwrite each other. This is really there only purpose.
Ex: IPAdress::RGB Gamut Error( Rr--Bb ):5:46
Am I correct in assuming the reply would be in array form?
Yes, node_redis will give you the reply from a zrange as an array.
I also have another question and that is can I use an array when using zadd()? An example would be like this.
No. Before redis 2.4, you could only send one parameter at a time (so zadd key score member). Since redis 2.4, zadd (and many other commands) are variadic, i.e. they accept any number of parameters -- but not as an array. You still have to call it like this:
client.zadd(key, score1, member1, score2, member2, ..., function(err, reply){});
You could do some .apply trickery, but you would have to zip the scores and members arrays into one array first.
Update:
If you already have scores and members arrays, you could merge them into one array like this:
var scores = [1, 2, 3],
members = ['a', 'b', 'c'];
function merge (other) {
return function (result, current, index) {
result.push(current, other[index]);
return result;
}
}
var merged = scores.reduce(merge(members), []);
// Now merged = [1, 'a', 2, 'b', 3, 'c'];
var args = [key].concat(merged).concat(function(err, reply){});
client.zadd.apply(client, args);

Resources