Author Topic: Simple Programming, Calculus, and Geometry  (Read 5664 times)

0 Members and 1 Guest are viewing this topic.

Offline Thaeris

  • Can take his lumps
  • 211
  • Away in Limbo
Simple Programming, Calculus, and Geometry
It's the first time I've whipped out C++ for a while, and because I don't care that much at this point, I've still got VSE 2008. It's not that I don't care, it's just that a newer version of VSE won't do all that much for what amouts to a script-writing program, operated from the console window.

As some of you may be more aware than you'd like, I've been haunting the #scp channel for tips and, frankly, slightly excessive tips on optimizations. And that madness is important to me, because I am clearly insane...

I'll post the program a little later, but I'd like to talk about some geometry, because the program is designed to parse geometric coordinates. First, I want you to re-envision that assumedly dreaded unit circle from high school and freshman/sophmore calculus. 1.5 pi, or 270 degrees is normally on the bottom. But, to enable the program to work how I want it to, it was necessary to shift 0 pi/ 2 pi ( 0 or 360 degrees) from its usual position to where the 270 degree position is normally located. This alters calculations only slightly - the progression of degrees is still the same counter-clockwise direction. This time, however, theta starts at 0 * pi at the bottom and goes up to pi at the top (normally the pi/2 position). For a circle, the coordinates become as follows:

x = r*sin(theta)
y = -r*cos(theta)

Note that an ellipse is virtually the same as a circle in normal manipulations. In a circle the height and width are the same, so a = b = r. In an ellipse, these scale factors are independent. With the conventions being the same as described in the previous paragraph, elliptical coordinates become:

x = a*sin(theta)
y = -b*cos(theta)

Parametric equations are wonderful, and when you enter them into the derivative formulas of a circle or ellipse, you can find the slopes and equivalent measures of theta where the tangency between an ellipse and circle exist. Which brings me to the first question you probably had - what am I coding?

I'm writing a code that can spit out ordered groups of (z, x, y) coordinates for a program called FreeShip, that some of you may recall me mentioning in the past. FreeShip is not a really great general usage program for evreyday modeling. But it does have some really great features that are nothing to scoff at. Being able to take in coordinates from a text file and wrap geometry around them is pretty impressive. And when I get tired of trying to do sweeping mechanical - organic (or even just organic) shapes by hand in a conventional modeling program, FreeShip is a nice tool to have.

However, circular shapes are not hard to model, so why am I bothering to write a script-parsing code and use an obscure, specialized modeling program to do this? Ellipses. Ellipses are not hard to model, either... but they become a challenge when you don't want to manually ensure that all of your modeled surfaces are planar; they become a hellish challenge if you DO want to ensure that all the surfaces are perfectly flat. FreeShip, it turns out, is really good at fitting given geometry with flat, planar surfaces in orderly edge-loops. I also tried doing the former (modeling by hand) - in a way, TWO TIMES PRIOR. Additional abuse to self is obviously still being incurred. Just in a different way this time. :p

The current issue I'm dealing with are the limits of an ellipse for a given width at a given tangent line. It turns out my previous musings on the limits are not quite right:

Code: [Select]
(a.) A point in space may exist between two limits if the limits are along the same 1-dimensional
plane, or if parameters for lateral movement are defined. This problem is set up only to consider the former. Limits are established by
the elevation of the point of tangency and the intercept of the slope of the tangent line on the y-axis. First, the locations of the
limits must be known. For the y-intercept, y = m*x + b. y = -r * cos(t), m = tan(t), x = r * sin(t). This is then:
-r*cos(t) = r*tan(t)*sin(t) + b. This becomes: -r*cos(t) - r*tan(t)*sin(t) = b. Then, -r * (cos(t) + tan(t)*sin(t)) = b. Note that
cos(t) + tan(t)*sin(t) = sec(t). Because secant is not an available function in <cmath>, sec(t) = 1/cos(t). Thus, the y-intercept is
b = -r/cos(t). The elevation of the point of tangency is simply equal to y, or -r * cos(t) at the specified measure of theta.

Again note the height factor b and width factor a. If we divide b by a, we can get a proportional factor k. However, it seems that for a given slope m, which exists at a specific value of theta on the established interval (0 to pi), the width (dx) between the x-axis and the point of tangency (of the slope line) and height (dy) between the ellipse's apex and the y-coordinate of the point of tangency reach a proportional limit even as k approaches infinity. Because that's a mouth-full, have some equations:

The normal derivative of an ellipse: (-b^2 * x) / (a^2 * y) = m; Once we use our parametric equations: (b * sin(theta)) / (a * cos(theta)) = m.
This reduces to: k * tan(theta) = m

Because m is set to a given value for a test (in my case, this is -2.07; the negative number is because the slope, looking at the front of the shape's graph slopes downward). The proportional factor k is known to approach infinity. We re-write the equation as:

theta = arctan(m/k) + pi; we add pi to have a representative measure of theta with respect to our coordinate conventions. That said, the limit of theta seems to be pi, and I think most anyone can see that as true.

Reverting back to k, note that we are only ever make k larger than 1. As such, we may assume a = 1, and k thus equals b. With this information in mind...

x = dx = a * sin(theta); we may use any calculated value of theta we have derived from the tests prior. We simplify this as: dx = sin(theta)

y = -b * cos(theta); b = k; y = -k * cos(theta)

dy = b - y; b = k; dy = k + (k*cos(theta)). Simplified, dy = k * (1 + cos(theta))

The proportionality between the width and the height can be written as dy/dx. For my case where the slope = -2.07, as k approaches infinity, the proportionality seems to approach 1.035 for dy/dx. I still have yet to write a formal equation for this limit, but it's quite interesting with respect to the fact that this may very well be what's breaking my program. After all, my program relies on a relation I whipped up that uses that height dy and width dx to figure out the dimensions and location of a tangent ellipse to a circle. So, it's kind of a big deal. :p

If anyone finds this sort of mathematical nonsense interesting, I'll be happy to post more of it when I find the time.
"trolls are clearly social rejects and therefore should be isolated from society, or perhaps impaled."

-Nuke



"Look on the bright side, how many release dates have been given for Doomsday, and it still isn't out yet.

It's the Duke Nukem Forever of prophecies..."


"Jesus saves.

Everyone else takes normal damage.
"

-Flipside

"pirating software is a lesser evil than stealing but its still evil. but since i pride myself for being evil, almost anything is fair game."


"i never understood why women get the creeps so ****ing easily. i mean most serial killers act perfectly normal, until they kill you."


-Nuke

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: Simple Programming, Calculus, and Geometry
the thing i like about programming is that i learned how to do calculus without knowing that i learned how to do calculus. one day i was curious and looked it up and i was like, i already know how to do that. thats around the time i figured out that education is a scam.
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 

Offline Thaeris

  • Can take his lumps
  • 211
  • Away in Limbo
Re: Simple Programming, Calculus, and Geometry
Education is hardly a scam. Most need a teacher and a motive, and there are the gifted few we all envy which do not.

:)
"trolls are clearly social rejects and therefore should be isolated from society, or perhaps impaled."

-Nuke



"Look on the bright side, how many release dates have been given for Doomsday, and it still isn't out yet.

It's the Duke Nukem Forever of prophecies..."


"Jesus saves.

Everyone else takes normal damage.
"

-Flipside

"pirating software is a lesser evil than stealing but its still evil. but since i pride myself for being evil, almost anything is fair game."


"i never understood why women get the creeps so ****ing easily. i mean most serial killers act perfectly normal, until they kill you."


-Nuke

 

Offline z64555

  • 210
  • Self-proclaimed controls expert
    • Minecraft
    • Steam
Re: Simple Programming, Calculus, and Geometry
Thearis, your getting ahead of yourself again...

What do the circle and ellipse represent?

What do you mean by "limits of an ellipse for a given width at a given tangent line?"

   Width of what, the ellipse's line thickness, the ellipse's maximum radius along the X axis, or the width of the tangent line?
Secure the Source, Contain the Code, Protect the Project
chief1983

------------
funtapaz: Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Juche.
z64555: s/J/Do
BotenAlfred: <funtapaz> Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Douche.

 

Offline Thaeris

  • Can take his lumps
  • 211
  • Away in Limbo
Re: Simple Programming, Calculus, and Geometry
I'm not getting ahead of myself, man. You just don't know. :p

In any sense the parsing code prototype is... kind of working. Mathematically and procedurally, I think it's right, but the output disagrees. I also have no idea why the first line is printed twice... madness!

Without further ado, here is the code, still in prototype stage. The factors on input as noted in the first post are still wholly there:

Code: [Select]
// HullForm.cpp : Defines the entry point for the console application. This is HullForm I.
// This is a geometry parsing program designed to output files to FreeShip.

#include "stdafx.h"
#include <iostream>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
using namespace std;


