Coding help

Background info is a bit lengthy to understand the context of code.

This is an equation to a Bi-linear Bezier surface.
Given equation:S = {(P1 (1-u) + P2u) (1-v)} + {(P3 (1-u) + P4u) v}.

This is an equation to represent triangles, Points P1 (2,2,2) for example, and so on, P2, P3 and P4 are coordinate points and are known.
A structure class is created for the coordinate points (‘v3d’ aka 3 dimensional vector).
u and v are scalar quantities which is the input to the equation and S is the output point (a,b,c). The values for u are 0, 0.5 and 1 and for v is 0, 0.5 and 1 as well. So hence there are 9 different cases which would output 9 coordinate points or nine vectors. These nine points are stored in an array, and this array is passed through the function above. The code given below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <math.h>// consider <cmath> instead
#include <iostream>
#include <stdio.h>// not used

using namespace std;

struct v3d
{
    double X, Y, Z, mag;// data members

    // function members
    // no-arg constructor to declare arrays 
    v3d() { X = Y = Z = mag = 0.0; }
    // this constructor assigns values to X, Y, Z then calculates the magnitude
    v3d(double x, double y, double z): X(x), Y(y), Z(z)
    {
        mag = sqrt(X*X + Y*Y + Z*Z);
    }
};

//        Function to calculate dot product
double dotproduct(v3d a, v3d b)
{
    return a.X*b.X + a.Y*b.Y + a.Z*b.Z;
}

//        Function to calcuate cross product
void crossproduct(v3d A, v3d B, v3d &C)
{
    C.X = A.Y * B.Z - A.Z * B.Y;
    C.Y = A.Z * B.X - A.X * B.Z;
    C.Z = A.X * B.Y - A.Y * B.X;
}

//        To calculate the magnitude of a vector
void magnitude(v3d &a)
{
    a.mag = sqrt(dotproduct(a,a));
}

//        To create a normalised vector given two other vectors
void normalise (v3d &v, v3d a, v3d b)
{
    v3d temp( b.X - a.X, b.Y - a.Y, b.Z - a.Z );


    v.X = temp.X/temp.mag;// 
    v.Y = temp.Y/temp.mag;// function for v3d * scalar
    v.Z = temp.Z/temp.mag;
    magnitude(v);
}

void pprint(v3d A)
{
    cout<<A.X<<"\t"<<A.Y<<"\t"<<A.Z<<"\t"<<A.mag<<"\n";
}

//creating the function
void Bezier(v3d P1,v3d P2,v3d P3,v3d P4, v3d Pa[9])
{
    // all components and magnitudes of P1, P2, P3 and P4 were assigned before this function was called
    // assign values to u and v array
    double u[3] = {0.0, 0.5, 1.0 }, v[3] = {0.0, 0.5, 1.0 };

    for(int i=0; i<3; ++i)
        for(int j=0; j<3; ++j)
        {
            Pa[3*i+j].X = (  P1.X*(1-u[i] ) +  P2.X*u[i] )*( 1 - v[j] ) +  (  P3.X*(1-u[i] ) +  P4.X*u[i] )* v[j];
            Pa[3*i+j].Y = (  P1.Y*(1-u[i] ) +  P2.Y*u[i] )*( 1 - v[j] ) +  (  P3.Y*(1-u[i] ) +  P4.Y*u[i] )* v[j];
            Pa[3*i+j].Z = (  P1.Z*(1-u[i] ) +  P2.Z*u[i] )*( 1 - v[j] ) +  (  P3.Z*(1-u[i] ) +  P4.Z*u[i] )* v[j];
            magnitude(Pa[3*i+j]);
            pprint(Pa[3*i+j]);
        }
}

int main ()
{
    // using the new constructor. mag is also calculated
    v3d    P1(2,2,2), P2(12,2,2), P3(3,16,6), P4(13,16,6);
    v3d Pb[9];// uses the no-arg constructor
    Bezier (P1,P2,P3,P4,Pb);


//Triangle 1
 v3d temp1, temp2, temp3, uhat;

//directional vector to create cross product
d(Pb[0], Pb[3], Pb[1], temp1,temp2);

//cross product of two 3d vectors 
crossproduct (temp1,temp2, temp3);
magnitude(temp3);     
	   uhat.X = temp3.X / temp3.mag;
	   uhat.Y = temp3.Y / temp3.mag;
	   uhat.Z = temp3.Z / temp3.mag;
	   magnitude(uhat);
//uhat is the orthogonal vector to the triangular surface.  
cout<<"uhat\n";
pprint(uhat);

//Triangle 2
v3d temp4, temp5, temp6, vhat;
d(S[3], S[4], S[1], temp4,temp5);
crossproduct (temp4,temp5, temp6);
magnitude(temp6);
       vhat.X = temp6.X / temp6.mag;
	   vhat.Y = temp6.Y / temp6.mag;
	   vhat.Z = temp6.Z / temp6.mag;
	   magnitude(vhat);
cout<<"vhat\n";
pprint(vhat);

Triangle 3
v3d temp7, temp8, temp9, what;
d(S[3], S[6], S[4], temp7,temp8);
crossproduct (temp7,temp8, temp9);
magnitude(temp9);
       what.X = temp9.X / temp9.mag;
	   what.Y = temp9.Y / temp9.mag;
	   what.Z = temp9.Z / temp9.mag;
	   magnitude(what);
cout<<"what\n";
pprint(what);

Triangle 4
v3d temp10, temp11, temp12, ahat;
d(S[6], S[7], S[4], temp10,temp11);
crossproduct (temp10,temp11, temp12);
magnitude(temp12);
       ahat.X = temp12.X / temp12.mag;
	   ahat.Y = temp12.Y / temp12.mag;
	   ahat.Z = temp12.Z / temp12.mag;
	   magnitude(ahat);
cout<<"ahat\n";
pprint(ahat);


}
}


