<div dir="ltr">Hi Paul,<div><br></div><div>I may have misunderstood but could you not just project each triangle in the stl mesh onto the frontal plane (using vtkPlane::ProjectPoint() ), then sum the projected areas?</div>
<div><br></div><div>You may have to prune the mesh first of triangles not "facing" the plane... you could use vtkVectorDot to do this. You'll also have to deal with occluded triangles (if you have them)</div>
<div><br></div><div>hth,</div><div><br></div><div>Goodwin<br><br><div class="gmail_quote">On Wed, Oct 24, 2012 at 2:18 PM, Paul McIntosh <span dir="ltr"><<a href="mailto:paul.mcintosh@internetscooter.com" target="_blank">paul.mcintosh@internetscooter.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi All,<br>
<br>
I have been working on a utility for calculating frontal area of an STL mesh<br>
for CFD. I thought I had it cracked my scanning a line through the mesh at<br>
evenly spaced distances and then counting the number of hits (based on the<br>
OBBTree example). However on closer inspection the areas I was getting were<br>
always larger than they should be, with reason being the OBBTree method is<br>
not precise and I was getting double/triple hits at edges. I have included<br>
the code below as it would probably help someone solve some other problem ;)<br>
<br>
Ok - back to the drawing board... the next obvious way of doing this (and<br>
probably quicker) is to render with parallel projection and then count<br>
pixels in the result.<br>
<br>
Is there an easy way to take sceenshot so that pixels are a known size? Any<br>
pointers welcome!<br>
<br>
Cheers,<br>
<br>
Paul<br>
---<br>
<a href="http://www.internetscooter.com" target="_blank">www.internetscooter.com</a><br>
<br>
<br>
<a href="https://github.com/internetscooter/Vespa-Labs/blob/master/VespaCFD/Calculate
FrontalArea/CalculateFrontalArea.cxx" target="_blank">https://github.com/internetscooter/Vespa-Labs/blob/master/VespaCFD/Calculate<br>
FrontalArea/CalculateFrontalArea.cxx</a><br>
<br>
#include <vtkPolyData.h><br>
#include <vtkTriangle.h><br>
#include <vtkLineSource.h><br>
#include <vtkSTLReader.h><br>
#include <vtkSmartPointer.h><br>
#include <vtkPolyDataMapper.h><br>
#include <vtkIdTypeArray.h><br>
#include <vtkSelectionNode.h><br>
#include <vtkActor.h><br>
#include <vtkRenderWindow.h><br>
#include <vtkRenderer.h><br>
#include <vtkRenderWindowInteractor.h><br>
#include <vtkSelection.h><br>
#include <vtkExtractSelection.h><br>
#include <vtkDataSetMapper.h><br>
#include <vtkProperty.h><br>
#include <vtkObjectFactory.h><br>
#include <vtkCellArray.h><br>
#include <vtkCell.h><br>
#include <vtkInformation.h><br>
#include <vtkExtractSelectedPolyDataIds.h><br>
#include <vtkOBBTree.h><br>
<br>
<br>
// C++<br>
#include <iostream><br>
using namespace std;<br>
<br>
// just to make things nicer later and save some documentation reading ;)<br>
struct boundingBox {<br>
double xmin;<br>
double xmax;<br>
double ymin;<br>
double ymax;<br>
double zmin;<br>
double zmax;<br>
};<br>
<br>
// this projects a series of lines through a mesh and looks for<br>
intersections to determine frontal area<br>
// lines are projected based on the bounding box and the resolution is<br>
determined by the steps<br>
// For my application I just need to look at frontal area along the X<br>
direction. The follow code could easily be<br>
// adapted to take a direction as a command line option and produce the area<br>
from that .<br>
// So this currently "scans" yMin->yMax,zMin->ZMax, with a line from Xmin to<br>
Xmax<br>
// ref:<br>
<a href="http://www.cmake.org/Wiki/VTK/Examples/Cxx/DataStructures/OBBTree_IntersectW" target="_blank">http://www.cmake.org/Wiki/VTK/Examples/Cxx/DataStructures/OBBTree_IntersectW</a><br>
ithLine<br>
int main(int argc, char *argv[])<br>
{<br>
// check and get the stl input file provided<br>
if ( argc != 2 )<br>
{<br>
cout << "Required parameters: Filename" << endl;<br>
return EXIT_FAILURE;<br>
}<br>
std::string inputfile = argv[1];<br>
<br>
// later this should be a command line option - hard coded for now<br>
double resolution = 0.005; // step value while scanning - will need to<br>
do some more calculations later if changed<br>
//char direction = "X"; // direction of scan<br>
<br>
// read STL and print out some info<br>
std::cout << "Reading: " << inputfile << std::endl;<br>
vtkSmartPointer<vtkSTLReader> stlReader =<br>
vtkSmartPointer<vtkSTLReader>::New();<br>
stlReader->SetFileName(inputfile.c_str());<br>
vtkSmartPointer<vtkPolyData> polydata =<br>
vtkSmartPointer<vtkPolyData>::New();<br>
polydata = stlReader->GetOutput();<br>
polydata->Update();<br>
// Debug info if needed:<br>
cout << "Cells: " << polydata->GetNumberOfCells() << endl;<br>
cout << "Points: " << polydata->GetNumberOfPoints() << endl;<br>
cout << "Polys: " << polydata->GetNumberOfPolys() << endl;<br>
cout << "Verts: " << polydata->GetNumberOfVerts() << endl;<br>
polydata->Print(cout);<br>
<br>
// makes sense to only scan in an area the object exists, the bounding<br>
box will tell us this<br>
double bounds[6];<br>
boundingBox boxBounds;<br>
polydata->GetBounds(bounds);<br>
boxBounds.xmin = bounds[0] - resolution*5;<br>
boxBounds.xmax = bounds[1] + resolution*5;<br>
boxBounds.ymin = bounds[2] - resolution*5;<br>
boxBounds.ymax = bounds[3] + resolution*5;<br>
boxBounds.zmin = bounds[4] - resolution*5;<br>
boxBounds.zmax = bounds[5] + resolution*5;<br>
<br>
// Debug info if needed:<br>
std::cout << "xmin: " << boxBounds.xmin << " "<br>
<< "xmax: " << boxBounds.xmax << std::endl<br>
<< "ymin: " << boxBounds.ymin << " "<br>
<< "ymax: " << boxBounds.ymax << std::endl<br>
<< "zmin: " << boxBounds.zmin << " "<br>
<< "zmax: " << boxBounds.zmax << std::endl;<br>
<br>
// build OBB Tree locator<br>
vtkSmartPointer<vtkOBBTree> tree = vtkSmartPointer<vtkOBBTree>::New();<br>
tree->SetDataSet(polydata);<br>
tree->BuildLocator();<br>
<br>
// calculate area<br>
double area = 0;<br>
for (double zdir = boxBounds.zmin; zdir < boxBounds.zmax; zdir = zdir +<br>
resolution)<br>
{<br>
for (double ydir = boxBounds.ymin; ydir < boxBounds.ymax; ydir =<br>
ydir + resolution)<br>
{<br>
// Line to intersect with<br>
double p1[3] = {boxBounds.xmin, ydir + resolution/2, zdir +<br>
resolution/2,};<br>
double p2[3] = {boxBounds.xmax, ydir + resolution/2, zdir +<br>
resolution/2,};<br>
//Find intersection points<br>
vtkSmartPointer<vtkPoints> intersectPoints =<br>
vtkSmartPointer<vtkPoints>::New();<br>
tree->IntersectWithLine(p1, p2, intersectPoints, NULL);<br>
// this bit will draw a rough approximation of the shape<br>
if (intersectPoints->GetNumberOfPoints() > 0)<br>
{<br>
cout << "#";<br>
area++;<br>
}<br>
else<br>
{<br>
cout << " ";<br>
}<br>
}<br>
cout << std::endl;<br>
}<br>
// output how many hits, which for a resolution of 1 should equal<br>
something like 1mm^2<br>
cout << "area: " << area * resolution * resolution << std::endl;<br>
<br>
return EXIT_SUCCESS;<br>
}<br>
<br>
<br>
<br>
_______________________________________________<br>
Powered by <a href="http://www.kitware.com" target="_blank">www.kitware.com</a><br>
<br>
Visit other Kitware open-source projects at <a href="http://www.kitware.com/opensource/opensource.html" target="_blank">http://www.kitware.com/opensource/opensource.html</a><br>
<br>
Please keep messages on-topic and check the VTK FAQ at: <a href="http://www.vtk.org/Wiki/VTK_FAQ" target="_blank">http://www.vtk.org/Wiki/VTK_FAQ</a><br>
<br>
Follow this link to subscribe/unsubscribe:<br>
<a href="http://www.vtk.org/mailman/listinfo/vtkusers" target="_blank">http://www.vtk.org/mailman/listinfo/vtkusers</a><br>
</blockquote></div><br></div></div>