int main()
{
/* This code may be expandable, but is at the moment only designed for use with a specific-case application. This case is that of the Blohm
und Voss P.212.03 fighter project, where the lower section of the hull is circular, while the upper section is elliptical. The program will
write a text file readable by the program "FreeShip," which will then output actual geometry usable by other software applications. This
version of the software is only reliable for producing fuselage sections as described above. */

// DECLARAION OF VARIABLES

int count; // This is a general purpose interger counter and selector variable.
int stations; // This is the number of hull sections to be parsed. This number must be at least 2.
int verts; // This is the number of verticies drawn at each hull station. 8 is the minimum number for a proper curve; 40+ are ideal.
double apex; // This is the highest point of an elliptical section of the hull.
double angle; // This is the radial angle n * pi that spaces the distance between each coordinate.
double a; // This is the width of an ellipse. This is datafield[ (5 + count) ].
double b; // This is the height of the ellipse. This is datafield[ (4 + count) ].
double radius; // This is the radius of a circular section of a hull. This is datafield[ (2 + radius) ].
double dx; // This is used as a temporary variable, and then as a proper variable in finding the center point of an elliptic section.
double dy; // This is used as a temporary variable, and then as a proper variable in finding the center point of an elliptic section.
double center; // This is the center coordinate of a circular section. This is datafield[ (1 + count) ].
double m; // This is the tangent slope where circular and elliptical sections of the fuselage meet.
double pi = 3.141592654; // Pi to nine decimal points. Whoo-Hoo!
double tangent; // This is the uniform point on the circular hull section with respect to theta that the elliptic section begins.
double tanEQ; // This is the equivalent measure of theta on the ellipse where both it and the circle are tangent; datafield[ (6 + count) ].
string extension = ".txt"; // This is the file type which is produced by running this code.
vector<double> datafield; // This is a one-dimensional database which the parser reads through to plot geometry.
/* OTHER DECLARATIONS:
(I.) datafield[ count ] is the z-coordinate of a station.
(II.) datafield[ (3 + count) ] is the center coordinate of the section's elliptical geometry. */

// CODE EXECUTION: INITIAL PARAMETERS

// Section Details: Determine number of stations.
cout << "Enter the total number of fuselage stations. This number must be at least equal to two.\n\n";
cin >> stations; // This is a number used to determine the number of entries listed in the data vector.
while (stations < 2)
{
cout << "\nEnter the total number of fuselage stations. This number must be at least equal to two.\n\n";
cin >> stations;
}
stations = stations * 7; // Simplifies data input and computation. There are seven data entries per station.
datafield.resize( stations, 0 ); // Initializes the data vector, all values at zero.
/* Notes on section calculations: (a.) Clearly, there's not much calculation here. However, multiplying the number of stations by a numeric
constant, in this case 7, allows a proper number of data entries to be entered for each station. */

// Section Details: Data gathering for plotting behavior. Input station vertex count here.
cout << "\nEnter the total number of verticies to be drawn at each station. This number\n"
<< "must be at least equal to eight. The program will also force this number to be\n"
<< "even, rounding down.\n\n";
cin >> verts; // Number remains constant for entire program.
while (verts < 8)
{
cout << "\nEnter the total number of verticies to be drawn at each station. This number\n"
<< "must be at least equal to eight. The program will also force this number to be\n"
<< "even, rounding down.\n\n";
cin >> verts;
}
verts = verts - (verts % 2); // Operation ensures number of verticies is even.

// Section Details: Data gathering for circle-ellipse tangency processing. This is the tangent angle or slope.
cout << "\nSelect the point of tangency for the elliptic section with the circular section."
<< "You may use a measure of theta or a slope.\n\n";
cout << "To use a measure of theta, press 0. Theta is measured from the bottom of the\n"
<< "circle (zero) to the top, which is 1 * pi.\n\n";
cout << "To use a slope, press 1. A slope is negative on the top surface of the circle\n"
<< "and positive on the lower surface of the circle.\n\n";
cin >> count; // Here count is used as a selector. Alhough an int, decimals strangely seem to break the code...
while (count < 0 || count > 1)
{
cout << "\nTo use a measure of theta, press 0. Theta is measured from the bottom of the\n"
<< "circle (zero) to the top, which is 1 * pi.\n\n";
cout << "To use a slope, press 1. A slope is negative on the top surface of the circle\n"
<< "and positive on the lower surface of the circle.\n\n";
cin >> count;
}
if (count == 0)
{
cout << "\nEnter the value of theta where the circular and elliptical sections are\n"
<< "tangent. Select a value between 0 and 1.\n\n";
cin >> tangent;
while (tangent < 0 || tangent > 1)
{
cout << "\nEnter the value of theta where the circular and elliptical sections are\n"
<< "tangent. Select a value between 0 and 1.\n\n";
cin >> tangent;
}
m = tan(tangent * pi); // An error exists when a slope is vertical/infinite (division by zero). 0.5 * pi is to be avoided...
}
else
{
cout << "\nEnter the slope of the tangent line where circular and elliptical fuselage\n"
<< "sections meet. Values are all real numbers.\n\n"; // At the moment, that is blatantly a lie...
cin >> m; // Behavior at positive values is not an issue for the current project, but presents an instability to be adressed later.
if (m <= 0)
{
tangent = (atan(m)/pi) + 1; // The code currently cannot handle vertical or infinite slopes, or tangents at zero pi.
}
else
{
tangent = (atan(m)/pi); // The code currently cannot handle vertical or infinite slopes, or tangents at zero pi.
}
}
/* Notes on section calculations: (a.) Slope m for traditional circles and ellipses is the derivative of the function
(b^2 * x^2) + (a^2 * y^2) = a^2 * b^2, which can be written as (-b^2 * x) / (a^2 * y). Note that in a circle, a = b = r.
For traditional parametric calculations, x = a * cos(t), and y = b * sin(t), where t = theta = n * pi, where n is any
real number. The derivative thus reduces to (-b * cos(t)) / (a * sin(t)). If it is not already apparent, "b" is the
height of the ellipse or circle, while "a" is the width. Due to the shift in theta 90 degrees (0.25 * pi) clockwise for
computational reasons, the functions must be re-written to reflect the values to be used. Thus, x = a * sin(t), and
y = -b * cos(t), as 0 * pi starts at the bottom of the fuselage and moves counter-clockwise upwards. Re-writing the
equation of the derivative thus yields m = (b * sin(t)) / (a * cos(t)). This simply then reduces to m = (b/a) * tan(t).
A constant k can be defined as b / a, and is a useful quantity. However, this ratio is not needed in this code development
as only the tangent at the circular section is of interest in computations. (b.) The measure of theta determined in the else
statement is achieved through a reverse process of determining the slope of the tangent line as demonstrated in prior statments.

(c.) Revision notes: Code needs to be break-proof and all-aspect! Consider omitting variable m in the future. */

// CODE EXECUTION: FINE DATA ENTRY

cout << "\nThe following section requires precise data entry. Errors will necessitate re-\nrunning the program.\n\n";

for (count = 0; count < stations; count = count + 7) // Uses count to cycle through vector entries whilst collecting information.
{
// Section Details: Assignment of given station's z-coordinate.
cout << "\nEnter the z-coordinate of the number #" << ((count/7) + 1) << " station.\n\n"; // Modifies the count to show station number.
cin >> datafield[ count ]; // Write z-value of station directly to the vector field.

// Section Details: Assignment of station's circular section center point in the y-axis.
cout << "\nEnter the y-coordinate of the number #" << ((count/7) + 1) << " station's circular centerpoint.\n\n";
cin >> center;
datafield[ (1 + count) ] = center; // Writes circular center point of station to the vector field.

// Section Details: Input of circular section radius for a given station.
cout << "\nEnter the radius of the circular section. The radius must be greater than 0.\n\n";
cin >> radius;
while (radius <= 0)
{
cout << "\nEnter the radius of the circular section. The radius must be greater than 0.\n\n";
cin >> radius;
}
datafield[ (2 + count) ] = radius; // Writes circular section radius to vector field.

// Section Details: Section apex entry and input check.
dx = (-0.5*radius) * ((1/cos(tangent * pi)) + cos(tangent * pi)); // Temporary reassignment of variable as centroid of limit region.
dy = (abs((radius * (cos(tangent * pi) - (1/cos(tangent * pi))))))/2; // Temporary reassignment of variable as radius of limit region.
cout << "\nEnter the height of the section apex. This coordinate must be between the point\n"
<< "of tangency between circular and elliptical sections and the y-intercept of the\n"
<< "tangent line.\n\n";
cout << "The limits for placing the apex are between " << dx + center + dy << " and " << dx + center - dy << "\n\n";
cin >> apex;
while ( (apex >= (dx + center + dy)) || (apex <= (dx + center - dy)) )
{
cout << "\nEnter the height of the section apex. This coordinate must be between the point\n"
<< "of tangency between circular and elliptical sections and the y-intercept of the\n"
<< "tangent line.\n\n";
cin >> apex;
}
/* Notes on section calculations: (a.) A point in space may exist between two limits if the limits are along the same 1-dimensional
plane, or if parameters for lateral movement are defined. This problem is set up only to consider the former. Limits are established by
the elevation of the point of tangency and the intercept of the slope of the tangent line on the y-axis. First, the locations of the
limits must be known. For the y-intercept, y = m*x + b. y = -r * cos(t), m = tan(t), x = r * sin(t). This is then:
-r*cos(t) = r*tan(t)*sin(t) + b. This becomes: -r*cos(t) - r*tan(t)*sin(t) = b. Then, -r * (cos(t) + tan(t)*sin(t)) = b. Note that
cos(t) + tan(t)*sin(t) = sec(t). Because secant is not an available function in <cmath>, sec(t) = 1/cos(t). Thus, the y-intercept is
b = -r/cos(t). The elevation of the point of tangency is simply equal to y, or -r * cos(t) at the specified measure of theta.

(b.) Terms must be combined and simplified for proper operation and clean implementation of algorithms. If the centroid or average
coordinate of the limit region is known, and the radius, or half of the distance between the coordinates is known, then the algorithm
"limit 1 > point > limit 2" can be implemented. Because the limits are of equal weight in importance, their order in the algorithm is of
no real concern, so long and the program properly recognizes of the points in relation to the coordinate to be entered into memory. The
average coordinate location, y-bar = ((m_1 * x_1) + (m_2 * x_2))/(m_1 + m_2). Because weights "m" are equal, m_1 = m_2, and the equation
becomes an arithmetic mean, y-bar = (x_1 + x_2)/2. The distance between two points is: d = ((x_1-x_2)^2)^0.5. Dividing this number by 2
delivers a radius: d_rad = (((x_1-x_2)^2)^0.5)/2. When combining terms from the first section, the following relations are derived:

y-bar = (-r/2)*((1/cos(t)) + cos(t)) (+ center coordinate of circular section)
d_rad = (((r * (cos(t) - (1/cos(t))))^2)^0.5)/2 (This looks much better on paper with proper symbology)

(c.) The above terms can now be used in an algorithm. An upper limit = y-bar + center + d_rad. The lower limit is y-bar + center - d_rad.
because a while loop is used for testing inputs, the algorithm must be altered. If the point must be less than limit 1, while the point
is greater than or equal to limit 1, the error check will continue to ask for a new value. For the lower limit, the condition is also
similarly reversed with respect to the original algorithm. This can be readily seen in the code above.

(d.) This section is for revision notes:
dy = (pow((pow(((radius * (cos(tangent * pi) - (1/cos(tangent * pi))))), 2)), 0.5))/2; // Old limit region radius code. This was
replaced by an absolute value function, where ideally the reduction of power operations will increase the efficiency of the code. */

// Section Details: Computation of elliptic geometry center point.
dx = radius * sin(tangent * pi); // Proper use of dx...
dy = abs( apex + ( radius * cos(tangent * pi)) - center ); // And also the proper use of dy!
b = ( dy / 2 ) * ( 1 + pow(( 1 + (( 2 * dy )/( m * dx ))), -1 )); // Currently verified to function properly for values over 0.5 * pi.
tanEQ = acos((dy/b) - 1); // Returns a value in radians.
a = dx / (sin(tanEQ));
datafield[ (3 + count) ] = apex + center - b; // Plot the coordinate of the ellipse center to the data vector.
datafield[ (4 + count) ] = b; // Plot the height of the ellipse.
datafield[ (5 + count) ] = a; // Plot the width of the ellipse.
datafield[ (6 + count) ] = tanEQ; // Plot the equivalent value in radians where the point of tangency exists on the ellipse.
/* Notes on section calculations: (a.) "dx" forms the width of a quadrilateral used in a geometric proof to find the center of an
ellipse. This is the same as the x-coordinate on the circle where the point of tangency exists.

(b.) "dy" forms the height of a quadrilateral used to find the center of an ellipse. The other sides of the quadrilateral are formed by
the tangent line "m" and dx', which is a length from the base of dx along the tangent line to where the tangent line intersects with the
horizontal line formed at the top of dy. Length dy is a measure from the apex of the ellipse to height of the point of tangency on the
circular section. This distance is calculated whith an absolute value function, where abs( x_1 - x_2 ) = distance. The apex is x_1, and
is simply an input value, while x_2 is -r * cos(t) + center. The simplified version of this is seen above.

(c.) The height of the ellipse b is determined from a geometric relation formed from the above calculations and previously aquired
information. If a rectangle is drawn, with height dy and width dx, a centerpoint exists at (dx/2, dy/2). A line can be drawn which
crosses through the centerpoint and the intersection of the tangent line with dx'. This line crosses through the local (non-shifted)
origin of the ellipse. This line, crossing between two definable points, has a definable angle between itself and dx'. Line dx' also has
a definable length, dx' = dx + (dy/m), where m is the slope of the tangent line. Inverse tangent may be used to compute the angle between
dx' and the line (which forms a hypotenuse) because the center coordinates and intersection coordinates are known. Tangent may be used to
find the height b of the ellipse because the angle and the length of a side (dx') are known. Because tan(arctan(t)) = t, the height of
the ellipse function reduces from a trigonometric function to an algebraic function. The reduced form of this function is shown above. I
may provide a more detailed proof of this in later writing.

(d.) Because the height of the ellipse, b, has been calculated, the height of the y-coordinate from the relative center can be calculated
as dy is also known. y = b - dy. This provides a useful relation in determining the equivalent measure of theta at the elliptical section
of the fuselage commences. With the conventions of this program, the simplified version reduces to what is seen in the code above.

(e.) Finally, the width of the ellipse must be known for elliptical points to be plotted in a file. Via the conventions, an
x-coordinate = a * sin(t), where a is the width of an ellipse. Because the x-coordinate is equal to dx = r * sin(t) at the point of
tangency, this value is known. From the previous calculation, the equivalent measure of theta with respect to the tangent slope is also
known. The equation thus reduces to a = dx/sin(t), as seen in the code above.

(f.) To shift the center of the elliptic section properly with respect to the circular section, the simple relation
(apex - b) + circular section coordinate is used.

(g.) Revision notes: Proofs need proper detailing and better formatting in the future.*/
}

// CODE EXECUTION: FILE PARSING (Console window output prototype)

// Section Details: Initializes file syntax.
cout << "\n0\n" << endl; // Denotes start of file; "0" signifies measurements are in meters.

for (count = 0; count < stations; count = count + 7) // Again re-using the counter. Very boss-like and professional. Or something.
{
// Section Details: Establish initial numerics for parsing computations.
angle = 2 / verts; // Computes the number of degrees theta (with respect to pi) between each vertex.
dy = 1; // Re-use dy to count the vertex number plotted.

// Section Details: Plot first coordinate semi-manually.
cout << "\t" << datafield[ count ] << "\t0\t" << ((datafield[ (2 + count) ] * (-1)) + datafield[ (1 + count) ]) << "\n";

// Section Details: Lower hull geometry parser. This uses the circular section data.
while (angle < tangent) // Plot up to the tangent point.
{
cout << "\t" << datafield[ count ] << "\t" << (datafield[ (2 + count) ] * sin(angle * pi)) << "\t"
<< ((datafield[ (2 + count) ] * (-1) * cos(angle * pi)) + datafield[ (1 + count) ]) << "\n";
angle++; // Augment angle...
dy++; // Count verticies...
}

// Section Details: Plot point of tangency. This uses the elliptic section data.
  cout << "\t" << datafield[ count ] << "\t" << (datafield[ (5 + count) ] * sin(datafield[ (6 + count) ])) << "\t"
<< ((datafield[ (4 + count) ] * (-1) * cos(datafield[ (6 + count) ])) + datafield[ (3 + count) ]) << "\n";
dy++; // Count the vertex...

// Section Details: Prepare ellipse plotting calculations.
dx = (verts / 2) + 1; // Determines the total number of vertices on the station half. Again re-appropriates dx.
angle = (pi - datafield[ (6 + count) ]) / (dx - dy); // Re-computes the number of radial degrees between verticies.
/* Notes on section calculations: (a.) The number of verticies on the side of a station is equivalent to the total number of vertices
desired for use in the station divided by two, plus one. This is because one vertex exists at the very top, while one exists at the
bottom. This assumes the number of verticies is even, which is enforced by the prior code. This is calculated as dx as seen above.

(b.) Because pi is the top of the hull section, subtracting the equivalent radial degree of the tangent point on the ellipse from it will
yield the number of radial degrees to be traversed. Recall once more that variable tanEQ is measured in radians. By subtracting the
number of counted verts placed on the station to this point, dy, from dx (part (a.)) the number of verticies to be plotted can be
determined. Finally, dividing the number of degrees to be traversed by the number of verticies to be plotted yields the number of degrees
between each vertex to be plotted on the elliptical section. */

// Section Details: Parse elliptic hull sections.
while ( dy < dx )
{
cout << "\t" << datafield[ count ] << "\t" << (datafield[ (5 + count) ] * sin(datafield[ (6 + count) ] + angle)) << "\t"
<< ((datafield[ (4 + count) ] * (-1) * cos(datafield[ (6 + count) ] + angle)) + datafield[ (3 + count) ]) << "\n";
angle++; // Augment that angle!
dy++; // Count that vertex!
}

// Section Details: Plot the final coordinate semi-manually for great justice, and to ensure no errors occur.
cout << "\t" << datafield[ count ] << "\t0\t" << (datafield[ (4 + count) ] + datafield[ (3 + count) ]) << "\n\n";
}

// Section Details: Finalizes file syntax.
cout << "\nEOF" << endl; // Ends the parsing of the file.

return 0;
}

