public Face(int[] v, Vec3D normal, double area) { vertices = v; numberOfVertices = v.Length; this.normal = normal; this.area = area; }
/// <summary> /// Write a pointcloud for a vector array in txt format /// </summary> /// <param name="points"></param> /// <param name="filename"></param> internal static void WritePointCloudTxt(Vec3D[] points, string filename) { StreamWriter sw = new StreamWriter(filename + ".txt"); foreach (Vec3D v in points) { sw.WriteLine(v.x + " " + v.y + " " + v.z); } sw.Close(); }
//parse een SOF file public static Model3D parseSofModel(string path, string sourcepath) { StreamReader sr = new StreamReader(path); string line; int vertices, faces; vertices = System.Convert.ToInt32(sr.ReadLine()); faces = System.Convert.ToInt32(sr.ReadLine()); Vec3D[] v = new Vec3D[vertices]; ArrayList f = new ArrayList(); for (int i = 0; i < vertices; i++) //possibly more than one whitespace inbetween, use Scanner? { line = sr.ReadLine(); string[] items = line.Split(' '); try { v[i] = new Vec3D(System.Convert.ToDouble(items[0]), System.Convert.ToDouble(items[1]), System.Convert.ToDouble(items[2])); } catch(FormatException) { return null; } } for (int i = 0; i < faces; i++) //possibly more than one whitespace inbetween, use Scanner? { line = sr.ReadLine(); string[] items = line.Split(' '); int aantal = System.Convert.ToInt32(items[0]); int[] vIndex = new int[aantal]; for (int z = 1; z <= aantal; z++) { vIndex[z - 1] = System.Convert.ToInt32(items[z]); } //Assumption of a polygon lying on a plane, would be hard otherwise, an average over the normals on the surface spline. Vec3D a, b, c; a = v[vIndex[0]]; b = v[vIndex[1]]; c = v[vIndex[2]]; Vec3D normal = (b.subtract(a)).cross(c.subtract(a)); ArrayList temp = Triangulate(ref v, new Face(vIndex, normal,0)); foreach (Face face in temp) f.Add(face); } sr.Close(); Face[] f2 = (Face[])f.ToArray(typeof(Face)); return new Model3D(v, f2, sourcepath); }
static ArrayList Triangulate(ref Vec3D[] v, Face f) { //verdeel Face f in meerdere kleine faces van 3 vertices //Er wordt vanuit gegaan dat een face meer dan drie vertices heeft als deze in deze methode komt. //en geef deze in een arraylist terug, MOGELIJK in een array. //BEGIN Naive/Simple implementation, ONLY works on convex polygons. ArrayList q = new ArrayList(); for (int i = 1; i < f.numberOfVertices - 1; i++) { int[] verts = new int[3]; verts[0] = f.vertices[0]; verts[1] = f.vertices[i]; verts[2] = f.vertices[i + 1]; Vec3D a, b, c; a = v[verts[0]]; b = v[verts[1]]; c = v[verts[2]]; Vec3D norm = (b.subtract(a)).cross(c.subtract(a)); double area = 0.5 * System.Math.Abs((c.subtract(a).cross(b.subtract(a)).length())); q.Add(new Face(verts, norm,area)); } return q; //END Naive/Simple implementation }
public unitVector(double phi, double theta, int a, int b, Vec3D v) { this.phi = phi; this.theta = theta; this.a = a; this.b = b; vector = v; }
public Vec3D subtract(Vec3D v) { return new Vec3D(x - v.x, y - v.y, z - v.z); }
public void sub(Vec3D v) { this.x -= v.x; this.y -= v.y; this.z -= v.z; }
public bool Equals(Vec3D v) { // If parameter is null return false: if ((object)v == null) { return false; } // Return true if the fields match: return (x == v.x) && (y == v.y) && (z == v.z); }
public double dot(Vec3D v) { return x * v.x + y * v.y + z * v.z; }
public Vec3D cross(Vec3D v) { return new Vec3D(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); }
public Vec3D addition(Vec3D v) { return new Vec3D(this.x + v.x, this.y + v.y, this.z + v.z); }
public void add(Vec3D v) { this.x += v.x; this.y += v.y; this.z += v.z; }
public static double[] SFFT(double[] data, unitVector[] ds) { //B^2 complex coefficients Flm in the range 0 (<= |m| <= l <= B) //extract the descriptor for k! the paper says 29 is good, or use the rotation invariant feature vector double[] rcoeffs = new double[B * B]; //(double*)malloc(sizeof(double) * (bw * bw)); double[] icoeffs = new double[B * B]; //(double*)malloc(sizeof(double) * (bw * bw)); double[] rdata = data; //(double*)malloc(sizeof(double) * (size * size)); double[] idata = new double[4 * B * B]; //(double*)malloc(sizeof(double) * (size * size)); double[] rdata2 = new double[4 * B * B]; //(double*)malloc(sizeof(double) * (size * size)); double[] idata2 = new double[4 * B * B]; //(double*)malloc(sizeof(double) * (size * size)); //idata = 0.0 for (int i = 0; i < idata.Length; i++) { idata[i] = 0.0; } Console.WriteLine("Starting SFFT"); DateTime startTime1 = DateTime.Now; try { calcCoeff(B, B, rdata, idata, rcoeffs, icoeffs); //if you wanna compute the real model again inverseTransform(B, B, rcoeffs, icoeffs, rdata2, idata2); } catch (DllNotFoundException e) { Console.WriteLine(e.StackTrace + "\n"); Console.WriteLine("DLL not found."); Application.Exit(); } //if you wanna compute the real model again Vec3D[] points = new Vec3D[4*B*B]; for (int i = 0; i < rdata2.Length; i++) { int b = i % B2; int a = (i / B2); points[i] = ds[B2*b+a].vector.times(rdata2[i]); } Random test = new Random(); FileWriter.WritePointCloudObj(points, "pointcloud" + test.Next(100)); DateTime stopTime1 = DateTime.Now; TimeSpan duration1 = stopTime1 - startTime1; Console.WriteLine("SFFT duration: {0}", duration1.TotalSeconds); Console.WriteLine("Done SFFT"); double[] fv = new double[B]; /* int k = 29; double[] fv2 = new double[k * (k + 1) / 2 + 1]; int total = 0; for (int l = 0; l < k; l++) { for (int m = 0; m < l; m++) { int index = getCoeffIndex(m, l); double mag = System.Math.Sqrt(rcoeffs[index] * rcoeffs[index] + icoeffs[index] * icoeffs[index]); if(m == 0) { fv2[total] = mag/2; total++; } else { fv2[total] = mag; total++; } } } return fv2; */ for (int l = 0; l < B; l++) { double result = 0; for (int m = 0 - l; m <= l; m++) { int index = getCoeffIndex(m, l); result += rcoeffs[index] * rcoeffs[index] + icoeffs[index] * icoeffs[index]; } fv[l] = System.Math.Sqrt(result); } return fv; }
static double[] getMinMaxPhiTheta(ref Face f, ref Vec3D[] v, ref Model3D model) { /* int minPhi = phiTheta[0]; int minTheta = phiTheta[1]; int maxPhi = phiTheta[2]; int maxTheta = phiTheta[3]; */ double[] minmax = new double[4]; minmax[0] = double.MaxValue; minmax[1] = double.MaxValue; minmax[2] = double.MinValue; minmax[3] = double.MinValue; double minX = double.MaxValue, maxX = double.MinValue, minY = double.MaxValue, maxY = double.MinValue, minZ = double.MaxValue, maxZ = double.MinValue, meanX = 0, meanY = 0, meanZ = 0; for(int k=0; k < f.numberOfVertices; k++) { Vec3D vec = v[f.vertices[k]]; updateMinMaxMeanXYZ(ref minX,ref maxX,ref meanX,vec.x,ref minY,ref maxY,ref meanY,vec.y,ref minZ,ref maxZ,ref meanZ,vec.z,k); double phi, theta; phi = System.Math.Atan2(vec.y, vec.x); theta = System.Math.Acos((vec.z) / (vec.length())); if (minmax[0] > phi) minmax[0] = phi; if (minmax[1] > theta) minmax[1] = theta; if (minmax[2] < phi) minmax[2] = phi; if (minmax[3] < theta) minmax[3] = theta; } /* //Because of the possibility of an polygon lying on all equal or close theta, the correct theta may not be found with only the points. //Trying to solve this here. Vec3D dotPoint = new Vec3D(double.NaN,double.NaN,double.NaN); double dotDist = double.MaxValue; for (int k = 0; k < f2.numberOfVertices; k++) { Vec3D a, b, edge; a = v[f.vertices[k]].copy().normalize(); b = v[f.vertices[(k + 1) % f.numberOfVertices]].copy().normalize(); edge = a.subtract(b).normalize(); double dotO = b.dot(edge); if (dotO < 0.0) { Vec3D tempPoint = b.addition(edge.times(dotO)); double tempDist = tempPoint.squaredLength(); if (dotDist > tempDist) { dotDist = tempDist; dotPoint = tempPoint; } } } minmax[3] = System.Math.Acos((dotPoint.z) / (dotPoint.length())); */ //Check om te bepalen of de polygon in het xy vlak (z is up), //zo ja, check of erboven of eronder is en pas theta aan om volledig door te lopen. if (minX < 0 && maxX > 0 && minY < 0 && maxY > 0) if (meanZ > 0) minmax[1] = 0; else minmax[3] = System.Math.PI; return minmax; }