algorithmic modeling for Rhino
Let's say, (-"-)
in c++:
static ON_3dPoint* MakeSomePoints(ON_Line* line, int* num)
{
*num = total point number
ON_3dPoint* result = new ON_3dPoint[*num]();
get *num points on the line;
}
static void DisposeMyPoints(ON_3dPoint* ptrObject[])
{
if(ptrObject!=NULL)
{
delete [] ptrObject;
ptrObject =NULL;
}
}
Tags:
Two recommendations:
1. use the non-legacy scripting components, so use RhinoCommon types - this means using Point3d instead of ON_3dPoint, and Line instead of ON_Line.
2. Use the built-in System.Collections types. Rather than going through all the mess above, simply declare a List<Point3d> and be done with it.
For example:
List<Point3d> MakeSomePoints(Line L, int num){
List<Point3d> results = new List<Point3d>();
for(int i = 0;i <= num;i++){
results.Add(L.PointAt(i / (double) num));
}
return results;
}
Where is this C++ code running from?
--
David Rutten
david@mcneel.com
Poprad, Slovakia
ON_3dPoint* MarchingCubeComputeMeshPoints(int resX, int resY, int resZ, double data[], double iso, ON_3dPoint* minCorner,ON_3dPoint*maxCorner, int* outNum)
{
int resX_1 = resX+1, resY_1 = resY+1, resZ_1 = resZ+1;
/*if((resX_1)*(resY_1)*(resZ_1) != sizeof(data) / sizeof(data[0]))
{
*outNum = 0;
return NULL;
}*/
int sliceXY = (resX_1)*(resY_1);
double intervalX = 1.0/resX;
double intervalY = 1.0/resY;
double intervalZ = 1.0/resZ;
ON_BoundingBox box = ON_BoundingBox(*minCorner,*maxCorner);
ON_Box refBox = ON_Box(box);
//Get corners of a single voxel
ON_3dPoint corners[8];
corners[0] = refBox.PointAt(0.0,0.0,0.0);
corners[1] = refBox.PointAt(intervalX,0.0,0.0);
corners[2] = refBox.PointAt(intervalX,intervalY,0.0);
corners[3] = refBox.PointAt(0.0,intervalY,0.0);
corners[4] = refBox.PointAt(0.0,0.0,intervalZ);
corners[5] = refBox.PointAt(intervalX,0.0,intervalZ);
corners[6] = refBox.PointAt(intervalX,intervalY,intervalZ);
corners[7] = refBox.PointAt(0.0,intervalY,intervalZ);
double d[8];
ON_3dPoint intersectionPoints[16];
int minCornerIndex= 0;
vector<ON_3dPoint> pts;
for (int z = 0; z < resZ; z++)
{
for (int y = 0; y < resY; y++)
{
for (int x = 0; x < resX; x++)
{
minCornerIndex = z * sliceXY + y * resX_1 + x;
d[0] = data[minCornerIndex];
d[1] = data[minCornerIndex + 1];
d[2] = data[minCornerIndex + 1 + resX_1];
d[3] = data[minCornerIndex + resX_1];
d[4] = data[minCornerIndex + sliceXY];
d[5] = data[minCornerIndex + 1 + sliceXY];
d[6] = data[minCornerIndex + 1 + resX_1 + sliceXY];
d[7] = data[minCornerIndex + resX_1 + sliceXY];
ON_3dVector translate = refBox.PointAt(x * intervalX, y * intervalY, z * intervalZ) - corners[0];
int num = VoxelBox::GetFaces(corners, d, iso, intersectionPoints);
if (num > 0)
{
for (int i = 0; i < num; i += 3)
{
pts.push_back(ON_3dPoint(intersectionPoints[i].x + translate.x, intersectionPoints[i].y + translate.y, intersectionPoints[i].z + translate.z));
pts.push_back(ON_3dPoint(intersectionPoints[i + 1].x + translate.x, intersectionPoints[i + 1].y + translate.y, intersectionPoints[i + 1].z + translate.z));
pts.push_back(ON_3dPoint(intersectionPoints[i + 2].x + translate.x, intersectionPoints[i + 2].y + translate.y, intersectionPoints[i + 2].z + translate.z));
*outNum += 3;
}
}
}
}
}
ON_3dPoint* result = new ON_3dPoint[pts.size()]();
for(unsigned int i =0;i<pts.size();i++)
{
result[i].Set(pts[i].x,pts[i].y,pts[i].z);
}
return result;
}
I think it's slow in tow places.
1. using vector<> to hold all the points first, then copy them to the array.
2. in c#, List<double> .ToArray
The first time I tested the code in Grasshopper, a warning "can''t find entry point blahblah..." came up. Then I did some google, used extern "C"__declspec(dllexport) and a .DEF file. If more code is added in, updating the .DEF file manually will be annoying.
How is RhinoCommon manage all the exported functions?
RhinoCommon consists of two parts, rhcommon_c.dll which is a pure C++ library that exposes Rhino SDK features as easily PInvokeable functions and RhinoCommon.dll which is a pure C# library which invokes these methods.
We have a small console application which runs through the rhcommon_c source code and collects all invokable methods, then it creates a giant C# class which exposes all of these in a way that .NET can call.
There are also a bunch of special classes in the Rhino.Runtime.InteropWrappers namespace that help us ferry data from C++ to C# and vice versa.
Things like ON_3dPoint etc. are somewhat special but basically we make sure that the memory layout of Point3d is the same as ON_3dPoint so we can pass a pointer.
Maybe it would be easier if you created arrays of doubles rather than ON_3dPoint? {x0,y0,z0,x1,y1,z1,x2,y2,z2,...} Then you can just iterate in steps of 3 and build Point3d structs from the coordinates.
--
David Rutten
david@mcneel.com
Poprad, Slovakia
Thanks, David. Marshalling double instead of Point3d struct can close the gap a little bit. //double[] dataArray = data.ToArray(); double[] dataArray = (double[])typeof(List) .GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance) .GetValue(data); I googled a way to convert List to array without copying, but there is no significant improvement. Reflection is not a good approach.
Hi Ian,
Here's some sample code that may clarify how I would go about performing the pInvoke.
https://gist.github.com/3970130
Let me know if you have any questions.
Thanks,
-Steve
Welcome to
Grasshopper
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
© 2024 Created by Scott Davidson. Powered by