The things the output does right so far are the header and the closing line. The first line (for each station) is kind of right, and the last line is correct. The "kind of right" part for the first line is due to the fact that the output is accurate, but for reasons beyond me, the line is repeated twice! That's quite odd. But, it seems to principally just be a fluke: if I enter in the minimum number of hull verticies to be parsed, 8, I should get five ordered coordinates in each block. This is because in a fuselage station with eight verticies, one is on the top, one on the bottom, and three on each side. Because I need the bottom and top vertex, I can divide the vertex count by two and add one to get a proper count working. I can delete the top line of the output easily enough, but it's still wrong.

The next set of errors is really... wrong. The z-coordinates, the first column of the output, is perfect. "datafile[ count ]" works exactly as it is supposed to here, and pulls the information out of the vector just as planned. But the second and third columns are train wrecks! The second column is for x-coordinates, and is never negative. The third column is y-coordinates, and depending on where the elevation coordinates of the circular or elliptical sections are, may be all negative or all positive. But, the lines at the tops of the block should always be less than the lines at the bottom. This is because parsing begins at the bottom of a station and moves upward...

I suppose it is once again time to add multiple cout << ..... lines to figure out what is going on at each phase of the calculation. And this bothers me, because this damned thing refuses to be finished!!!
"trolls are clearly social rejects and therefore should be isolated from society, or perhaps impaled."

-Nuke



"Look on the bright side, how many release dates have been given for Doomsday, and it still isn't out yet.

It's the Duke Nukem Forever of prophecies..."


"Jesus saves.

Everyone else takes normal damage.
"

-Flipside

"pirating software is a lesser evil than stealing but its still evil. but since i pride myself for being evil, almost anything is fair game."


"i never understood why women get the creeps so ****ing easily. i mean most serial killers act perfectly normal, until they kill you."


-Nuke

 

Offline z64555

  • 210
  • Self-proclaimed controls expert
    • Minecraft
    • Steam
Re: Simple Programming, Calculus, and Geometry
K, here's an linear-algebra way of determining if all vertices are planar for a given polygon/face.


Assuming all vertices are 3D:
  • Take three vertices out of the polygon, I shall name them A, B, and C for convenience.

  • Subtract A from all vertices that are in the face, and store ( B - A ) as v1 and ( C - A ) as v2

  • Calculate the vN, the normal vector, by taking the cross product between v1 and v2  ( v1 x v2 )

        Once you have vN, you can then proceed to check all other vertices in polygon to see if it is perpendicular to it.

  • Calculate the dot product between vN and v4, where v4 = ( D - A) and D is the forth vertex

  • If vN dot v4 = 0, then v4 is perpendicular to vN, ergo: D is on the same plane as A, B, and C


Now, if you wanted to create circles, ellipses that where in 3D space, then you'll definitely have to change your parametric equations up so that you can specify theta_x, theta_y, and theta_z (where each angle is is a counter-clockwise rotation about their associated Cartesian axis.) The circle would only need theta_x and theta_y, but the ellipse needs theta_z.

Also, be really careful in the order that you apply the rotations. I'd suggest applying the Z rotation first, then the X, and finally the Y axis.

P.S. You really need to concisely define what problems your having. This not only helps me, but it also helps you. I couldn't tell if you needed to verify if all vertices on a polygon where planar to each other, or if you needed to create circular and elliptical surfaces that where planar and had a normal vector that wasn't along any of the Cartesian axes.
Secure the Source, Contain the Code, Protect the Project
chief1983

------------
funtapaz: Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Juche.
z64555: s/J/Do
BotenAlfred: <funtapaz> Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Douche.

 

Offline Thaeris

  • Can take his lumps
  • 211
  • Away in Limbo
Re: Simple Programming, Calculus, and Geometry
Z, keep in mind that every 3D format is different. This is not wavefront object or anything of that sort. This is a format that is read by FreeShip, interpreted by a b-spline, and then matched to subdivided geometry. If you're curious about the output, you need to look through this software's manual: http://sourceforge.net/projects/freeship/

Anyway, back to bug stomping!

Meow, can anyone tell me why this code, if the variable int verts = 8, will return a value of zero?

Code: [Select]
angle = 2 / verts;

...Well, it's apparently because it needed to be this code:

Code: [Select]
angle = 2 / double(verts);

It's one of the wonkiest things I've seen. Double angle should be able to do math with an interger, right? In this case, apparently not. I'd like a more computer-sciency explanation for this one if possible. This is likely the bug that was messing up my code in the beginning.
"trolls are clearly social rejects and therefore should be isolated from society, or perhaps impaled."

-Nuke



"Look on the bright side, how many release dates have been given for Doomsday, and it still isn't out yet.

It's the Duke Nukem Forever of prophecies..."


"Jesus saves.

Everyone else takes normal damage.
"

-Flipside

"pirating software is a lesser evil than stealing but its still evil. but since i pride myself for being evil, almost anything is fair game."


"i never understood why women get the creeps so ****ing easily. i mean most serial killers act perfectly normal, until they kill you."


-Nuke

 

Offline z64555

  • 210
  • Self-proclaimed controls expert
    • Minecraft
    • Steam
Re: Simple Programming, Calculus, and Geometry
Z, keep in mind that every 3D format is different. This is not wavefront object or anything of that sort. This is a format that is read by FreeShip, interpreted by a b-spline, and then matched to subdivided geometry. If you're curious about the output, you need to look through this software's manual: http://sourceforge.net/projects/freeship/

The 3D format is irrelevant, the fact that your working with B-splines instead of polygons is relevant... and probably should've been mentioned before you went off spitting out (otherwise) nonsensical mathematics. "The music is pleasant until the record skips a groove or five."

Quote
Can anyone tell me why this code, if the variable int verts = 8, will return a value of zero?

Code: [Select]
angle = 2 / verts;

...Well, it's apparently because it needed to be this code:

Code: [Select]
angle = 2 / double(verts);

It's one of the wonkiest things I've seen. Double angle should be able to do math with an interger, right? In this case, apparently not. I'd like a more computer-sciency explanation for this one if possible. This is likely the bug that was messing up my code in the beginning.

That's dependant on the compiler your using, as well as which version of C++ it supports. Namely, the thing your compiler is complaining about is called implicit type casting. Although the first code snippet above is perfectly valid, the compiler still thinks that the calculations on the right are integers, whereas we (and smarter compilers) know that it should be converted into a double precision floating type.


Also, some nitpicks:
Code: [Select]
angle = 2 / ( (double) verts );
It's "stanchion" (the vertical supporting members of railings and ships alike)... not stations. :P

You've got WAY too much documentation in your code. Thin it out, cut the rambling, and get to the point.

Suggest making helper functions to spit out the prompt text. They may be beneficial later on if somebody decides to add multiple language support... but mainly so as to reduce the amount of cout paragraphs in your main functions.


That's all I can think of at the moment. I'll see if I can dig through your code some more tomorrow.
Secure the Source, Contain the Code, Protect the Project
chief1983

------------
funtapaz: Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Juche.
z64555: s/J/Do
BotenAlfred: <funtapaz> Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Douche.

 

Offline Thaeris

  • Can take his lumps
  • 211
  • Away in Limbo
Re: Simple Programming, Calculus, and Geometry
Z, cool it, man. I don't think you understand what I'm doing, and that's fine. In your defense, I've not noted too much about what I'm doing, either. The console window output is a prototype to make sure the output of my program is good before commiting the code to an equivalent in the <cstdio> library.

As far as good news goes, the prototype now mostly works. I tried elevating the rear station (and guess what, I shall call a station what I please... :p), and the parser is throwing out yet another strange bug or algbraic error for me to hunt down. However, it is nevertheless kind of cool to look at:



That again, is the appearance when loaded into FreeShip.

