How to extract the dataArray values within a rectangleWidget or shapewidget in vtk.js? - vtk

I am trying to develop a region of interest/ROI and a histogram(Piecewise Gussian Widget) corresponding to that ROI. Is there a way to extract the vtkImageData within the region or the dataArray within the ROI?

Related

Unexpected behaviour of geometry in Earth Engine

I am analysing solar farms and have defined two areas of geometry. In the example below, for a site called 'Stateline', I have drawn the boundary of the site and saved the geometry as a variable 'Stateline_boundary'. I have drawn around the solar panels within the boundary, which exist in two distinct groups and saved the geometry as a variable 'Stateline_panels'.
Stateline_panels has two co-ordinate lists (as there are two areas of panels).
When I try to subtract the area covered by the panels from the area within the boundary only the first of the two lists in the 'Stateline_panels' geometry is used (see code below and attached image).
var mask = Stateline_boundary
var mask_no_panels = mask.difference(Stateline_panels);
Map.addLayer(mask_no_panels,{},'Stateline_mask_no_panels',false);
I don't understand the behaviour of the geometry. Specifically why when adding the 'Stateline_panels' geometry to the map it displays in its entirety, but when used as a mask breaks the geometry and only uses the first of two lists of coordinates.
I was going to write a longer question asking why the geometry variables seem to behave differently when they are imported into the script rather than listed within the script (which I don't think should make a difference, but it does). However I think this is an earlier manifestation of whatever is going on.
The methodology that I found worked in the end was to create geometry assets individually with the polygon tool in the Earth Engine IDE - ensuring that each is on a different layer (using the line tool, then converting to polygons never worked).
Not only was this more flexible, it was also easier to manage on Earth Engine as editing geometries is not easy. I read about the importance of winding clockwise - though never determined if that was part of the issue here. If I always drew polygons clockwise the issue never occured.
I ended up with my aoi covered in polygons like this (each colour a different named layer/geometry object):
Once this was done, manipulating each geometry object in the code editor was relatively straightforward. They can be converted to FeatureCollections and merged (or subtracted) using simple code - see below for my final code.
It was also then easy to share them between scripts by importing the generated code.
I hope that helps someone - first attempt at answering a question (even if its my own). :)
// Convert panel geometries to Feature Collections and merge to create one object.
var spw = ee.FeatureCollection(stateline_panels_west);
var spe = ee.FeatureCollection(stateline_panels_east);
var stateline_panels = spw.merge(spe);
// Convert 'features to mask' geometries to Feature Collections.
var gc = ee.FeatureCollection(golf_course);
var sp = ee.FeatureCollection(salt_pan);
var sc = ee.FeatureCollection(solar_concentrator);
var h1 = ee.FeatureCollection(hill_1);
var h2 = ee.FeatureCollection(hill_2);
var h3 = ee.FeatureCollection(hill_3);
var mf = ee.FeatureCollection(misc_features);
// Merge geometries to create mask
var features_to_mask = gc.merge(sp).merge(sc).merge(h1).merge(h2).merge(h3).merge(mf);
// Convert 'Features_to_mask' to geometry (needed to create mask)
var features_to_mask = features_to_mask.geometry();
// Change name
var mask = features_to_mask
///// If site has other solar panels nearby need to add these separately & buffer by 1km
var extra_mask = ee.Feature(solar_concentrator);
var extra_mask = extra_mask.buffer(1000);
var extra_mask = extra_mask.geometry();
///// Join mask & extra mask into single feature using .union()
// Geometry objects
var mask = mask.union(extra_mask);

Once Shapefile is imported to Matlab, How to use longitude and latitude data from the created structure