Hence as observed in the output the first three columns represent the x,y,z coordinates and the fourth the magnitude of the vector. Hence I can call three corresponding vectors from Pb to create a 3d triangle by the cross product of two vectors.

So to sum up I am calling three corresponding points from this bi-linear bezier surface to create eight 3d triangles.

If you plot the nine coordinate points on a graph you will see eight triangles.

For example I have to call from Pb coordinate points to create 3d triangles(see code above).

//Triangle 1
d(Pb[0] = (2,2,2) , Pb[3] = (7,2,2), Pb[1] = (2.5,9,4)) then cross product
//Triangle 2
d(Pb[3] = (7,2,2) , Pb[4] = (7.5,9,4), Pb[1] = (2.5,9,4))


So on and this in done another 6 times to create eight triangles. My first query is there a method to reduce this repetition of code (The code shows only 4 triangles). Do I have to create a function for this I have no idea or a for loop.

General question:
Is it better to create a class for a triangle?

Will it be better to store the nine vector points Pb in an array class so I can access the array at randomly to create the triangles. Also if I have to access the array at random should I use a vector class (std::vector) to store the nine points.

Last edited on
Always a good idea to create functions for repetitive tasks.

If you plan to build upon this code then it is a good idea to create a class/struct for triangle
Certainly create a Triangle class; I'd even argue you could make a Vector class too. The idea is if you can have something that is well-defined, you can create a cookie cutter class out of it. Once you create a class, you don't have to worry about taking in three points to find two direction vectors which I then find the orthogonal unit vector of. A class will automate and hide the process so all you'll have to worry about is input and output.

I'd make the Vector class too just for clean code.

Picking random elements from a set doesn't depend on whether you use an array or a vector, so in regards to using an array vs a vector, I've always preferred using a fixed-sized array if I know the what its size is always going to be in advance; vectors will grow/shrink based on what's required of them during runtime, so they have a bit of overhead, but if the scope/size of your problem is small, it doesn't matter.
Hey guys,

Hope all is well with you today and thank you for your reply, I understand that all this extra code can be eliminated by creating a class for the triangle. The type of triangles are called .stl triangles and not to be confused with stl(standard template library).

I had a question in creating a class for a .STL traingle . For back ground information I have attached the link, the first two paragraphs and the ASCII STL part is what is relevant.


http://en.wikipedia.org/wiki/STL_%28file_format%29

My question here is, I have to create a class for the representation of the triangle below. Mathematically I understand what to do as I have the functions to create the class from the code above, but I dont know how to relate the given puesdo code from the wiki page and link to my method of creating the triangle.

I understand that a class representation has member functions so does the calculation part go into these member functions of the class?

Am confused how to represent this class in c++. Any suggestions from you will be extremely helpful to me. Thank you once again for you time and if you do not understand anything do let me know.

An example for a code would be perfect.



Your class should be contain (1) the data section relevant to the object and (2) the member functions that modify that data. My loose definition of what should constitute your data section is what values you would like to persist (e.g. if you had to save it in a file, what's the bare minimum you would have to save?). Coincidentally, your problem involves actual files, so the data section is easy: a vector for the normal, and three vectors for the three vertices. Keep them in the private section. Your functions should be thrown in as well just like you said. I'd say keep all the low-level detail functions in the private section (like calculating a directional derivative, finding the norm) and have your high-level functions in the public section (say, maybe a constructor that takes in three verts and creates an object with that way or a bunch of accessor methods).


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//StlTriangle.h
class StlTriangle
{
     public:
          StlTriangle(v3d vert1, v3d vert2, v3d vert3);
          v3d getNorm();
          void print(); //equivalent of pprint()

     private:
          v3d vert1, vert2, vert3, norm;
          //pretty much all the math functions go here if you don't put them in the v3d struct/class
}


//StlTriangle.cpp
StlTriangle::StlTriangle(Vector3 vert1, Vector3 vert2, Vector3 vert3)
{
     //initialize class variables
     //call function to calculate directional vectors
     //call function to calculate cross product, storing the vector in your norm data section
     //convert norm into a unit vector
}


That's just a rough sketch of what the class could be. Probably some things omitted on my part tough.
Topic archived. No new replies allowed.