If you care to see for yourself, here is the contents of the current test file:
Code: [Select]
0

        0       0       -1
        0       0.0697565       -0.997564
        0       0.139173        -0.990268
        0       0.207912        -0.978148
        0       0.275637        -0.961262
        0       0.34202 -0.939693
        0       0.406737        -0.913545
        0       0.469472        -0.882948
        0       0.529919        -0.848048
        0       0.587785        -0.809017
        0       0.642788        -0.766044
        0       0.694658        -0.71934
        0       0.743145        -0.669131
        0       0.788011        -0.615661
        0       0.829038        -0.559193
        0       0.866025        -0.5
        0       0.898794        -0.438371
        0       0.927184        -0.374607
        0       0.951057        -0.309017
        0       0.970296        -0.241922
        0       0.984808        -0.173648
        0       0.994522        -0.104528
        0       0.999391        -0.0348995
        0       0.999391        0.0348995
        0       0.994522        0.104528
        0       0.984808        0.173648
        0       0.970296        0.241922
        0       0.951057        0.309017
        0       0.927184        0.374607
        0       0.898794        0.438371
        0       0.891007        0.45399
        0       0.855364        0.518027
        0       0.815128        0.579281
        0       0.770513        0.637424
        0       0.72176 0.692143
        0       0.669131        0.743145
        0       0.612907        0.790155
        0       0.553392        0.832921
        0       0.490904        0.871214
        0       0.425779        0.904827
        0       0.358368        0.93358
        0       0.289032        0.957319
        0       0.218143        0.975917
        0       0.146083        0.989272
        0       0.0732382       0.997314
        0       0       1

        5       0       -1.5
        5       0.104635        -1.49635
        5       0.20876 -1.4854
        5       0.311868        -1.46722
        5       0.413456        -1.44189
        5       0.51303 -1.40954
        5       0.610105        -1.37032
        5       0.704207        -1.32442
        5       0.794879        -1.27207
        5       0.881678        -1.21353
        5       0.964181        -1.14907
        5       1.04199 -1.07901
        5       1.11472 -1.0037
        5       1.18202 -0.923492
        5       1.24356 -0.838789
        5       1.29904 -0.75
        5       1.34819 -0.657557
        5       1.39078 -0.56191
        5       1.42658 -0.463525
        5       1.45544 -0.362883
        5       1.47721 -0.260472
        5       1.49178 -0.156793
        5       1.49909 -0.0523492
        5       1.49909 0.0523492
        5       1.49178 0.156793
        5       1.47721 0.260472
        5       1.45544 0.362883
        5       1.42658 0.463525
        5       1.39078 0.56191
        5       1.34819 0.657557
        5       1.33651 0.680986
        5       1.26956 0.804778
        5       1.19821 0.922
        5       1.12272 1.03225
        5       1.04335 1.13514
        5       0.960367        1.23032
        5       0.874061        1.31746
        5       0.784731        1.39625
        5       0.692686        1.46643
        5       0.598244        1.52775
        5       0.501732        1.58
        5       0.403485        1.623
        5       0.303841        1.6566
        5       0.203147        1.68068
        5       0.101749        1.69517
        5       0       1.7

        11      0       -0.5
        11      0.0558052       -0.498051
        11      0.111338        -0.492214
        11      0.166329        -0.482518
        11      0.22051 -0.469009
        11      0.273616        -0.451754
        11      0.325389        -0.430836
        11      0.375577        -0.406358
        11      0.423935        -0.378438
        11      0.470228        -0.347214
        11      0.51423 -0.312836
        11      0.555727        -0.275472
        11      0.594516        -0.235304
        11      0.630409        -0.192529
        11      0.66323 -0.147354
        11      0.69282 -0.1
        11      0.719035        -0.0506969
        11      0.741747        0.000314725
        11      0.760845        0.0527864
        11      0.776237        0.106462
        11      0.787846        0.161081
        11      0.795618        0.216377
        11      0.799513        0.27208
        11      0.799513        0.32792
        11      0.795618        0.383623
        11      0.787846        0.438919
        11      0.776237        0.493538
        11      0.760845        0.547214
        11      0.741747        0.599685
        11      0.719035        0.650697
        11      0.712805        0.963192
        11      0.701857        0.977959
        11      0.684245        0.992427
        11      0.660136        1.00646
        11      0.62976 1.01992
        11      0.593404        1.03269
        11      0.551414        1.04464
        11      0.504188        1.05566
        11      0.452175        1.06564
        11      0.395869        1.0745
        11      0.335805        1.08213
        11      0.272552        1.08848
        11      0.206711        1.09349
        11      0.138907        1.09709
        11      0.069785        1.09927
        11      0       1.1


EOF

Copy that into a text file (just the good old standard .txt extension), and import it into FreeShip as a surface. Hopefully a stable-enough-code to do what I've been wanting it to do will be ready by tomorrow.
"trolls are clearly social rejects and therefore should be isolated from society, or perhaps impaled."

-Nuke



"Look on the bright side, how many release dates have been given for Doomsday, and it still isn't out yet.

It's the Duke Nukem Forever of prophecies..."


"Jesus saves.

Everyone else takes normal damage.
"

-Flipside

"pirating software is a lesser evil than stealing but its still evil. but since i pride myself for being evil, almost anything is fair game."


"i never understood why women get the creeps so ****ing easily. i mean most serial killers act perfectly normal, until they kill you."


-Nuke

 

Offline z64555

  • 210
  • Self-proclaimed controls expert
    • Minecraft
    • Steam
Re: Simple Programming, Calculus, and Geometry
I've done some editing on your code, but since I still have no clue what it's trying to do, I cannot garuntee that it will still work.

Code: [Select]
// HullForm.cpp : Defines the entry point for the console application. This is HullForm I.
// This is a geometry parsing program designed to output files to FreeShip.

#include "stdafx.h"
#include <iostream>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
using namespace std;