I created a shapefie from a portal item in Arc GIS. So, on Matlab, I have this map, which shows the polygons outlined within NYC:
MapNYC
The shapefile I have is called "Sewershed.shp".
In Matlab, I type in:
shaperead('Sewershed');
Then, I get a 17x1 structure
17x1 Structure
So, the heading, "Bounding Box" are the longitude and latitude boundaries that define the Sewersheds (under heading "SewerShed")
The polygons in the map I showed above are the outlines of the sewer shed.
Now, I have an Excel spreadsheet that lists items as defined by longitude latitudes. I need to identify which Sewer Shed each item belongs to.
Excel Spreadsheet Image
I'd appreciate any help with this!
Josephina
assuming your boundingbox record has [x0,y0, x1,y1] where x0-x1 is the range of the longitude and y0-y1 is the range of your latitude. If you have a new coordinate newpt=[long1, lat1], you just need to compare long1 with x0-x1 and lat1 with y0-y1 and find the records that they belong to.
here is my sample test code
mydata(1).BoundingBox=[1,2,5,7]
mydata(2).BoundingBox=[2,3,6,9];
mydata(3).BoundingBox=[7,1,8,20];
bbx=cell2mat({mydata(:).BoundingBox}')
newpt=[4,3]
find(newpt(1)>=bbx(:,1) & newpt(1)<=bbx(:,3) & newpt(2)>=bbx(:,2) & newpt(2)<=bbx(:,4))

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();

How to change the value of a certain core data across VCs/ How to know the index of a created CoreData?

I start from a TableView to create and store user information. This is how I create a core data entity called "Trials" in CreateTrialViewController. And I can successfully fetch it in the tableViewController after I come back to it.
let trial : Trials = NSEntityDescription.insertNewObjectForEntityForName("Trials", inManagedObjectContext: self.managedObjectContext!) as? Trials
{
trial.project = theProject.text
trial.record = theRecord.text
trial.notes = theNotes.text
trial.percentile = ""
managedObjectContext?.save(nil)
}
'
But after I create the Trial, I will get some calculated results from the accelerometer in the next measureViewController, and I want to save the result into 'trial.percentile'.
I have already converted the results into a string, so I can write it directly into the core data attribute. But how can I know the index of this core data that I just created? Should I try to use 'segue' to transmit?
In the tableView it fetches in a ascending sequence of date, so the index is clear. But here in the following VC how to know the index? I still couldn't figure this out by myself... The sequence of my VCs is: TableViewController -> CreateTrialViewController -> MeasureViewController -> TableViewController (start again)
Your table view controller can keep a reference to the newly created object. Insert the object (trial) in the original view controller and pass it on to the next controller in prepareForSegue. So the CreateTrialViewController starts out with a blank object to which the table view controller has a reference.
You configure the object, go to the measure controller, modify the object. When done, you pop these two controllers from the navigation stack and are back in your original table view controller.
Because your table view controller has the NSFetchedResultsControllerDelegate enabled, it will update itself to reflect the data of your new object. Remember, you still have a reference to this object, so you can just use indexPathForObject to retrieve its index path.

How to update the fill color on existing svg elements with d3.js?

So i'm trying to make a map from an .svg file I produced with Illustrator because it's a map of the Netherlands with not so straightforward regions.
All the regions have their own #ID.
Now i'm trying to color each region according to their value in the dataset. I can force color on the regions by CSS ive done so on one region but thats obviously not good solution.
If I for example try to select(#id) and then change the .attr("fill","red"); it doesnt work.
How would I update region colors by id using d3.js according to the d[1] value in the dataset ?
Files: https://gist.github.com/gordonhatusupy/9466794
Live link: http://www.gordonjakob.me/regio_map/
The problem is that your Illustrator file already specifies fill colours on the individual <path> elements, and your id values are for parent <g> elements. Child elements inherit styles from parents, but only if the child doesn't have values of its own.
There are a couple things you could do to change it:
Change the Illustrator file so that the paths have no fill. Then they will inherit a fill colour set on the parent.
Select the paths directly, using d3.selectAll("g#id path") or d3.select("g#id").selectAll("path"); either version will select all <path> elements that are descendents of the <g> elment with id "id". Then you can set the fill attribute directly to over-write the value from Illustrator.
As discussed in the comments to the main question, if you want to take this a step further and actually join the data to the elements for future reference (e.g., in an event handler), the easiest way is to loop through your dataset, select each element, then use the .datum(newData) method to attach the data to each element:
dataset.forEach(function(d){ //d is of form [id,value]
d3.select("g#"+d[0]) //select the group matching the id
.datum(d) //attach this data for future reference
.selectAll("path, polygon") //grab the shapes
.datum(d) //attach the data directly to *each* shape for future reference
.attr("fill", colour(d[1]) ); //colour based on the data
});
http://jsfiddle.net/ybAj5/6/
If you want to be able to select all the top-level <g> elements in the future, I would suggest also giving them a class, so you can select them with, for example, d3.select("g.region"). For example:
dataset.forEach(function(d){ //d is of form [id,value]
d3.select("g#"+d[0]) //select the group matching the id
.datum(d) //attach this data for future reference
.classed("region", true) //add a class, without erasing any existing classes
.selectAll("path, polygon") //grab the shapes
.datum(d) //attach the data directly to *each* shape for future reference
.attr("fill", colour(d[1]) ); //colour based on the data
});
d3.selectAll("g.region")
.on("click", function(d,i) {
infoBox.html("<strong>" + d[0] + ": </strong>" + d[1] );
//print the associated data to the page
});
Example implementation: http://jsfiddle.net/ybAj5/7/
Although using dataset.forEach doesn't seem to be using the full capability of d3, it is actually much simpler than trying to attach the whole dataset at once -- especially since there is such variability in the structure of the regions, some of which have nested <g> elements:
//Option two: select all elements at once and create a datajoin
d3.selectAll("g[id]") //select only g elements that have id values
.datum(function(){
var id=d3.select(this).attr("id");
return [id, null]; })
//create an initial [id, value] dataset based on the id attribute,
//with null value for now
.data(dataset, function(d){return d[0];})
//use the first entry in [id,value] as the key
//to match the dataset with the placeholder data we just created for each
.selectAll("path, polygon") //grab the shapes
.datum(function(){
return d3.select(this.parentNode).datum() ||
d3.select(this.parentNode.parentNode).datum();
}) //use the parent's data if it exists, else the grandparent's data
.attr("fill", function(d){return d?colour(d[1]):"lightgray";});
//set the colour based on the data, if there is a valid data element
//else use gray.
This fiddle shows the above code in action, but again I would recommend using the forEach approach.

Resources