6

मैंने सी # में मार्चिंग क्यूब्स, दोहरी मार्चिंग क्यूब्स और अनुकूली मार्चिंग क्यूब्स लागू किया है, केवल यह पता लगाने के लिए कि मुझे अपने उद्देश्यों के लिए दोहरी समोच्चता की आवश्यकता है। मैंने दोहरी समोच्चता के बारे में सभी कार्यों को पढ़ा है और मुझे दोहरी समोच्चता के मूल के अलावा सभी मिलते हैं: वर्गबद्ध त्रुटि फ़ंक्शन को कम करना (क्यूईएफ)।दोहरी कंटूरिंग और क्वाड्रैटिक त्रुटि फ़ंक्शन

अभी, मैं आंतरिक वॉक्सेल की ऊर्ध्वाधर स्थिति की गणना कर रहा हूं, केवल एक ही चरम (3 से 6 किनारों) को साझा करने वाले सभी किनारे बिंदुओं के बीच का मतलब ढूंढकर और यह अच्छी तरह से काम करता है, लेकिन यह स्पष्ट रूप से आंतरिक शिखर नहीं बनाता है सही जगहें

यहां कोड का वह टुकड़ा है जिसे मैं बनाने की कोशिश कर रहा हूं। किसी भी मदद की बहुत सराहना की जाएगी

/// <summary> 
    /// ORIGINAL WORK: Dual Contouring of Hermite Data by Tao Ju (remember me of a MechCommander 2 character) 
    /// 2.3 Representing and minimizing QEFs 
    /// The function E[x] can be expressed as the inner 
    /// product (Ax-b)T (Ax-b) where A is a matrix whose rows are the 
    /// normals ni and b is a vector whose entries are ni*pi. <------------ (dot product?)> 
    /// Typically, the quadratic function E[x] is expanded into the form 
    /// E[x] = xT AT Ax - 2xT AT b + bT b (2) 
    /// where the matrix AT A is a symmetric 3x3 matrix, AT b is a column 
    /// vector of length three and bT b is a scalar. The advantage of this expansion 
    /// is that only the matrices AT A, AT b and bT b need be stored 
    /// (10 floats), as opposed to storing the matrices A and b. Furthermore, 
    /// a minimizing value ˆ x for E[x] can be computed by solving 
    /// the normal equations AT Aˆ x = AT b. 
    /// </summary> 
    public Vector3 GetMinimumError(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 n0, Vector3 n1, Vector3 n2) 
    { 
     //so, here we are. I'm creating a vector to store the final value. 
     Vector3 position = Vector3.Zero; 

     //Values of b are supposed to b (:P) three floats. The only way i know to find a float value 
     //by multiplying 2 vectors is to use dot product. 
     Vector3 b = new Vector3(
       Vector3.Dot(p0, n0), 
       Vector3.Dot(p1, n1), 
       Vector3.Dot(p2, n2)); 

     //What the transpose of a vector is supposed to be? 
     //I don't know, but i think should be the vector itself :) 
     float bTb = Vector3.Dot(b, b); 

     //i create a square matrix 3x3, so i can use c# matrix transformation libraries. 
     //i know i will probably have to build bigger matrix later on, but it should fit for now 
     Matrix A = new Matrix(
      n0.X, n0.Y, n0.Z, 0, 
      n1.X, n1.Y, n1.Z, 0, 
      n2.X, n2.Y, n2.Z, 0, 
      0, 0, 0, 0); 

     //easy 
     Matrix AT = Matrix.Transpose(A); 

     //EASY 
     Matrix ATA = Matrix.Multiply(AT, A); 

     //Another intuition. Hope makes sense... 
     Vector3 ATb = Vector3.Transform(b, AT); 

     //... 
     // some cool stuff about solving 
     // the normal equations AT Aˆ x = AT b 
     //... 

     return position; //profit! 
    } 

उत्तर

5