int main()
{
/* This code may be expandable, but is at the moment only designed for use with a specific-case application. This case is that of the Blohm
und Voss P.212.03 fighter project, where the lower section of the hull is circular, while the upper section is elliptical. The program will
write a text file readable by the program "FreeShip," which will then output actual geometry usable by other software applications. This
version of the software is only reliable for producing fuselage sections as described above. */

// DECLARAION OF VARIABLES

int count; // counter and selector variable.
int stanchions; // number of hull sections to be parsed. This number must be at least 2.
int verts; // number of verticies drawn per hull stanchion. 8 is the minimum number for a proper curve; 40+ are ideal.
double apex; // highest point of an elliptical section of the hull.
double angle; // equal to n*Pi, radial angle that spaces the distance between each vertex.
double a; // width of the ellipse. This is datafield[ (5 + count) ].
double b; // height of the ellipse. This is datafield[ (4 + count) ].
double radius; // radius of a circular section of the hull. This is datafield[ (2 + radius) ].
double dx; // temporary variable, later used as a proper variable in finding the center point of an elliptic section.
double dy; // temporary variable, later used as a proper variable in finding the center point of an elliptic section.
double center; // center coordinate of a circular section. This is datafield[ (1 + count) ].
double m; // tangent slope where circular and elliptical sections of the fuselage meet.
double pi = 3.141592654;
double tangent; // This is the uniform point on the circular hull section with respect to theta that the elliptic section begins.
double tanEQ; // This is the equivalent measure of theta on the ellipse where both it and the circle are tangent; datafield[ (6 + count) ].
string extension = ".txt"; // This is the file type which is produced by running this code.

struct data_entry
{
double z; // Stanchion's z cordinate
double y; // Stanchion's y coordinate (centerpoint)
double radius; // Circular seciton's radius
double center_of_ellipse;
double a; // Ellipse height
double b; // Ellipse width
double tan_slope; // Slope, in radians, of the tangent at the point of tangency.
};

vector<data_entry> datafield;


// CODE EXECUTION: INITIAL PARAMETERS

// Determine number of stanchions.
cout << "Enter the total number of fuselage stanchions. This number must be at least equal to two.\n\n";
cin >> stanchions; // This is a number used to determine the number of entries listed in the data vector.
while (stanchions < 2)
{
cout << "\nEnter the total number of fuselage stanchions. This number must be at least equal to two.\n\n";
cin >> stanchions;
}

datafield.resize( stanchions );

// Data gathering for plotting behavior. Input station vertex count here.
do
{
cout << "\nEnter the total number of verticies to be drawn at each station. This number\n"
<< "must be at least equal to eight. The program will also force this number to be\n"
<< "even, rounding down.\n\n";
cin >> verts; // Number remains constant for entire program.
}while (verts < 8);

verts = verts - (verts % 2); // Operation ensures number of verticies is even.

// Data gathering for circle-ellipse tangency processing. This is the tangent angle or slope.
cout << "\nSelect the point of tangency for the elliptic section with the circular section."
<< "You may use a measure of theta or a slope.\n\n";
do
{
cout << "To use a measure of theta, press 0. Theta is measured from the bottom of the\n"
<< "circle (zero) to the top, which is 1 * pi.\n\n";
cout << "To use a slope, press 1. A slope is negative on the top surface of the circle\n"
<< "and positive on the lower surface of the circle.\n\n";

cin  >> count; // Here count is used as a selector. Alhough an int, decimals strangely seem to break the code...
}while ( (count < 0) || (count > 1) );

if (count == 0)
{
do
{
cout << "\nEnter the value of theta where the circular and elliptical sections are\n"
<< "tangent. Select a value between 0 and 1.\n\n";

cin  >> tangent;
}while (tangent < 0 || tangent > 1);

m = tan(tangent * pi); // An error exists when a slope is vertical/infinite (division by zero). pi/2 is to be avoided...
}
else
{
cout << "\nEnter the slope of the tangent line where circular and elliptical fuselage\n"
<< "sections meet. Values are all real numbers.\n\n";

// Behavior at positive values presents an instability to be adressed later.
cin  >> m;

if (m <= 0)
{
tangent = (atan(m)/pi) + 1;
}
else
{
tangent = (atan(m)/pi); // The code currently cannot handle vertical or infinite slopes, or tangents at zero radians.
}
}
/* Notes on section calculations: (a.) Slope m for traditional circles and ellipses is the derivative of the function
(b^2 * x^2) + (a^2 * y^2) = a^2 * b^2, which can be written as (-b^2 * x) / (a^2 * y). Note that in a circle, a = b = r.
For traditional parametric calculations, x = a * cos(t), and y = b * sin(t), where t = theta = n * pi, where n is any
real number. The derivative thus reduces to (-b * cos(t)) / (a * sin(t)). If it is not already apparent, "b" is the
height of the ellipse or circle, while "a" is the width. Due to the shift in theta 90 degrees (0.25 * pi) clockwise for
computational reasons, the functions must be re-written to reflect the values to be used. Thus, x = a * sin(t), and
y = -b * cos(t), as 0 * pi starts at the bottom of the fuselage and moves counter-clockwise upwards. Re-writing the
equation of the derivative thus yields m = (b * sin(t)) / (a * cos(t)). This simply then reduces to m = (b/a) * tan(t).
A constant k can be defined as b / a, and is a useful quantity. However, this ratio is not needed in this code development
as only the tangent at the circular section is of interest in computations. (b.) The measure of theta determined in the else
statement is achieved through a reverse process of determining the slope of the tangent line as demonstrated in prior statments.

(c.) Revision notes: Code needs to be break-proof and all-aspect! Consider omitting variable m in the future. */

// CODE EXECUTION: FINE DATA ENTRY

cout << "\nThe following section requires precise data entry. Errors will necessitate re-\nrunning the program.\n\n";

for (count = 0; count < stanchions; count++ ) // Uses count to cycle through vector entries whilst collecting information.
{
// Assignment of given station's z-coordinate.
cout << "\nEnter the z-coordinate of the number #" << ((count/7) + 1) << " stanchion.\n\n"; // Modifies the count to show station number.
cin >> datafield[ count ].z; // Write z-value of station directly to the vector field.

// Assignment of station's circular section center point in the y-axis.
cout << "\nEnter the y-coordinate of the number #" << ((count/7) + 1) << " station's circular centerpoint.\n\n";
cin >> datafield[count].y;

// Input of circular section radius for a given station.
do
{
cout << "\nEnter the radius of the circular section. The radius must be greater than 0.\n\n";
cin >> radius;
}while (radius <= 0)

datafield[count].radius = radius; // Writes circular section radius to vector field.

// Section apex entry and input check.
dx = (-0.5*radius) * ((1/cos(tangent * pi)) + cos(tangent * pi)); // Temporary reassignment of variable as centroid of limit region.
dy = (abs((radius * (cos(tangent * pi) - (1/cos(tangent * pi))))))/2; // Temporary reassignment of variable as radius of limit region.
do
{
cout << "\nEnter the height of the section apex. This coordinate must be between the point\n"
<< "of tangency between circular and elliptical sections and the y-intercept of the\n"
<< "tangent line.\n\n";
cout << "The limits for placing the apex are between " << dx + center + dy << " and " << dx + center - dy << "\n\n";
cin >> apex;
}while ( (apex >= (dx + center + dy)) || (apex <= (dx + center - dy)) );


/* Notes on section calculations: (a.) A point in space may exist between two limits if the limits are along the same 1-dimensional
plane, or if parameters for lateral movement are defined. This problem is set up only to consider the former. Limits are established by
the elevation of the point of tangency and the intercept of the slope of the tangent line on the y-axis. First, the locations of the
limits must be known. For the y-intercept, y = m*x + b. y = -r * cos(t), m = tan(t), x = r * sin(t). This is then:
-r*cos(t) = r*tan(t)*sin(t) + b. This becomes: -r*cos(t) - r*tan(t)*sin(t) = b. Then, -r * (cos(t) + tan(t)*sin(t)) = b. Note that
cos(t) + tan(t)*sin(t) = sec(t). Because secant is not an available function in <cmath>, sec(t) = 1/cos(t). Thus, the y-intercept is
b = -r/cos(t). The elevation of the point of tangency is simply equal to y, or -r * cos(t) at the specified measure of theta.

(b.) Terms must be combined and simplified for proper operation and clean implementation of algorithms. If the centroid or average
coordinate of the limit region is known, and the radius, or half of the distance between the coordinates is known, then the algorithm
"limit 1 > point > limit 2" can be implemented. Because the limits are of equal weight in importance, their order in the algorithm is of
no real concern, so long and the program properly recognizes of the points in relation to the coordinate to be entered into memory. The
average coordinate location, y-bar = ((m_1 * x_1) + (m_2 * x_2))/(m_1 + m_2). Because weights "m" are equal, m_1 = m_2, and the equation
becomes an arithmetic mean, y-bar = (x_1 + x_2)/2. The distance between two points is: d = ((x_1-x_2)^2)^0.5. Dividing this number by 2
delivers a radius: d_rad = (((x_1-x_2)^2)^0.5)/2. When combining terms from the first section, the following relations are derived:

y-bar = (-r/2)*((1/cos(t)) + cos(t)) (+ center coordinate of circular section)
d_rad = (((r * (cos(t) - (1/cos(t))))^2)^0.5)/2 (This looks much better on paper with proper symbology)

(c.) The above terms can now be used in an algorithm. An upper limit = y-bar + center + d_rad. The lower limit is y-bar + center - d_rad.
because a while loop is used for testing inputs, the algorithm must be altered. If the point must be less than limit 1, while the point
is greater than or equal to limit 1, the error check will continue to ask for a new value. For the lower limit, the condition is also
similarly reversed with respect to the original algorithm. This can be readily seen in the code above.

(d.) This section is for revision notes:
dy = (pow((pow(((radius * (cos(tangent * pi) - (1/cos(tangent * pi))))), 2)), 0.5))/2; // Old limit region radius code. This was
replaced by an absolute value function, where ideally the reduction of power operations will increase the efficiency of the code. */

// Computation of elliptic geometry center point.
dx = radius * sin(tangent * pi); // Proper use of dx...
dy = abs( apex + ( radius * cos(tangent * pi)) - center ); // And also the proper use of dy!
b = ( dy / 2 ) * ( 1 + pow(( 1 + (( 2 * dy )/( m * dx ))), -1 )); // Currently verified to function properly for values over 0.5 * pi.
tanEQ = acos((dy/b) - 1); // Returns a value in radians.
a = dx / (sin(tanEQ));

datafield[count].center_of_ellipse = apex + center - b;
datafield[count].b = b;
datafield[count].a = a;
datafield[count].tan_slope = tanEQ;

/* Notes on section calculations: (a.) "dx" forms the width of a quadrilateral used in a geometric proof to find the center of an
ellipse. This is the same as the x-coordinate on the circle where the point of tangency exists.

(b.) "dy" forms the height of a quadrilateral used to find the center of an ellipse. The other sides of the quadrilateral are formed by
the tangent line "m" and dx', which is a length from the base of dx along the tangent line to where the tangent line intersects with the
horizontal line formed at the top of dy. Length dy is a measure from the apex of the ellipse to height of the point of tangency on the
circular section. This distance is calculated whith an absolute value function, where abs( x_1 - x_2 ) = distance. The apex is x_1, and
is simply an input value, while x_2 is -r * cos(t) + center. The simplified version of this is seen above.

(c.) The height of the ellipse b is determined from a geometric relation formed from the above calculations and previously aquired
information. If a rectangle is drawn, with height dy and width dx, a centerpoint exists at (dx/2, dy/2). A line can be drawn which
crosses through the centerpoint and the intersection of the tangent line with dx'. This line crosses through the local (non-shifted)
origin of the ellipse. This line, crossing between two definable points, has a definable angle between itself and dx'. Line dx' also has
a definable length, dx' = dx + (dy/m), where m is the slope of the tangent line. Inverse tangent may be used to compute the angle between
dx' and the line (which forms a hypotenuse) because the center coordinates and intersection coordinates are known. Tangent may be used to
find the height b of the ellipse because the angle and the length of a side (dx') are known. Because tan(arctan(t)) = t, the height of
the ellipse function reduces from a trigonometric function to an algebraic function. The reduced form of this function is shown above. I
may provide a more detailed proof of this in later writing.

(d.) Because the height of the ellipse, b, has been calculated, the height of the y-coordinate from the relative center can be calculated
as dy is also known. y = b - dy. This provides a useful relation in determining the equivalent measure of theta at the elliptical section
of the fuselage commences. With the conventions of this program, the simplified version reduces to what is seen in the code above.

(e.) Finally, the width of the ellipse must be known for elliptical points to be plotted in a file. Via the conventions, an
x-coordinate = a * sin(t), where a is the width of an ellipse. Because the x-coordinate is equal to dx = r * sin(t) at the point of
tangency, this value is known. From the previous calculation, the equivalent measure of theta with respect to the tangent slope is also
known. The equation thus reduces to a = dx/sin(t), as seen in the code above.

(f.) To shift the center of the elliptic section properly with respect to the circular section, the simple relation
(apex - b) + circular section coordinate is used.

(g.) Revision notes: Proofs need proper detailing and better formatting in the future.*/
}

// CODE EXECUTION: FILE PARSING (Console window output prototype)

// Initializes file syntax.
cout << "\n0\n" << endl; // Denotes start of file; "0" signifies measurements are in meters.

for (count = 0; count < stanchions; count++ )
{
int number_of_verts = 1;
int number_of_verts_on_lower_hull;

// Establish initial numerics for parsing computations.
angle = 2 / verts; // Computes the radian angle step size between each vertex. (?)

// Plot first coordinate semi-manually.
cout << "\t" << datafield[ count ].z << "\t0\t" << ((datafield[ count ].radius * (-1)) + datafield[ count ].y ) << "\n";

// Lower hull geometry parser. This uses the circular section data.
while (angle < tangent) // Plot up to the tangent point.
{
cout << "\t" << datafield[count].z << "\t" << (datafield[count].radius * sin(angle * pi)) << "\t"
<< ((datafield[count].radius * (-1) * cos(angle * pi)) + datafield[count].y ) << "\n";
angle++;
number_of_verts++;
}

// Plot point of tangency. This uses the elliptic section data.
  cout << "\t" << datafield[count].z << "\t" << (datafield[count].b * sin(datafield[count].tan_slope)) << "\t"
<< ((datafield[count].a * (-1) * cos(datafield[count].tan_slope)) + datafield[count].center_of_ellipse) << "\n";
number_of_verts++;

// Prepare ellipse plotting calculations.
number_of_verts_on_lower_hull = (verts / 2) + 1; // Determines the total number of vertices on the station half.
angle = (pi - datafield[count].tan_slope) / (number_of_verts_on_lower_hull - number_of_verts); // Re-computes the number of radial degrees between verticies.
/* Notes on section calculations: (a.) The number of verticies on the side of a station is equivalent to the total number of vertices
desired for use in the station divided by two, plus one. This is because one vertex exists at the very top, while one exists at the
bottom. This assumes the number of verticies is even, which is enforced by the prior code. This is calculated as dx as seen above.

(b.) Because pi is the top of the hull section, subtracting the equivalent radial degree of the tangent point on the ellipse from it will
yield the number of radial degrees to be traversed. Recall once more that variable tanEQ is measured in radians. By subtracting the
number of counted verts placed on the station to this point, dy, from dx (part (a.)) the number of verticies to be plotted can be
determined. Finally, dividing the number of degrees to be traversed by the number of verticies to be plotted yields the number of degrees
between each vertex to be plotted on the elliptical section. */

// Parse elliptic hull sections.

// z64: Hey! number_of_verts will _always_ be greater than number_of_verts_on_lower_hull... therefor this while loop does nothing!
while ( number_of_verts < number_of_verts_on_lower_hull )
{
cout << "\t" << datafield[count].z << "\t" << (datafield[count].b * sin(datafield[count].tan_slope + angle)) << "\t"
<< ((datafield[count].a * (-1) * cos(datafield[count].tan_slope + angle)) + datafield[count].center_of_ellipse) << "\n";
angle++;
number_of_verts++;
}

// Plot the final coordinate semi-manually for great justice, and to ensure no errors occur.
cout << "\t" << datafield[count] << "\t0\t" << (datafield[count].a + datafield[count].center_of_ellipse) << "\n\n";
}

// Finalizes file syntax.
cout << "\nEOF" << endl; // Ends the parsing of the file.

return 0;
}

Now, here are some very important issues I must stress to you.

Do Not Use Magic Numbers.
Magic numbers are constant values throughout the code, and in most cases are not immediately apparent. In the case of your .cpp file, you make avid use of magic numbers for your datafield vector.

This Is Not Good Code Practice. Although it would make perfect sense to do so in assembler, specifying the relative address of non-sequential data is damn hard to figure out which data is what from memory, and even harder to debug. Use the a struct to group your data entries (like what I did above) so you, and everyone else that's trying to read the .cpp file, can immediately know where the hell the data is going.

Minimize the use of comments.
Comments are exactly that. Comments. Not paragraphs or dissertations. Overuse of the comments field only clouds up the .cpp file and makes it visually difficult to distinguish what is, and what isn't code.

Divide and Conquer your work load.
In your code, you put all of your functionality into a single main function. While this is OK for small, beginning programs, it is not OK for a program as complex as yours. Break up functions into smaller, easily digestible functions, and then use them in your main function. This aide the debugging process because a coder can go through and verify each function works on it's own, instead digging through walls of text to figure out what is causing problems.

Clearly Define Your Problem.
You had me running around trying to figure out what the heck you where trying to solve. Initially, you had me thinking that you needed to verify that all points of a face where planar, then you had me thinking that you where trying to make a tubular mesh/surface that had a circular profile on one end and an elliptical profile on the other. By finally researching the P 212-03, I found out that you are, in actuality, trying to make a hull that has an initially tubular hull that goes from a egg-shape profile to a circular profile.

This may be entertaining for you, but not all for me, who has been trying to help you debug your program (since you asked for help in the first place.) The fact that you have not clearly defined your problem, nor have you even tried to explain what it is you are trying to do, has made it so difficult for me and the rest of the world to figure out what's going on. Slow Down.




Lastly, I believe your method of calculating the vertices is flawed, and suggest using a method such as this on a cylindrical mesh. Basically, I'm imagining an algorithm that will allow a user to define the height and widths (top and bottom) of a trapezoidal cross section. This cross section would line up on each stanchion and transform/warp the vertices of a cylindrical mesh so as to achieve the egg-shaped profiles. This should avoid the confusing geometry functions your using, as well as make it simpler for the end-user of the program.
Secure the Source, Contain the Code, Protect the Project
chief1983

------------
funtapaz: Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Juche.
z64555: s/J/Do
BotenAlfred: <funtapaz> Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Douche.

 

Offline jr2

  • The Mail Man
  • 212
  • It's prounounced jayartoo 0x6A7232
    • Steam
Re: Simple Programming, Calculus, and Geometry
Quote
Minimize the use of comments.
Comments are exactly that. Comments. Not paragraphs or dissertations. Overuse of the comments field only clouds up the .cpp file and makes it visually difficult to distinguish what is, and what isn't code.

Can't you use some sort of filter (IIRC Notepad++ has one) that makes comment text a different color?

EDIT: Not saying one way or the other what's right, just this might be helpful for reading the code as it is?

 

Offline z64555

  • 210
  • Self-proclaimed controls expert
    • Minecraft
    • Steam
Re: Simple Programming, Calculus, and Geometry
Quote
Minimize the use of comments.
Comments are exactly that. Comments. Not paragraphs or dissertations. Overuse of the comments field only clouds up the .cpp file and makes it visually difficult to distinguish what is, and what isn't code.

