Если кто-то заботится, я использую WPF ....Как я мог polygonise логическое значение [,,]
Начало истории:
Я получил ряд полутоновых изображений (фрагменты модели). Пользователь вводит «диапазон» значений шкалы серого для построения 3D-модели. Таким образом, я создал массив 3D bool
, чтобы упростить сборку 3D-модели. Этот массив представляет собой поле с пикселями, указывающее, должен ли каждый пиксель быть создан/сгенерирован/заполнен или нет.
Галстук:
Использование bool[,,]
, я хочу, чтобы извлечь List<Point3D[]>
где каждый Point3D[]
имеет длину 3 и представляет собой треугольник в 3D-пространстве.
Дополнительная информация:
Сформированная модель будет 3D распечатаны. В bool[,,]
true
указывает на наличие вещества, а false
указывает на отсутствие вещества. Мне нужно избегать кубических моделей, где каждый пиксель заменяется кубом (это было бы бесполезно в соответствии с моей целью). Модель должна быть максимально гладкой и максимально точной.
То, что я пытался сделать:
1- я реализовал алгоритм марширующих кубов, но это просто, кажется, не будет создан, чтобы принять «диапазон» значений.
2- Я продолжал бороться в течение нескольких дней, пытаясь сделать свой собственный алгоритм, но я частично провалился. (Это реальная сложная Если вы хотите узнать больше об этом, пожалуйста, сообщите.)
Некоторые ожидаемые решения, которые я не имею ни малейшего представления о том, как реализовать:
1- изменить алгоритм Маршевые кубов для того, чтобы заставить его работать, используя
bool[,,]
2- Изменить алгоритм Маршевые кубов для того, чтобы заставить его работать, используя работу, используя «диапазон» isolevel
значений
3- Показывает, как реализовать другой алгоритм, подходящий для моей цели (возможно, алгоритм Ray-Casting) в WPF.
4 Запрос источника сигнала, который я попытался реализовать, показывая мне, как его решить.
(Это было сделано для полигонаж bool[,,]
)
5 Некоторые другие магические решения.
Заранее спасибо.
EDIT:
Говоря
Использование
bool[,,]
, я хочу, чтобы извлечьList<Point3D[]>
где каждыйPoint3D[]
имеет длину 3 и представляет собой треугольник в 3D-пространстве.
Я имею в виду, что хочу получить группу треугольников. Каждый треугольник должен быть представлен как 3 Point3D
s. Если вы не знаете, что такое Point3D
, это struct
, содержащий 3 двухместных (X, Y и Z), которые используются для представления позиции в трехмерном пространстве.
Проблема с алгоритмом маршевых кубов заключается в том, что это смутно. Я имею в виду, что вы понимаете, делая это?
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;
Таким образом, я просто понятия не имею, с чего начать его модифицировать.
Другой EDIT:
После нескольких экспериментов с использованием алгоритма марширующих кубов, я заметил, что polygonising в bool[,,]
не будет приводить к гладкой 3D модели, я с нетерпением жду, так что мой первое ожидаемое решение, и мое четвертое ожидаемое решение вышло из игры. После многих исследований я узнал о методе рендеринга Ray-Casting. Кажется, это здорово, но я не уверен, подходит ли он для моих нужд. Я не могу понять, как это реализовано, хотя я знаю как это работает.
Еще один EDIT: TriTable.LookupTable
и EdgeTable.LookupTable
являются таблицы представляют here
Вот 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);
}
}
}
Вот GridCell
класс:
public class GridCell
{
public Point3D[] p = new Point3D[8];
public Int32[] val = new Int32[8];
}
Хорошо, это то, что я делаю:
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;
}
Я сделал это прямо из стека при переполнении, поэтому, пожалуйста, указать на опечатки. Это работает. В результате получается оболочка модели. Я хочу сделать замену переменной isolevel
в функции Polygonise
с 2 целыми числами: isolevelMin
и isolevelMax
. Не только 1 int
, но и диапазон.
EDIT: Ребята, пожалуйста, помогите. 50 репутации почти 1/2 моей репутации. Надеюсь, я смогу изменить свои ожидания.Теперь я просто хочу понять, как я могу реализовать то, что я хочу, любой фрагмент, как это сделать, или если кто-то выдаст некоторые ключевые слова, которые я могу использовать для Google, которые я использовал для решения моей проблемы, он получит репутацию. Мне просто нужно немного света - здесь все темно.
редактирует являются удивительными: После даже больше, больше и гораздо больше исследований, я обнаружил, что алгоритм мерной луч-маршевый фактически не генерировать поверхности. Поскольку мне нужно распечатать созданную 3D-модель, у меня есть только один выход. Я должен сделать алгоритм маршевых кубов, создавая полую модель из максимальных и минимальных значений изолесте.
«Использование bool [,,], я хочу получить список, где каждый Point3D [] имеет длину 3 и представляет треугольник в трехмерном пространстве»: 1. На юридической панели выпишите в longhand * точно, что вы подразумеваете под этим, ваше предположение, безусловно, намного лучше, чем мое. 2. Уточните это, пока оно не будет выглядеть как псевдокод. 3. Простая часть: переведите это в реальный код. 4. Попросите помощи, если его борен. –
«Я реализовал алгоритм маршевых кубов, но он просто не создается, чтобы принять« диапазон »значений». Когда вопрос говорит «не кажется», я немного умираю. Информация в этом предложении раундов равна нулю. Если у вас есть конкретная проблема с внедрением алгоритма, отправьте свой код и скажите, где он болит. Но вы не описываете конкретную проблему реализации; вы описываете эмоциональное состояние. Может быть, кто-то здесь может написать рецепты, я не знаю. Я не могу. –
[здесь] (http://vis.computer.org/vis2004/DVD/vis/papers/nielson2.pdf) - это документ, который может помочь в этом поговорить о том, как сгладить вашу сетку при использовании алгоритма маршевого куба. –