क्यूईएफ को समझना मुश्किल है। उम्मीद है कि मैं मदद कर सकता हूँ। दोहरी contouring विधि प्रत्येक क्रॉसिंग बिंदु पर 'Hermite' डेटा की गणना करता है, या दूसरे शब्दों में, voxel के किनारे पर बनाए गए प्रत्येक बिंदु पर सतह के सामान्य जाना जाता है। एक बिंदु और एक सामान्य के साथ एक विमान के समीकरण की गणना कर सकते हैं।

क्यूईएफ वोक्सेल से जुड़े प्रत्येक विमान के लिए वोक्सेल के आंतरिक बिंदु से दूरी के वर्गों का योग है। क्यूईएफ की गणना के लिए नीचे कुछ छद्म कोड है।

double get_QEF(Point3d point, Voxel3d voxel) 
{ 
    double QEF = 0.0; 
    foreach(plane in voxel.planes) 
    { 
     double dist_to_plane = plane.distance(point); 
     QEF += dist_to_plane*dist_to_plane; 
    } 
    return(QEF); 
} 

लक्ष्य फिर वोक्सेल के अंदर एक बिंदु चुनने के लिए है जो क्यूईएफ को कम करता है। साहित्य इष्टतम बिंदु का पता लगाने के लिए ग्राम-श्मिट प्रक्रिया का उपयोग करने का सुझाव देता है लेकिन यह जटिल हो सकता है और इसके परिणामस्वरूप वोक्सेल के बाहर स्थित बिंदु भी हो सकते हैं।

एक और विकल्प (हैक-आईएसएच) वोक्सेल के अंदर बिंदुओं का ग्रिड बनाना और प्रत्येक के लिए क्यूईएफ की गणना करना और सबसे कम से एक को चुनना है, ग्रिड को इष्टतम बिंदु के करीब जितना बेहतर होगा लेकिन लंबी गणना।

1

दोहरी समोच्चता के अपने वर्तमान कार्यान्वयन में क्यूईएफ को हल करने के लिए एक बहुत ही सरल तरीका का उपयोग कर रहा हूं। चूंकि संक्षेप में क्यूईएफ कम से कम वर्ग अनुमान है, इसलिए मुझे क्यूईएफ की गणना करने का सबसे आसान तरीका स्यूडोइनवर्स की गणना करके पाया गया है। इस छद्म संकेतक की गणना आपकी भाषा में किसी भी बीजगणितीय पुस्तकालय का उपयोग करके की जा सकती है।

इस कोड मैं का उपयोग कर रहा है:

public static Vector<float> CalculateCubeQEF(Vector3[] normals, Vector3[] positions, Vector3 meanPoint) 
    { 
     var A = DenseMatrix.OfRowArrays(normals.Select(e => new[] { e.X, e.Y, e.Z }).ToArray()); 
     var b = DenseVector.OfArray(normals.Zip(positions.Select(p => p - meanPoint), Vector3.Dot).ToArray()); 

     var pseudo = PseudoInverse(A); 
     var leastsquares = pseudo.Multiply(b); 

     return leastsquares + DenseVector.OfArray(new[] { meanPoint.X, meanPoint.Y, meanPoint.Z }); 
    } 

समारोह के आदानों चौराहे अंक और normals हैं, और meanPoint अंक intersectoin दिया की औसत है।

गणित का सारांश: यह फ़ंक्शन उस बिंदु की गणना करता है जो चौराहे बिंदुओं और मानदंडों द्वारा परिभाषित सभी विमानों के चौराहे पर स्थित है। चूंकि इसका कोई सटीक समाधान नहीं है, कम से कम वर्ग अनुमानों की गणना की जाती है, जो उस बिंदु को पाता है जो 'कम से कम गलत' है। इसके अतिरिक्त, चौराहे बिंदु 'स्थानांतरित' होते हैं ताकि माध्य बिंदु मूल हो जाए। यह सुनिश्चित करता है कि क्यूईएफ के कई समाधान होने पर, औसत बिंदु के निकटतम समाधान चुना जाता है।

संबंधित मुद्दे