Can't you use some sort of filter (IIRC Notepad++ has one) that makes comment text a different color?

EDIT: Not saying one way or the other what's right, just this might be helpful for reading the code as it is?

Even with the usage of comment colors and comment hiders (like what MS Visual Studio has) it still clouds up the file. I believe it's just better code practice to be concise, consistent, and to the point when making comments in the first place. If you feel that there's much to be said about a section of code, then it's probably a good idea to make that section a new function and then save your comments for that function, as you'll have much more room over the top of a function definition or declaration than in the middle the main routine.
Secure the Source, Contain the Code, Protect the Project
chief1983

------------
funtapaz: Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Juche.
z64555: s/J/Do
BotenAlfred: <funtapaz> Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Douche.

 

Offline Thaeris

  • Can take his lumps
  • 211
  • Away in Limbo
Re: Simple Programming, Calculus, and Geometry
Z, let me throw this out there: this is the first time I've ever heard someone complain about documentation of how algorithms and code works. Seeing as you personally admit that you do not understand my code, why in the seven hells are you complaining about documentation?

Next, it IS station, NOT stanchion. Refer to page 8 of this document: http://v5.books.elsevier.com/bookscat/samples/9780750649889/9780750649889.PDF

This terminology also works for aviation, and is what I'm abusing FreeShips modeling capacity for. "Section" is more common in engineering terminology, but again, I don't care, because I am not wrong in my usage of terminology.

I do appreciate some of your input, and will no dobut go over it when appropriate when applicable (this being if I decide to revise and re-write my software), but you also need to understand that this project was not supposed to last a long time. Between math calculations and proofs, however, and then wierd flukes like the problem with dividing by an int (which was the cause for me to raise this as an issue), this program grew into something more complex than I had in mind, and took far longer than I ever wanted. I PURPOSELY intended to not make a header file, and keep everything in one document, because it's a console-window operated script-writing program. Despite any complexity you think it might have, it really doesn't.

Next thing, rant aside, is that the problem with geometry appears to have been resolved. :D

The culprit in the code was this line:

Code: [Select]
datafield[ (3 + count) ] = apex + center - b; // Plot the coordinate of the ellipse center to the data vector.

This is the ellipse shifting function. By logic of the original documentation alone, it works. BUT, in reality, it doesn't, because the apex height calculation (dy proper) is made in relation to the y-coordinate of the point of tangency. The y-coordinate of the point of tangency is already calculated with respect to the location of the center section. SO, when ever a shift was made to the y-coordinate of a station, the coordinates above the tangent line were shifted up or down by the displacement of of the location of the center section. (Thus, positve center sections stretched elliptical coordinates, while negative center sections flattened them.) You can see the effects of that in the image in Post #8.

After a bit of analysis with lots of cout functions so I could see the outputs of any and all operations, the fix was very simple indeed:

Code: [Select]
datafield[ (3 + count) ] = apex - b; // Plot the coordinate of the ellipse center to the data vector.

And some sample output:



Three circular sections, all at different elevations, no distortion. :D

...I now just need to convert the console window output into syntax needed by the <cstdio> library. This will enable me to parse coordinate data directly to a text file. In other words, no more copy-paste from the console window!
"trolls are clearly social rejects and therefore should be isolated from society, or perhaps impaled."

-Nuke



"Look on the bright side, how many release dates have been given for Doomsday, and it still isn't out yet.

It's the Duke Nukem Forever of prophecies..."


"Jesus saves.

Everyone else takes normal damage.
"

-Flipside

"pirating software is a lesser evil than stealing but its still evil. but since i pride myself for being evil, almost anything is fair game."


"i never understood why women get the creeps so ****ing easily. i mean most serial killers act perfectly normal, until they kill you."


-Nuke

 

Offline z64555

  • 210
  • Self-proclaimed controls expert
    • Minecraft
    • Steam
Re: Simple Programming, Calculus, and Geometry
Z, let me throw this out there: this is the first time I've ever heard someone complain about documentation of how algorithms and code works. Seeing as you personally admit that you do not understand my code, why in the seven hells are you complaining about documentation?

The reason I'm complaining about the documentation of the algorithms and code is because that is usually the best and fastest way to understand the sections of code/algorithms they are documenting. Improper and messy documentation that is unreadable means that the only sure-fire way to understand what the code is doing is to trudge through and reverse-engineer it line-by-line. Obviously, I don't have enough time to do so (nor the patience.)

Quote
Next, it IS station, NOT stanchion. Refer to page 8 of this document: http://v5.books.elsevier.com/bookscat/samples/9780750649889/9780750649889.PDF

OK, thanks for clearing that up. Might've been able to avoid that argument if you referred to it to begin with, :D and yes "Cross-section" is more commonly used in the most engineering fields (at least in the mechanical, chemical, and electrical fields, I can't vouch for aeronautical or naval). EDIT: after reading a bit through that .pdf, I saw that there are two types of cross sections used, stations for port/starboard cross-sections, buttocks for bow/stern cross-sections.

Also, good job figuring out what was wrong with the ellipse center calculation.  :yes:
Secure the Source, Contain the Code, Protect the Project
chief1983

------------
funtapaz: Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Juche.
z64555: s/J/Do
BotenAlfred: <funtapaz> Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Douche.

 

Offline Thaeris

  • Can take his lumps
  • 211
  • Away in Limbo
Re: Simple Programming, Calculus, and Geometry
God. Damn. It. TO HEELLLL!!!

I do not know why I can't be done with this damn bloody thing. I may or may not improve it in the future, but it's pissing the hell out of me now. With some very, very good help from Swifty in fixing a careless mistake in the file output code, I've nearly got the program to where I need it to be to do my dirty work. But, because the universe generally hates me, there's still some bizzare quirks in the parsing code. Let's illustrate with an example of the output from the console window:

Code: [Select]
Enter the total number of fuselage stations. This number must be at least equal
to two.

2

Enter the total number of verticies to be drawn at each station. This number
must be at least equal to eight. The program will also force this number to be
even, rounding down.

16

Select the point of tangency for the elliptic section with the circular section.
You may use a measure of theta or a slope.

To use a measure of theta, press 0. Theta is measured from the bottom of the
circle (zero) to the top, which is 1 * pi.

To use a slope, press 1. A slope is negative on the top surface of the circle
and positive on the lower surface of the circle.

0

Enter the value of theta where the circular and elliptical sections are
tangent. Select a value between 0 and 1.

0.75

The following section requires precise data entry. Errors will necessitate re-
running the program.


Enter the z-coordinate of the number #1 station.

0

Enter the y-coordinate of the number #1 station's circular centerpoint.

0

Enter the radius of the circular section. The radius must be greater than 0.

1

Enter the height of the section apex. This coordinate must be between the point
of tangency between circular and elliptical sections and the y-intercept of the
tangent line; Use the absolute distance between the centerpoint and apex height.



For using a slope of -2.07, the apex limit is = 1.43896

1

Enter the z-coordinate of the number #2 station.

2.78

Enter the y-coordinate of the number #2 station's circular centerpoint.

1

Enter the radius of the circular section. The radius must be greater than 0.

2

Enter the height of the section apex. This coordinate must be between the point
of tangency between circular and elliptical sections and the y-intercept of the
tangent line; Use the absolute distance between the centerpoint and apex height.



For using a slope of -2.07, the apex limit is = 3.87792

3

Name the output file. NOTE: DO NOT ADD A FILE EXTENSION!

Anothertest

Parsing...


0

        0       0       -1
        0       0.382683        -0.92388
        0       0.707107        -0.707107
        0       0.92388 -0.382683
        0       1       2.05103e-010
        0       0.92388 0.382683
        0       0.707107        0.707107
        0       0.382683        0.92388
        0       0       1

        2.78    0       -1
        2.78    0.765367        -0.847759
        2.78    1.41421 -0.414214
        2.78    1.84776 0.234633
        2.78    2       1
        2.78    1.84776 1.76537
        2.78    1.41421 2.41421
        2.78    0.765367        2.84776
        2.78    0       3


EOF



File written. Check directory for output.

Press any key to continue . . .

This is the actual text output:

Code: [Select]
0

0.000000000 0.000000000 -325711365792980900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000000
0.000000000 0.382683432 -0.923879532
0.000000000 0.707106781 -0.707106781
0.000000000 0.923879533 -0.382683432
0.000000000 1.000000000 0.000000000
0.000000000 0.923879532 0.382683433
0.000000000 0.707106781 0.707106781
0.000000000 0.382683432 0.923879533
0.000000000 0.000000000 -325711229089810600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000000

2.780000000 0.000000000 -325711365792980900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000000
2.780000000 0.765366865 -0.847759065
2.780000000 1.414213563 -0.414213562
2.780000000 1.847759065 0.234633136
2.780000000 2.000000000 1.000000000
2.780000000 1.847759065 1.765366865
2.780000000 1.414213562 2.414213563
2.780000000 0.765366864 2.847759065
2.780000000 0.000000000 -325711229189934990000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000000


EOF

And here is the current source:

Code: [Select]
// HullForm.cpp : Defines the entry point for the console application. This is HullForm I.
// This is a geometry parsing program designed to output files to FreeShip.

#include "stdafx.h"
#include <iostream>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
using namespace std;


