Nếu bất cứ ai quan tâm, tôi đang sử dụng WPF ....Làm thế nào tôi có thể polygonise một bool [,,]
Bắt đầu của câu chuyện:
tôi có một loạt các hình ảnh màu xám quy mô (lát của một mô hình). Người dùng nhập "phạm vi" các giá trị thang màu xám để tạo mô hình 3D. Vì vậy, tôi đã tạo một mảng 3D bool
để làm cho việc xây dựng mô hình 3D dễ dàng hơn. Mảng này đại diện cho một hộp pixel, cho biết mỗi pixel có nên được tạo/tạo/lấp đầy hay không.
Các tie:
Sử dụng một bool[,,]
, tôi muốn lấy một List<Point3D[]>
nơi mỗi Point3D[]
có chiều dài 3 và đại diện cho một hình tam giác trong không gian 3D.
Thông tin thêm:
Mô hình được tạo ra sẽ được in 3D. Trong số bool[,,]
, true
cho biết sự hiện diện của vật chất, trong khi false
cho biết sự vắng mặt của vật chất. Tôi cần phải tránh các mô hình khối, trong đó mỗi pixel được thay thế bằng một khối lập phương (Điều đó sẽ vô dụng theo mục đích của tôi). Mô hình nên càng trơn tru càng tốt và càng chính xác càng tốt.
Những gì tôi đã cố gắng để làm:
1- Tôi thực hiện các thuật toán khối diễu hành, nhưng nó chỉ đơn giản dường như không phải được tạo ra để chấp nhận một "phạm vi" các giá trị.
2- Tôi tiếp tục đấu tranh trong một vài ngày cố gắng tạo thuật toán của riêng mình, nhưng tôi đã thất bại một phần. (Nó thật phức tạp Nếu bạn muốn biết thêm về nó, xin vui lòng thông.)
Một số giải pháp dự kiến rằng tôi không có ý tưởng làm thế nào để thực hiện:
1- Sửa đổi các thuật toán khối Marching để làm cho nó hoạt sử dụng một
bool[,,]
2- Sửa đổi các thuật toán khối Marching để làm cho nó hoạt sử dụng một tác phẩm sử dụng một "tầm" của isolevel
giá trị
3- Hiển thị cách triển khai thuật toán khác phù hợp với mục đích của tôi (Có thể thuật toán Ray-Casting) trong WPF.
4- Yêu cầu nguồn của thuật toán mà tôi đã cố thực hiện sau đó chỉ cho tôi cách giải quyết.
(Nó đã được thực hiện để đa giác một bool[,,]
ở nơi đầu tiên)
5- Một số giải pháp kỳ diệu khác.
Xin cảm ơn trước.
EDIT:
Bằng cách nói
Sử dụng một
bool[,,]
, tôi muốn lấy mộtList<Point3D[]>
nơi mỗiPoint3D[]
có chiều dài 3 và đại diện cho một hình tam giác trong không gian 3D.
Tôi có nghĩa là tôi muốn truy xuất một nhóm Hình tam giác. Mỗi tam giác phải được thể hiện bằng 3 Point3D
s. Nếu bạn không biết Point3D
là gì, nó là struct
chứa 3 đôi (X, Y và Z) được sử dụng để đại diện cho một vị trí trong không gian 3D.
Vấn đề với thuật toán hình khối diễu hành là nó khá mơ hồ. Ý tôi là, bạn hiểu gì khi làm điều đó?
cubeindex = 0;
if (grid.val[0] < isolevel) cubeindex |= 1;
if (grid.val[1] < isolevel) cubeindex |= 2;
if (grid.val[2] < isolevel) cubeindex |= 4;
if (grid.val[3] < isolevel) cubeindex |= 8;
if (grid.val[4] < isolevel) cubeindex |= 16;
if (grid.val[5] < isolevel) cubeindex |= 32;
if (grid.val[6] < isolevel) cubeindex |= 64;
if (grid.val[7] < isolevel) cubeindex |= 128;
Vì vậy, tôi chỉ đơn giản là không biết bắt đầu sửa đổi nó ở đâu.
Một EDIT:
Sau một số thử nghiệm với các thuật toán khối diễu hành, tôi nhận thấy rằng polygonising một bool[,,]
sẽ không dẫn đến việc mô hình 3D mượt mà tôi mong muốn, vì vậy tôi giải pháp dự kiến đầu tiên và giải pháp dự kiến thứ tư của tôi đều không được phát. Sau rất nhiều nghiên cứu, tôi đã biết về phương pháp Ray-Casting về hiển thị khối lượng. Nó có vẻ thực sự mát mẻ, nhưng tôi không thực sự chắc chắn nếu nó phù hợp với nhu cầu của tôi. Tôi thực sự không thể hiểu cách nó được triển khai như thế nào mặc dù tôi biết cách hoạt động.
Thêm một EDIT: TriTable.LookupTable
và EdgeTable.LookupTable
là bảng hiện here
Đây là lớp MarchingCubes
:
public class MarchingCubes
{
public static Point3D VertexInterp(double isolevel, Point3D p1, Point3D p2, double valp1, double valp2)
{
double mu;
Point3D p = new Point3D();
if (Math.Abs(isolevel - valp1) < 0.00001)
return (p1);
if (Math.Abs(isolevel - valp2) < 0.00001)
return (p2);
if (Math.Abs(valp1 - valp2) < 0.00001)
return (p1);
mu = (isolevel - valp1)/(valp2 - valp1);
p.X = p1.X + mu * (p2.X - p1.X);
p.Y = p1.Y + mu * (p2.Y - p1.Y);
p.Z = p1.Z + mu * (p2.Z - p1.Z);
return (p);
}
public static void Polygonise (ref List<Point3D[]> Triangles, int isolevel, GridCell gridcell)
{
int cubeindex = 0;
if (grid.val[0] < isolevel) cubeindex |= 1;
if (grid.val[1] < isolevel) cubeindex |= 2;
if (grid.val[2] < isolevel) cubeindex |= 4;
if (grid.val[3] < isolevel) cubeindex |= 8;
if (grid.val[4] < isolevel) cubeindex |= 16;
if (grid.val[5] < isolevel) cubeindex |= 32;
if (grid.val[6] < isolevel) cubeindex |= 64;
if (grid.val[7] < isolevel) cubeindex |= 128;
// Cube is entirely in/out of the surface
if (EdgeTable.LookupTable[cubeindex] == 0)
return;
Point3D[] vertlist = new Point3D[12];
// Find the vertices where the surface intersects the cube
if ((EdgeTable.LookupTable[cubeindex] & 1) > 0)
vertlist[0] = VertexInterp(isolevel, grid.p[0], grid.p[1], grid.val[0], grid.val[1]);
if ((EdgeTable.LookupTable[cubeindex] & 2) > 0)
vertlist[1] = VertexInterp(isolevel, grid.p[1], grid.p[2], grid.val[1], grid.val[2]);
if ((EdgeTable.LookupTable[cubeindex] & 4) > 0)
vertlist[2] = VertexInterp(isolevel, grid.p[2], grid.p[3], grid.val[2], grid.val[3]);
if ((EdgeTable.LookupTable[cubeindex] & 8) > 0)
vertlist[3] = VertexInterp(isolevel, grid.p[3], grid.p[0], grid.val[3], grid.val[0]);
if ((EdgeTable.LookupTable[cubeindex] & 16) > 0)
vertlist[4] = VertexInterp(isolevel, grid.p[4], grid.p[5], grid.val[4], grid.val[5]);
if ((EdgeTable.LookupTable[cubeindex] & 32) > 0)
vertlist[5] = VertexInterp(isolevel, grid.p[5], grid.p[6], grid.val[5], grid.val[6]);
if ((EdgeTable.LookupTable[cubeindex] & 64) > 0)
vertlist[6] = VertexInterp(isolevel, grid.p[6], grid.p[7], grid.val[6], grid.val[7]);
if ((EdgeTable.LookupTable[cubeindex] & 128) > 0)
vertlist[7] = VertexInterp(isolevel, grid.p[7], grid.p[4], grid.val[7], grid.val[4]);
if ((EdgeTable.LookupTable[cubeindex] & 256) > 0)
vertlist[8] = VertexInterp(isolevel, grid.p[0], grid.p[4], grid.val[0], grid.val[4]);
if ((EdgeTable.LookupTable[cubeindex] & 512) > 0)
vertlist[9] = VertexInterp(isolevel, grid.p[1], grid.p[5], grid.val[1], grid.val[5]);
if ((EdgeTable.LookupTable[cubeindex] & 1024) > 0)
vertlist[10] = VertexInterp(isolevel, grid.p[2], grid.p[6], grid.val[2], grid.val[6]);
if ((EdgeTable.LookupTable[cubeindex] & 2048) > 0)
vertlist[11] = VertexInterp(isolevel, grid.p[3], grid.p[7], grid.val[3], grid.val[7]);
// Create the triangle
for (int i = 0; TriTable.LookupTable[cubeindex, i] != -1; i += 3)
{
Point3D[] aTriangle = new Point3D[3];
aTriangle[0] = vertlist[TriTable.LookupTable[cubeindex, i]];
aTriangle[1] = vertlist[TriTable.LookupTable[cubeindex, i + 1]];
aTriangle[2] = vertlist[TriTable.LookupTable[cubeindex, i + 2]];
theTriangleList.Add(aTriangle);
}
}
}
Đây là lớp GridCell
:
public class GridCell
{
public Point3D[] p = new Point3D[8];
public Int32[] val = new Int32[8];
}
Ok, đó là những gì tôi đang làm:
List<int[][]> Slices = new List<int[][]>(); //Each slice is a 2D jagged array. This is a list of slices, each slice is a value between about -1000 to 2300
public static void Main()
{
List <Point3D[]> Triangles = new List<Point3D[]>();
int RowCount;//That is my row count
int ColumnCount;//That is my column count
//Here I fill the List with my values
//Now I'll polygonise each GridCell
for (int i = 0; i < Slices.Count - 1; i++)
{
int[][] Slice1 = Slices[i];
int[][] Slice2 = Slices[i + 1];
for (int j = 0; j < RowCount - 1; j++)
{
for (int k = 0; k < ColumnCount - 1; k++)
{
GridCell currentCell = GetCurrentCell (Slice1, Slice2, j, k);
Polygonise (ref Triangles, int isoLevel, GridCell currentCell);
}
}
}
//I got the "Triangles" :D
}
//What this simply does is that it returns in 3D space from RI and CI
public static GridCell GetCurrentCell (int[][] CTSliceFront, int[][] CTSliceBack, int RI, int CI)//RI is RowIndex and CI is ColumnIndex
{
//Those are preset indicating X,Y or Z coordinates of points/edges
double X_Left_Front;
double X_Right_Front;
double X_Left_Back;
double X_Right_Back;
double Y_Top_Front;
double Y_Botton_Front;
double Y_Top_Back;
double Y_Botton_Back;
double Z_Front;
double Z_Back;
GridCell currentCell = new GridCell();
currentCell.p[0] = new Point3D(X_Left_Back, Y_Botton_Back, Z_Back);
currentCell.p[1] = new Point3D(X_Right_Back, Y_Botton_Back, Z_Back);
currentCell.p[2] = new Point3D(X_Right_Front, Y_Botton_Front, Z_Front);
currentCell.p[3] = new Point3D(X_Left_Front, Y_Botton_Front, Z_Front);
currentCell.p[4] = new Point3D(X_Left_Back, Y_Top_Back, Z_Back);
currentCell.p[5] = new Point3D(X_Right_Back, Y_Top_Back, Z_Back);
currentCell.p[6] = new Point3D(X_Right_Front, Y_Top_Front, Z_Front);
currentCell.p[7] = new Point3D(X_Left_Front, Y_Top_Front, Z_Front);
currentCell.val[] = CTSliceBack[theRowIndex + 1][theColumnIndex];
currentCell.val[] = CTSliceBack[theRowIndex + 1][theColumnIndex + 1];
currentCell.val[] = CTSliceFront[theRowIndex + 1][theColumnIndex + 1];
currentCell.val[] = CTSliceFront[theRowIndex][theColumnIndex];
currentCell.val[] = CTSliceBack[theRowIndex][theColumnIndex + 1];
currentCell.val[] = CTSliceFront[theRowIndex][theColumnIndex + 1];
currentCell.val[] = CTSliceFront[theRowIndex][theColumnIndex];
return currentCell;
}
tôi đã thực hiện điều đó ngay từ stack-Overflow, vì vậy xin vui lòng chỉ ra bất kỳ lỗi chính tả. Đó là làm việc, Điều này dẫn đến một vỏ của một mô hình. Tôi muốn thay thế biến số isolevel
trong hàm Polygonise
với 2 số nguyên: isolevelMin
và isolevelMax
. Không chỉ 1 int
mà còn là một dải ô.
EDIT: Guys, xin vui lòng giúp đỡ. 50 đại diện gần 1/2 danh tiếng của tôi. Tôi hy vọng tôi có thể thay đổi kỳ vọng của mình.Bây giờ tôi chỉ muốn bất kỳ ý tưởng làm thế nào tôi có thể thực hiện những gì tôi muốn, bất kỳ đoạn nào về cách làm điều đó hoặc nếu ai đó đưa ra một số từ khóa mà tôi có thể google mà tôi sử dụng để giải quyết vấn đề của tôi, ông sẽ nhận được đại diện. Tôi chỉ cần một ít ánh sáng - tất cả đều tối ở đây.
chỉnh sửa là tuyệt vời: Sau thậm chí nhiều hơn, nghiên cứu nhiều hơn và nhiều hơn nữa, tôi phát hiện ra rằng các thuật toán ray-diễu hành thể tích không thực sự tạo ra bề mặt. Vì tôi cần in mô hình 3D được tạo ra, tôi chỉ có một lối thoát ngay bây giờ. Tôi phải làm cho thuật toán hình khối diễu hành tạo ra một mô hình rỗng từ các giá trị cách ly tối đa và tối thiểu.
"Sử dụng bool [,,], tôi muốn truy xuất Danh sách trong đó mỗi Point3D [] có độ dài là 3 và biểu thị một hình tam giác trong không gian 3D": 1. Trên một pad pháp lý, viết bằng tay * chính xác * ý của bạn là gì, đoán của bạn chắc chắn là rất tốt hơn tôi. 2. Tinh chỉnh cho đến khi nó trông giống như mã giả. 3. Phần dễ dàng: Dịch thành mã thực. 4. Yêu cầu giúp đỡ nếu borken của nó. –
"Tôi đã thực hiện thuật toán hình khối diễu hành, nhưng nó đơn giản dường như không được tạo ra để chấp nhận" phạm vi "của các giá trị": Khi câu hỏi "không có vẻ", tôi sẽ chết một chút. Thông tin trong câu đó tròn thành 0. Nếu bạn có vấn đề cụ thể trong việc triển khai thuật toán, hãy đăng mã của bạn và nói nó bị đau ở đâu. Nhưng bạn không mô tả vấn đề triển khai cụ thể; bạn đang mô tả trạng thái cảm xúc. Có lẽ ai đó ở đây có thể viết toa thuốc, tôi không biết. Tôi không thể. –
[ở đây] (http://vis.computer.org/vis2004/DVD/vis/papers/nielson2.pdf) là một bài báo có thể giúp nói về cách làm mịn lưới của bạn khi sử dụng thuật toán marching cube –