int main()
{
/* This code may be expandable, but is at the moment only designed for use with a specific-case application. This case is that of the Blohm
und Voss P.212.03 fighter project, where the lower section of the hull is circular, while the upper section is elliptical. The program will
write a text file readable by the program "FreeShip," which will then output actual geometry usable by other software applications. This
version of the software is only reliable for producing fuselage sections as described above. */

// DECLARAION OF VARIABLES

int count; // This is a general purpose interger counter and selector variable.
int stations; // This is the number of hull sections to be parsed. This number must be at least 2.
int verts; // This is the number of verticies drawn at each hull station. 8 is the minimum number for a proper curve; 40+ are ideal.
double apex; // This is the highest point of an elliptical section of the hull.
double angle; // This is the radial angle n * pi that spaces the distance between each coordinate.
double a; // This is the width of an ellipse. This is datafield[ (5 + count) ].
double b; // This is the height of the ellipse. This is datafield[ (4 + count) ].
double radius; // This is the radius of a circular section of a hull. This is datafield[ (2 + radius) ].
double dx; // This is used as a temporary variable, and then as a proper variable in finding the center point of an elliptic section.
double dy; // This is used as a temporary variable, and then as a proper variable in finding the center point of an elliptic section.
double center; // This is the center coordinate of a circular section. This is datafield[ (1 + count) ].
double m; // This is the tangent slope where circular and elliptical sections of the fuselage meet.
double pi = 3.141592654; // Pi to nine decimal points. Whoo-Hoo!
double tangent; // This is the uniform point on the circular hull section with respect to theta that the elliptic section begins.
double tanEQ; // This is the equivalent measure of theta on the ellipse where both it and the circle are tangent; datafield[ (6 + count) ].
string extension = ".txt"; // This is the file type which is produced by running this code.
string filename; // This is the name of the output file.
FILE *File; // This is the output data.
vector<double> datafield; // This is a one-dimensional database which the parser reads through to plot geometry.
/* OTHER DECLARATIONS:
(I.) datafield[ count ] is the z-coordinate of a station.
(II.) datafield[ (3 + count) ] is the center coordinate of the section's elliptical geometry. */

// CODE EXECUTION: INITIAL PARAMETERS

// Section Details: Determine number of stations.
cout << "Enter the total number of fuselage stations. This number must be at least equal to two.\n\n";
cin >> stations; // This is a number used to determine the number of entries listed in the data vector.
while (stations < 2)
{
cout << "\nEnter the total number of fuselage stations. This number must be at least equal to two.\n\n";
cin >> stations;
}
stations = stations * 7; // Simplifies data input and computation. There are seven data entries per station.
datafield.resize( stations, 0 ); // Initializes the data vector, all values at zero.
/* Notes on section calculations: (a.) Clearly, there's not much calculation here. However, multiplying the number of stations by a numeric
constant, in this case 7, allows a proper number of data entries to be entered for each station. */

// Section Details: Data gathering for plotting behavior. Input station vertex count here.
cout << "\nEnter the total number of verticies to be drawn at each station. This number\n"
<< "must be at least equal to eight. The program will also force this number to be\n"
<< "even, rounding down.\n\n";
cin >> verts; // Number remains constant for entire program.
while (verts < 8)
{
cout << "\nEnter the total number of verticies to be drawn at each station. This number\n"
<< "must be at least equal to eight. The program will also force this number to be\n"
<< "even, rounding down.\n\n";
cin >> verts;
}
verts = verts - (verts % 2); // Operation ensures number of verticies is even.

// Section Details: Data gathering for circle-ellipse tangency processing. This is the tangent angle or slope.
cout << "\nSelect the point of tangency for the elliptic section with the circular section."
<< "You may use a measure of theta or a slope.\n\n";
cout << "To use a measure of theta, press 0. Theta is measured from the bottom of the\n"
<< "circle (zero) to the top, which is 1 * pi.\n\n";
cout << "To use a slope, press 1. A slope is negative on the top surface of the circle\n"
<< "and positive on the lower surface of the circle.\n\n";
cin >> count; // Here count is used as a selector. Alhough an int, decimals strangely seem to break the code...
while (count < 0 || count > 1)
{
cout << "\nTo use a measure of theta, press 0. Theta is measured from the bottom of the\n"
<< "circle (zero) to the top, which is 1 * pi.\n\n";
cout << "To use a slope, press 1. A slope is negative on the top surface of the circle\n"
<< "and positive on the lower surface of the circle.\n\n";
cin >> count;
}
if (count == 0)
{
cout << "\nEnter the value of theta where the circular and elliptical sections are\n"
<< "tangent. Select a value between 0 and 1.\n\n";
cin >> tangent;
while (tangent < 0 || tangent > 1)
{
cout << "\nEnter the value of theta where the circular and elliptical sections are\n"
<< "tangent. Select a value between 0 and 1.\n\n";
cin >> tangent;
}
m = tan(tangent * pi); // An error exists when a slope is vertical/infinite (division by zero). 0.5 * pi is to be avoided...
}
else
{
cout << "\nEnter the slope of the tangent line where circular and elliptical fuselage\n"
<< "sections meet. Values are all real numbers.\n\n"; // At the moment, that is blatantly a lie...
cin >> m; // Behavior at positive values is not an issue for the current project, but presents an instability to be adressed later.
if (m <= 0)
{
tangent = (atan(m)/pi) + 1; // The code currently cannot handle vertical or infinite slopes, or tangents at zero pi.
}
else
{
tangent = (atan(m)/pi); // The code currently cannot handle vertical or infinite slopes, or tangents at zero pi.
}
}
/* Notes on section calculations: (a.) Slope m for traditional circles and ellipses is the derivative of the function
(b^2 * x^2) + (a^2 * y^2) = a^2 * b^2, which can be written as (-b^2 * x) / (a^2 * y). Note that in a circle, a = b = r.
For traditional parametric calculations, x = a * cos(t), and y = b * sin(t), where t = theta = n * pi, where n is any
real number. The derivative thus reduces to (-b * cos(t)) / (a * sin(t)). If it is not already apparent, "b" is the
height of the ellipse or circle, while "a" is the width. Due to the shift in theta 90 degrees (0.25 * pi) clockwise for
computational reasons, the functions must be re-written to reflect the values to be used. Thus, x = a * sin(t), and
y = -b * cos(t), as 0 * pi starts at the bottom of the fuselage and moves counter-clockwise upwards. Re-writing the
equation of the derivative thus yields m = (b * sin(t)) / (a * cos(t)). This simply then reduces to m = (b/a) * tan(t).
A constant k can be defined as b / a, and is a useful quantity. However, this ratio is not needed in this code development
as only the tangent at the circular section is of interest in computations. (b.) The measure of theta determined in the else
statement is achieved through a reverse process of determining the slope of the tangent line as demonstrated in prior statments.

(c.) Revision notes: Code needs to be break-proof and all-aspect! Consider omitting variable m in the future. */

// CODE EXECUTION: FINE DATA ENTRY

cout << "\nThe following section requires precise data entry. Errors will necessitate re-\n"
<< "running the program.\n\n";

for (count = 0; count < stations; count = count + 7) // Uses count to cycle through vector entries whilst collecting information.
{
// Section Details: Assignment of given station's z-coordinate.
cout << "\nEnter the z-coordinate of the number #" << ((count/7) + 1) << " station.\n\n"; // Modifies the count to show station number.
cin >> datafield[ count ]; // Write z-value of station directly to the vector field.

// Section Details: Assignment of station's circular section center point in the y-axis.
cout << "\nEnter the y-coordinate of the number #" << ((count/7) + 1) << " station's circular centerpoint.\n\n";
cin >> center;
datafield[ (1 + count) ] = center; // Writes circular center point of station to the vector field.

// Section Details: Input of circular section radius for a given station.
cout << "\nEnter the radius of the circular section. The radius must be greater than 0.\n\n";
cin >> radius;
while (radius <= 0)
{
cout << "\nEnter the radius of the circular section. The radius must be greater than 0.\n\n";
cin >> radius;
}
datafield[ (2 + count) ] = radius; // Writes circular section radius to vector field.

// Section Details: Section apex entry and input check.
dx = (-0.5*radius) * ((1/cos(tangent * pi)) + cos(tangent * pi)); // Temporary reassignment of variable as centroid of limit region.
dy = (abs((radius * (cos(tangent * pi) - (1/cos(tangent * pi))))))/2; // Temporary reassignment of variable as radius of limit region.
cout << "\nEnter the height of the section apex. This coordinate must be between the point\n"
<< "of tangency between circular and elliptical sections and the y-intercept of the\n"
<< "tangent line; Use the absolute distance between the centerpoint and apex height.\n\n";
// cout << "The limits for placing the apex are between " << dx + center + dy << " and " << dx + center - dy << "\n\n"; // Old code...
cout << "\nFor using a slope of -2.07, the apex limit is = " << ((radius*sin(tangent*pi)) * 1.035)+(-1*radius*cos(tangent*pi)) + center
<< "\n\n"; // Proper limit formula needs to be derived for future versions.
cin >> apex;
// while ( (apex >= (dx + center + dy)) || (apex <= (dx + center - dy)) ) // Inaccurate limit system. Needs revision.
// {
// cout << "\nEnter the height of the section apex. This coordinate must be between the point\n"
// << "of tangency between circular and elliptical sections and the y-intercept of the\n"
// << "tangent line; Use the absolute distance between the centerpoint and apex height.\n\n";
// cin >> apex;
// }
/* Notes on section calculations: (a.) A point in space may exist between two limits if the limits are along the same 1-dimensional
plane, or if parameters for lateral movement are defined. This problem is set up only to consider the former. Limits are established by
the elevation of the point of tangency and the intercept of the slope of the tangent line on the y-axis. First, the locations of the
limits must be known. For the y-intercept, y = m*x + b. y = -r * cos(t), m = tan(t), x = r * sin(t). This is then:
-r*cos(t) = r*tan(t)*sin(t) + b. This becomes: -r*cos(t) - r*tan(t)*sin(t) = b. Then, -r * (cos(t) + tan(t)*sin(t)) = b. Note that
cos(t) + tan(t)*sin(t) = sec(t). Because secant is not an available function in <cmath>, sec(t) = 1/cos(t). Thus, the y-intercept is
b = -r/cos(t). The elevation of the point of tangency is simply equal to y, or -r * cos(t) at the specified measure of theta.

(b.) Terms must be combined and simplified for proper operation and clean implementation of algorithms. If the centroid or average
coordinate of the limit region is known, and the radius, or half of the distance between the coordinates is known, then the algorithm
"limit 1 > point > limit 2" can be implemented. Because the limits are of equal weight in importance, their order in the algorithm is of
no real concern, so long and the program properly recognizes of the points in relation to the coordinate to be entered into memory. The
average coordinate location, y-bar = ((m_1 * x_1) + (m_2 * x_2))/(m_1 + m_2). Because weights "m" are equal, m_1 = m_2, and the equation
becomes an arithmetic mean, y-bar = (x_1 + x_2)/2. The distance between two points is: d = ((x_1-x_2)^2)^0.5. Dividing this number by 2
delivers a radius: d_rad = (((x_1-x_2)^2)^0.5)/2. When combining terms from the first section, the following relations are derived:

y-bar = (-r/2)*((1/cos(t)) + cos(t)) (+ center coordinate of circular section)
d_rad = (((r * (cos(t) - (1/cos(t))))^2)^0.5)/2 (This looks much better on paper with proper symbology)

(c.) The above terms can now be used in an algorithm. An upper limit = y-bar + center + d_rad. The lower limit is y-bar + center - d_rad.
because a while loop is used for testing inputs, the algorithm must be altered. If the point must be less than limit 1, while the point
is greater than or equal to limit 1, the error check will continue to ask for a new value. For the lower limit, the condition is also
similarly reversed with respect to the original algorithm. This can be readily seen in the code above.

(d.) This section is for revision notes:
dy = (pow((pow(((radius * (cos(tangent * pi) - (1/cos(tangent * pi))))), 2)), 0.5))/2; // Old limit region radius code. This was
replaced by an absolute value function, where ideally the reduction of power operations will increase the efficiency of the code.
The limit code is now obsolete, and needs to be revised in the future. */

// Section Details: Computation of elliptic geometry center point.
dx = radius * sin(tangent * pi); // Proper use of dx...
dy = abs( apex + ( radius * cos(tangent * pi)) - center ); // And also the proper use of dy!
b = ( dy / 2 ) * ( 1 + pow(( 1 + (( 2 * dy )/( m * dx ))), -1 )); // Currently verified to function properly for values over 0.5 * pi.
tanEQ = acos((dy/b) - 1); // Returns a value in radians.
a = dx / (sin(tanEQ));
datafield[ (3 + count) ] = apex - b; // Plot the coordinate of the ellipse center to the data vector.
datafield[ (4 + count) ] = b; // Plot the height of the ellipse.
datafield[ (5 + count) ] = a; // Plot the width of the ellipse.
datafield[ (6 + count) ] = tanEQ; // Plot the equivalent value in radians where the point of tangency exists on the ellipse.
/* Notes on section calculations: (a.) "dx" forms the width of a quadrilateral used in a geometric proof to find the center of an
ellipse. This is the same as the x-coordinate on the circle where the point of tangency exists.

(b.) "dy" forms the height of a quadrilateral used to find the center of an ellipse. The other sides of the quadrilateral are formed by
the tangent line "m" and dx', which is a length from the base of dx along the tangent line to where the tangent line intersects with the
horizontal line formed at the top of dy. Length dy is a measure from the apex of the ellipse to height of the point of tangency on the
circular section. This distance is calculated whith an absolute value function, where abs( x_1 - x_2 ) = distance. The apex is x_1, and
is simply an input value, while x_2 is -r * cos(t) + center. The simplified version of this is seen above.

(c.) The height of the ellipse b is determined from a geometric relation formed from the above calculations and previously aquired
information. If a rectangle is drawn, with height dy and width dx, a centerpoint exists at (dx/2, dy/2). A line can be drawn which
crosses through the centerpoint and the intersection of the tangent line with dx'. This line crosses through the local (non-shifted)
origin of the ellipse. This line, crossing between two definable points, has a definable angle between itself and dx'. Line dx' also has
a definable length, dx' = dx + (dy/m), where m is the slope of the tangent line. Inverse tangent may be used to compute the angle between
dx' and the line (which forms a hypotenuse) because the center coordinates and intersection coordinates are known. Tangent may be used to
find the height b of the ellipse because the angle and the length of a side (dx') are known. Because tan(arctan(t)) = t, the height of
the ellipse function reduces from a trigonometric function to an algebraic function. The reduced form of this function is shown above. I
may provide a more detailed proof of this in later writing.

(d.) Because the height of the ellipse, b, has been calculated, the height of the y-coordinate from the relative center can be calculated
as dy is also known. y = b - dy. This provides a useful relation in determining the equivalent measure of theta at the elliptical section
of the fuselage commences. With the conventions of this program, the simplified version reduces to what is seen in the code above.

(e.) Finally, the width of the ellipse must be known for elliptical points to be plotted in a file. Via the conventions, an
x-coordinate = a * sin(t), where a is the width of an ellipse. Because the x-coordinate is equal to dx = r * sin(t) at the point of
tangency, this value is known. From the previous calculation, the equivalent measure of theta with respect to the tangent slope is also
known. The equation thus reduces to a = dx/sin(t), as seen in the code above.

(f.) To shift the center of the elliptic section properly with respect to the circular section, the simple relation apex - b is used.

(g.) Revision notes: Proofs need proper detailing and better formatting in the future.*/
}

// CODE EXECUTION: FILE PARSING

// Section Details: Name file and write contents.
cout << "\nName the output file. NOTE: DO NOT ADD A FILE EXTENSION!\n\n";
cin >> filename;
filename = filename + extension;
File = fopen( filename.c_str(), "w" );
if ( File != NULL )
{
// Section Details: List start.
cout << "\nParsing...\n\n";

// Section Details: Initializes file syntax.
cout << "\n0\n" << endl; // Denotes start of file; "0" signifies measurements are in meters.
fputs( "0\n\n", File );

for (count = 0; count < stations; count = count + 7) // Again re-using the counter. Very boss-like and professional. Or something.
{
// Section Details: Establish initial numerics for parsing computations.
angle = 2 / double(verts); // Computes the number of degrees theta (with respect to pi) between each vertex.
dy = 2; // Re-use dy to count the vertex number plotted. Count pre-set to 2 so as to count for the upcoming vertex.

// Section Details: Plot first coordinate semi-manually.
cout << "\t" << datafield[ count ] << "\t0\t" << ((datafield[ (2 + count) ] * (-1)) + datafield[ (1 + count) ]) << "\n";
fprintf( File, "\t%1.9f\t%1.9f\t%1.9f\n", datafield[ count ], 0, datafield[ (1 + count) ] - datafield[ (2 + count) ] );

// Section Details: Lower hull geometry parser. This uses the circular section data.
for (dx = angle; dx < tangent; dx = dx + angle) // Plot up to the tangent point.
{
cout << "\t" << datafield[ count ] << "\t" << (datafield[ (2 + count) ] * sin(dx * pi)) << "\t"
<< ((datafield[ (2 + count) ] * (-1) * cos(dx * pi)) + datafield[ (1 + count) ]) << "\n";
fprintf( File, "\t%1.9f\t%1.9f\t%1.9f\n", datafield[ count ], ((datafield[ (2 + count) ] * sin(dx * pi))),
((datafield[ (2 + count) ] * (-1) * cos(dx * pi)) + datafield[ (1 + count) ]) );
dy++; // Count verticies...
}

// Section Details: Plot point of tangency. This uses the elliptic section data.
  cout << "\t" << datafield[ count ] << "\t" << (datafield[ (5 + count) ] * sin(datafield[ (6 + count) ])) << "\t"
<< ((datafield[ (4 + count) ] * (-1) * cos(datafield[ (6 + count) ])) + datafield[ (3 + count) ]) << "\n";
fprintf( File, "\t%1.9f\t%1.9f\t%1.9f\n", datafield[ count ], (datafield[ (5 + count) ] * sin(datafield[ (6 + count) ])),
((datafield[ (4 + count) ] * (-1) * cos(datafield[ (6 + count) ])) + datafield[ (3 + count) ]) );
dy++; // Count the vertex...

// Section Details: Prepare ellipse plotting calculations.
angle = (pi - datafield[ (6 + count) ]) / (((double(verts)/2) + 2) - dy); // Computes the number of radial degrees between verticies.
dx = angle; // Re-set dx as angle counter.
/* Notes on section calculations: (a.) The number of verticies on the side of a station is equivalent to the total number of vertices
desired for use in the station divided by two, plus one. This is because one vertex exists at the very top, while one exists at the
bottom. This assumes the number of verticies is even, which is enforced by the prior code. This formula, as incorporated into the
angle code, adds two due to the fore-count of counter dy: ((verts/2) + 1) - (dy - 1) = (verts/2) + 2 - dy.

(b.) Because pi is the top of the hull section, subtracting the equivalent radial degree of the tangent point on the ellipse from it
will yield the number of radial degrees to be traversed. Recall once more that variable tanEQ is measured in radians. By subtracting
the number of counted verts placed on the station to this point, dy, from dx (part (a.)) the number of verticies to be plotted can be
determined. Finally, dividing the number of degrees to be traversed by the number of verticies to be plotted yields the number of
degrees between each vertex to be plotted on the elliptical section. (Section will need revision in the future.) */

// Section Details: Parse elliptic hull sections.
while ( dy < ((verts / 2) + 1) ) // Somewhat sloppy revision to the code. Will be fixed in the future.
{
cout << "\t" << datafield[ count ] << "\t" << (datafield[ (5 + count) ] * sin(datafield[ (6 + count) ] + dx)) << "\t"
<< ((datafield[ (4 + count) ] * (-1) * cos(datafield[ (6 + count) ] + dx)) + datafield[ (3 + count) ]) << "\n";
fprintf( File, "\t%1.9f\t%1.9f\t%1.9f\n", datafield[ count ], (datafield[ (5 + count) ] * sin(datafield[ (6 + count) ] +dx)),
((datafield[ (4 + count) ] * (-1) * cos(datafield[ (6 + count) ] + dx)) + datafield[ (3 + count) ]) );
dx = dx + angle; // Augment that angle!
dy++; // Count that vertex!
}

// Section Details: Plot the final coordinate semi-manually for great justice, and to ensure no errors occur.
cout << "\t" << datafield[ count ] << "\t0\t" << (datafield[ (4 + count) ] + datafield[ (3 + count) ]) << "\n\n";
fprintf( File, "\t%1.9f\t%1.9f\t%1.9f\n\n", datafield[ count ], 0, datafield[ (4 + count) ] + datafield[ (3 + count) ] );
}

// Section Details: Finalizes file syntax.
cout << "\nEOF\n\n" << endl; // Ends the parsing of the file.
fputs( "\nEOF", File );

// Section Details: Close file and report.
fclose( File );
cout << "\nFile written. Check directory for output.\n\n";
}

return 0;
}

The first and last lines each for each of the station's y-coordinates are bugged! I have no idea why, and I have no idea of what the problem might be. I cleaned up the arithmetic for the y-coordinate of the first line, and there wasn't anything to do on the last line, but I'm baffled and pretty angry at this point. This needs to be done and over, and right when I'm ready to be done and over... this. If there are any bright ideas for why I'm getting this output, please do tell.
« Last Edit: July 25, 2012, 08:28:16 pm by Thaeris »
"trolls are clearly social rejects and therefore should be isolated from society, or perhaps impaled."

-Nuke



"Look on the bright side, how many release dates have been given for Doomsday, and it still isn't out yet.

It's the Duke Nukem Forever of prophecies..."


"Jesus saves.

Everyone else takes normal damage.
"

-Flipside

"pirating software is a lesser evil than stealing but its still evil. but since i pride myself for being evil, almost anything is fair game."


"i never understood why women get the creeps so ****ing easily. i mean most serial killers act perfectly normal, until they kill you."


-Nuke

 

Offline z64555

  • 210
  • Self-proclaimed controls expert
    • Minecraft
    • Steam
Re: Simple Programming, Calculus, and Geometry
Quick update for those who have been following. Thaeris got on #SCP's IRC channel yesterday, and we managed to figure out his problem was due to this:

Code: [Select]
fprintf( File, "\t%1.9f\t%1.9f\t%1.9f\n", datafield[ count ], 0, datafield[ (1 + count) ] - datafield[ (2 + count) ] );
The constant, 0, was interpreted as an integer by Thaeris's compiler. fprintf did not like that (since it was expecting a float or double) and corrupted whatever entries that came behind it.

Additionally, thanks to a suggestion by Valathil, Thaeris modified the entries so that no actual math was done in fprintf, and instead stored the results of the math in a temp variable and fprint'ed those variables.

So hopefully, that'll be the end of that headache for now.
Secure the Source, Contain the Code, Protect the Project
chief1983

------------
funtapaz: Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Juche.
z64555: s/J/Do
BotenAlfred: <funtapaz> Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Douche.

 

Offline Thaeris

  • Can take his lumps
  • 211
  • Away in Limbo
Re: Simple Programming, Calculus, and Geometry
Doing math in fprintf caused no problems on my end, and I have no intention of changing that at this stage of programming. When I have an update of my workings, I will let you know.

However, I did find that:

Code: [Select]
double(0)

...was a more elegant solution than wrapping the term in a variable (thus, thank you for the suggestion). Once again, however, for the time being, I'll put together something first before I make an update.
"trolls are clearly social rejects and therefore should be isolated from society, or perhaps impaled."

-Nuke



"Look on the bright side, how many release dates have been given for Doomsday, and it still isn't out yet.

It's the Duke Nukem Forever of prophecies..."


"Jesus saves.

Everyone else takes normal damage.
"

-Flipside

"pirating software is a lesser evil than stealing but its still evil. but since i pride myself for being evil, almost anything is fair game."


"i never understood why women get the creeps so ****ing easily. i mean most serial killers act perfectly normal, until they kill you."


-Nuke

 

Offline Thaeris

  • Can take his lumps
  • 211
  • Away in Limbo
Re: Simple Programming, Calculus, and Geometry
At some point, moving this to the fan fiction and art section may be in order. In any sense, let's look at what our fuselage looks like at some angles in FreeShip. When asked to import the "surface" model which my program exports, I select 48 vertical sections (twice the number of plotted stations) and 100 stringers for the side:





Note that each little "x" on a section line signifies the location of an ordered coordinate.

Now, let's observe the side profile with a rate-of-change curve applied:



Whoa... what's all this, you ask? The rate-of-change part is pretty self-explanitory in many regards, but it's still an eyeful the first time. A high spike on the line tells me that a high rate of change exists in a region, and it can also mean that there's a burr on the surface, or some other sort of sharp point. Going below the line and under tells me that the line has gone through a point of inflection, and the concavity of the line has changed. I do indeed want to avoid that - yet it's happening here! That defect is caused by the fact that two of my fuselage stations are below where their original apex points were to have been, because an elliptical section could not have mathematically existed at such a point while being contrained by the width of the given circular section with respect to the slope of the tangent line.  Thus, a bit of a redesign is in order from the dimensions of my original design (which were fed into the coordinate file written by my program and then fed into FreeShip). Fortunately, unlike using a conventional modeling program for that, I can simply specify the new parameters into my program, and then I can just copy and paste those parameters into the existing text file, unless I completely change the measure of the tangent slope line I'm using, which I will evaluate tonight.

You can see the effects of the inward-sloping fuselage section to an extent in this view:



It is better seen in AC3D, which is generally a much better choice for modeling than FreeShip:



That, I must fix. However, the radii of the circular parts is pretty much set, as seen by the dorsal profile:

"trolls are clearly social rejects and therefore should be isolated from society, or perhaps impaled."

-Nuke



"Look on the bright side, how many release dates have been given for Doomsday, and it still isn't out yet.

It's the Duke Nukem Forever of prophecies..."


"Jesus saves.

Everyone else takes normal damage.
"

-Flipside

"pirating software is a lesser evil than stealing but its still evil. but since i pride myself for being evil, almost anything is fair game."


"i never understood why women get the creeps so ****ing easily. i mean most serial killers act perfectly normal, until they kill you."


-Nuke

 

Offline z64555

  • 210
  • Self-proclaimed controls expert
    • Minecraft
    • Steam
Re: Simple Programming, Calculus, and Geometry
Is the plotted RoC along 2 axes or all 3? If it was along just 2 I believe it would be much more smooth, but on all 3 it's going to be bumpy like that (because of the tangental slope along the stations)

The negative RoC is troubling, though, as that means instead of peaking or flattening out, that part of the buttocks section is not the top of section curve's peak...
Secure the Source, Contain the Code, Protect the Project
chief1983

------------
funtapaz: Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Juche.
z64555: s/J/Do
BotenAlfred: <funtapaz> Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Douche.