Convex hull length in C - c

Im making a program to calculate convex hull length of 2D points.
On the input there is a number of points n and then the coordinates of each point.
for example:
6
-8 -3
-6 1
-5 -2
-3 1
-3 4
2 18
and output is simply the length of the convex hull.
my code looks like this so far:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct point
{
double x;
double y;
}POINT,VECTOR;
POINT b[1000];
VECTOR normal;
int n;
int upper_lower(int i, VECTOR ab, double c) {
double x, y,result;
y = b[i].y;
x = normal.x*b[i].x;
result = -(x + c) / normal.y;
if (y>result) return 1;
if (y == result) return 0;
else
return -1;
}
int ccw(VECTOR v,VECTOR v2)
{
double cp;
cp = v2.x*v.y - v2.y*v.x;
if (cp == abs(cp)) return 1;
else
return -1;
}
double vector_length(VECTOR v)
{
return sqrt(pow(v.x, 2) + pow(v.y, 2));
}
int cmp_points(const void *p1, const void *p2)
{
const POINT *pt1 = p1;
const POINT *pt2 = p2;
// do primary compare on x
if (pt1->x > pt2->x)
return 1;
if (pt1->x < pt2->x)
return -1;
// pt1->x == pt2->x - do secondary compare on y...
if (pt1->y > pt2->y)
return 1;
if (pt1->y < pt2->y)
return -1;
// pt1 == pt2
return 0;
}
int main()
{
int i,poloha,upper[1000],lower[1000],h=0,d=0;
scanf("%d", &n);
if (n <= 0 && n > 1000) return 0;
for (i = 0; i < n; i++)
{
scanf("%lf %lf", &b[i].x, &b[i].y);
}
qsort(b, n, sizeof(POINT), cmp_points);
//split in half
VECTOR ab;
double c;
ab.x = b[n - 1].x - b[0].x;
ab.y = b[n - 1].y - b[0].y;
normal.x = -ab.y;
normal.y = ab.x;
c = -normal.x*b[0].x - (normal.y*b[0].y);
for (i = 0; i < n; i++)
{
poloha = upper_lower(i,ab,c);
if (poloha == 1) upper[h++] = i;
if (poloha == -1) lower[d++]=i;
if (poloha == 0)
{
upper[h++] = i;
lower[d++] = i;
}
}
int j = 0;
double v, length = 0;
VECTOR v1, v2, v3,v4;
v3.x = 0; v3.y = 0;
//lower part
for (i = 0; ; i++)
{
int in = 0;
if (lower[i + 2] < 0)
{
v1.x = b[lower[i + 1]].x - b[lower[0]].x;
v1.y = b[lower[i + 1]].y - b[lower[0]].y;
v2.x = b[lower[i]].x - b[lower[i + 1]].x;
v2.y = b[lower[i]].y - b[lower[i + 1]].y;
lenght += vector_length(v1);
length += vector_length(v2);
break;
}
v1.x = b[lower[i + 1]].x - b[lower[i]].x;
v1.y = b[lower[i + 1]].y - b[lower[i]].y;
v2.x = b[lower[i + 2]].x - b[lower[i]].x;
v2.y = b[lower[i + 2]].y - b[lower[i]].y;
in = ccw(v1, v2);
if (in == 1)
{
length += vector_length(v1);
v3 = v2;
v4 = v1;
}
if (in == -1)
{
length -= vector_length(v4);
if (v3.x != 0 && v3.y != 0)
{
length += vector_length(v3);
v3.x = 0; v3.y = 0;
}
else
{
length += vector_length(v2);
}
}
}
printf("%.3lf", length);
return 0;
}
the problem is that in the last part where I try to compute the length...I just dont know how to finish it..no matter what I try it never works as I want to. Could you guys give me some advice?

I can't see a standard answer, so here's the algorithm:
Choose a point roughly in the centre of your point cloud. Then sort the points radially, by angle from the centre. The topmost point must be in the convex hull, so define it as having an angle of 0.0 and being first in the list.
Now go though. Put point 2 in the "tentative" hull list. Then check point 3. If the angle P1-P2-P3 is concave (relative to the centre point), remove P2 from the list, if it is convex, keep it. Continue like this, backtracking and removing points if they go concave. You only need two points in your "tentative" list, once you have three, they become definite.
You stop when you go full circle and get back to P1.

There are many known convex hull algorithms, one of the simplest of which is the gift wrapping algorithm. Here's an implementation that fits in your program where the points have been input and sorted:
int j = 0; // after sorting, b[0] is leftmost point, must be on an edge
double length = 0;
VECTOR v1, v2, vv;
v1.x = 0, v1.y = 1; // start by measuring angles from vertical
int iv; // index of next edge point
do // find next egde point by minimum angle
{
double lv1 = vector_length(v1), lv2, lv;
double cv = -1; // minimal possible cosine value
for (i = 0; i < n; ++i) if (i != j)
{ // compute cosine of angle between v1 and (b[j]-->b[i]) = v2
v2.x = b[i].x-b[j].x, v2.y = b[i].y-b[j].y;
double c = (v1.x*v2.x + v1.y*v2.y) / lv1 / (lv2 = vector_length(v2));
if (c > cv) cv = c, iv = i, lv = lv2, vv = v2; // new maximum cosine
}
if (v == -1) break;
// printf("%d:%f,%f-->%d:%f,%f = %f\n", j, b[j], iv, b[iv], lv);
length += lv;
v1 = vv; // found edge is new reference edge
} while (j = iv); // repeat while not at start again
printf("%.3lf\n", length);

Related

What is wrong with my breadth first search algorithm, it crashes with a segmentation fault?

When I run my code it throws a segmentation fault and I have tried rewriting the code several times. Still to no avail, it won't even run. The segmentation fault happens as soon as my program is launched. What it's supposed to do is print a path on screen using the ncurses library in Linux, from the given coordinates. Here is the problematic snippet with the lines where gdb said the segmentation fault was, also it (snippet) reproduces the problem.
EDIT: This will help explain what I'm trying to do, but using dynamic arrays. Breadth First Search
EDIT 2: The variable frontier is supposed to keep track of the X and Y values at a specific index. The add_neighbors function is there to add all four neighbors (providing they aren't already added) to the frontier and came_from arrays.
frontier[index][0] is X value.
frontier[index][1] is Y value.
The before the first while loop I set the start position x1 and y1. During the first while loop, it increments getting the new coordinates from the frontier, then processing and adding to came_from array.
For example:
(x1,y1) (x1+1,y1)
(x1,y1+1) (x1+1,y1+1)
(x1,y2) (x2,y2)
I'm trying to get from (x1,y1) to (x2,y2). Sure hope that explains it better. What I'm trying to implement is a Breadth First Search (BFS) algorithm. Using two arrays, one is frontier (keeps track of visited positions) and came_from (keeps track of X and Y the path from x1,y1 to x2,y2). Updated the code to reflect the first answer. Plus added a comment to explain where the error might be, not really sure but I've been debugging it. It looks like the came_from array never gets set with x and y.
The Code:
/*
* pathfind.c - Simple Breadth First Search algorithm implementation.
*
* Author: Philip R. Simonson
* Date : 05/17/2021
*
****************************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ncurses.h>
#define MAXHEIGHT 24
#define MAXWIDTH 80
/* Add neighboring positions to the arrays.
*/
int add_neighbors(int **frontier, int ***came_from, int count, int x, int y)
{
// North
if(y > 0 && came_from[y - 1][x][0] < 0) {
frontier[count][0] = x;
frontier[count][1] = y;
count++;
came_from[y - 1][x][0] = x;
came_from[y - 1][x][1] = y;
}
// South
if(y < MAXHEIGHT-1 && came_from[y + 1][x][0] < 0) {
frontier[count][0] = x;
frontier[count][1] = y;
count++;
came_from[y + 1][x][0] = x;
came_from[y + 1][x][1] = y;
}
// West
if(x > 0 && came_from[y][x - 1][0] < 0) {
frontier[count][0] = x;
frontier[count][1] = y;
count++;
came_from[y][x - 1][0] = x;
came_from[y][x - 1][1] = y;
}
// East
if(x < MAXWIDTH-1 && came_from[y][x + 1][0] < 0) {
frontier[count][0] = x;
frontier[count][1] = y;
count++;
came_from[y][x + 1][0] = x;
came_from[y][x + 1][1] = y;
}
return count; // Return counter for frontier
}
/* Simple BFS algorithm for path finding.
*/
void path_finding(int x1, int y1, int x2, int y2)
{
int **frontier, ***came_from;
int index, count;
int i, j;
index = 0;
count = 0;
// Initialise frontier array
frontier = malloc(sizeof(int *) * MAXHEIGHT * MAXWIDTH);
for(i = 0; i < (MAXHEIGHT * MAXWIDTH); i++) {
frontier[i] = malloc(sizeof(int) * 2);
}
// Create came_from array
came_from = malloc(sizeof(int **) * MAXHEIGHT);
for(i = 0; i < MAXHEIGHT; i++) {
came_from[i] = malloc(sizeof(int *) * MAXWIDTH);
for(j = 0; j < MAXWIDTH; j++) {
came_from[i][j] = malloc(sizeof(int) * 2);
came_from[i][j][0] = -1;
came_from[i][j][1] = -1;
}
}
// Add start to came_from
came_from[y1][x1][0] = -9;
came_from[y1][x1][1] = -9;
// Add start to frontier
frontier[count][0] = x1;
frontier[count][1] = y1;
count++;
while(index < count) {
int x = frontier[index][0];
int y = frontier[index][1];
index++;
if(x == x2 && y == y2)
break;
count = add_neighbors(frontier, came_from, count, x, y);
}
// Set temp position variables to end position
{
int x = x2;
int y = y2;
while(x != x1 || y != y1) {
int tempy = y;
mvprintw(y, x, "*");
// Segmentation fault because came_from[tempy][x][1] and came_from[tempy][x][0]
// always equals -1 which is out of bounds. Not sure how to fix it, something
// is wrong with add_neighbors function I think.
y = came_from[tempy][x][1];
x = came_from[tempy][x][0];
}
}
// TODO: Return came_from array!
// Free all resources from both arrays
for(i = 0; i < MAXHEIGHT; i++) {
for(j = 0; j < MAXWIDTH; j++) {
free(came_from[i][j]);
}
free(came_from[i]);
}
free(came_from);
for(i = 0; i < (MAXHEIGHT * MAXWIDTH); i++) {
free(frontier[i]);
}
free(frontier);
}
int main(void)
{
initscr();
noecho();
clear();
path_finding(0, 2, 7, 8);
refresh();
getch();
endwin();
return 0;
}
Compile with: cc -o test test.c -lncurses
GDB output:
[philip#darkstar temp]$ gdb --batch --ex r --ex bt --ex q temp
Program received signal SIGSEGV, Segmentation fault.
0x000055555555599d in path_finding (x1=0, y1=2, x2=7, y2=8) at src/pathfind.c:117
117 y = came_from[tempy][x][1];
#0 0x000055555555599d in path_finding (x1=0, y1=2, x2=7, y2=8) at src/pathfind.c:117
#1 0x00005555555551ff in main () at src/main.c:11
A debugging session is active.
Inferior 1 [process 65294] will be killed.
Quit anyway? (y or n) [answered Y; input not from terminal]
[philip#darkstar temp]$
Some of the allocation sizes are incorrect:
frontier = malloc(sizeof(frontier) * MAXHEIGHT * MAXWIDTH); should be
frontier = malloc(sizeof(*frontier) * MAXHEIGHT * MAXWIDTH);
frontier[i] = malloc(sizeof(*frontier) * 2); should read:
frontier[i] = malloc(sizeof(frontier[i][0]) * 2);
These accesses are not properly protected:
if(y <= MAXHEIGHT && came_from[y + 1][x][0] < 0) should be
if (y < MAXHEIGHT-1 && came_from[y + 1][x][0] < 0)
if(x <= MAXWIDTH && came_from[y][x + 1][0] < 0) should be
if(x < MAXWIDTH-1 && came_from[y][x + 1][0] < 0)
the frontier array is not initialized. You should use calloc() to intialize the int arrays to 0 or run an initialization loop.
in the while (x != x1 || y != y1) loop, when you read y = came_from[tempy][x][1] you do not check that y >= 0. Since you initialized came_from[y1][x1][0] = -9; it way be negative and cause an out of bounds access during the next iteration as you set tempy = y.
the algorithm is not obvious from the code, you might want to comment more for the reader's sake.

How to check if rectilinear polygons intersect

I am trying to create a program in C to check if the lines of rectilinear polygon intersect each other at any point.
I only need simple rectilinear polygons that do not intersect at any point. It can be counter-clockwise or clockwise.
The direction values will be less than 10. NS direction must alternate with WE direction and vice versa.
The inputs being passed are in the form of direction from an input file such as; and also shown in the pictures:
S 2 E 4 S 2 E 4 N 2 W 4 N 2 W 4
I tried to store points in a two-dimensional array with every point being checked as true, but I am unable to figure out how to move in case of counter and clockwise direction as the points could be N4 E6 or S4 W6. In such a case if I add when the value is N-4 (x,y) = (0,4) and subtract when S-4 (x,y) = (0,-4) that would fail when using it as index in array.
int arr[10][10];
int xPrime = 0, yPrime = 0;
bool checkContinuity(int y, const char * dir ){
if(strcmp(dir, "S")==0){
y = -y;
cols = y;
int j;
for(j = cols; j >= 0; j--){
if(arr[xPrime][j] == 1 && j != yPrime){
return false;
}
arr[xPrime][j] = 1;
printf(" %d ", j);
}
yPrime -= y;
if(yPrime < 0)
yPrime = -yPrime;
}
else if(strcmp(dir, "W")==0){
y = -y;
cols = y;
int j;
for(j = cols; j >= 0; j--){
if(arr[j][yPrime] == 1 && j != xPrime && (j != 0 && yPrime != 0)){
return false;
}
arr[j][yPrime] = 1;
printf(" %d ", j);
}
xPrime -= y;
if(xPrime < 0)
xPrime = -xPrime;
}
else if(strcmp(dir, "N")==0){
cols = y;
int j;
for(j = 0; j <= cols; j++){
if(arr[xPrime][j] == 1)
return false;
arr[xPrime][j] = 1;
printf(" %d ", j);
}
yPrime += y;
}
else if(strcmp(dir, "E")==0){
cols = y;
int j;
for(j = 0; j <= cols; j++){
if(arr[j][yPrime] == 1 && j != xPrime)
return false;
arr[j][yPrime] = 1;
printf(" %d ", j);
}
xPrime += y;
}
else
return false;
return true;
}
It might be easier to store the actual polygon rather than all possible
points of the plane. We are then not restricted by the choice of the
point array (arr in your code). See this working example:
the polygon is stored in the int-array P = {0, 0, x1, y1, x2, y2, ...}
segments are two-point polygons. The function 'intersection' checks if
two such segments Q and P intersect;
if so, returns the intersection coordinates.
It uses the helper function 'between' to ckeck if one number is between two others.
the function 'next' calculates the next point of the polygon, assuming
the input is provided as char-string (eg: "S2E4S2E4N2W4N2W4")
In the function main we now loop over all segments, and check if they intersect with
any previous one.
Of course, the input should at some point be checked for sanity etc.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void
next( const char *s,
int *v )
{
v[2] = v[0];
v[3] = v[1];
int step = s[1] - '0';
switch(s[0]) {
case 'S': v[3] -= step; break;
case 'N': v[3] += step; break;
case 'W': v[2] -= step; break;
case 'E': v[2] += step; break;
}
}
int
between( int x,
int a,
int b )
{
return a < b ? x >= a && x <= b : x >= b && x <= a;
}
int
intersection( int *P,
int *Q,
int *R )
{
if(P[0] == P[2] && Q[1] == Q[3]){ // P vertical, Q horizontal (w.l.o.g.)
if(between(P[0], Q[0], Q[2]) && between(Q[1], P[1], P[3])){
R[0] = P[0];
R[1] = Q[1];
return 1;
} else
return 0;
}else if(Q[0] == Q[2] && P[1] == P[3])
return intersection(Q, P, R);
else return 0;
}
int
main() {
char *s = "S2E4S2E4N2W4N2W4";
int n = strlen(s) / 2, // number of steps
*P = calloc((n + 1) * 2, sizeof(int)), // polygon
R[2]; // intersection
if(!P) exit(137);
for(int k = 0; k < n; k++){
next(s + 2 * k, P + 2 * k);
for(int j = 0; j < k - 1; j++) {
if(intersection(P + k * 2, P + j * 2, R)) {
printf("Intersection at: %d, %d\n", R[0], R[1]);
exit(0);
}
}
}
printf("No intersection\n");
}

Program in C , working with 3 digits but not working with 5 digits

145 = sum of 1! + 4! + 5!. I need to write a program in C, that finds the 5 digit numbers that have this property.
I have written the code successfully for the 3 digits. I used the same code for 5 digits, but it cant find any number.
I would like to help me with my solution, in order for me to see where am I wrong.
#include <stdio.h>
int factorial(int n);
main() {
int pin[5];
int q = 1;
int w = 0;
int e = 0;
int r = 0;
int t = 0;
int result = 0;
int sum = 0;
for (q = 1; q <= 9; q++) {
for (w = 0; w <= 9; w++) {
for (e = 0; e <= 9; e++) {
for (r = 0; r <= 9; r++) {
for (t = 0; t <= 9; t++) {
pin[0] = q;
pin[1] = w;
pin[2] = e;
pin[3] = r;
pin[4] = t;
int factq = factorial(q);
int factw = factorial(w);
int facte = factorial(e);
int factr = factorial(r);
int factt = factorial(t);
sum = factq + factw + facte + factr + factt;
result = 10000 * q + 1000 * w + 100 * e + 10 * r + t * 1;
if (sum == result)
printf("ok");
}
}
}
}
}
}
int factorial(int n) {
int y;
if (n == 1) {
y = 1;
} else if (n == 0)
y = 0;
else {
y = n * factorial(n - 1);
return y;
}
}
Your factorial function doesn't return a value in all cases:
int factorial (int n) {
int y;
if (n==1) {
y = 1;
}
else
if (n==0)
y = 0;
else {
y = n * factorial(n-1);
return y;
}
}
It only returns a value when it makes a recursive call. The base cases don't return anything. Failing to return a value from a function and then attempting to use that value invokes undefined behavior.
Move the return statement to the bottom of the function so it gets called in all cases. Also the value of 0! is 1, not 0.
int factorial (int n) {
int y;
if (n<=1)
y = 1;
else
y = n * factorial(n-1);
return y;
}
Also, when you find the target value you probably want to print it:
printf("ok: %d\n", result);
dbush's answer is accurate in pointing out why your code didn't work. This is an alternative solution to reduce the amount of calculation done by your program by not re-calculating the factorial of each numeral every step of the way. The way your program currently works, it winds up being around 500,000 calls to the factorial function from your nested loop, and then in turn recursively calls the function on average 4ish times for each call from the nested loop, so that's around 2 million calls to factorial. The more digits you tack on, the faster that number grows and more expensive it gets. To avoid all these recalculations, you can create a Look-up table that stores the factorial of the numerals [0-9] and just looks them up as needed.
You can calculate these values ahead of time and initialize your LUT with these values, but if hypothetically you wanted them to be calculated by the program because this is a programming assignment where you can't cut out such a step, it is still pretty trivial to populate the LUT.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
void populate_lut(uint32_t *lut);
int main(void) {
// lut is an array holding the factorials of numerals 0-9
uint32_t lut[10];
populate_lut(lut);
for (uint8_t q = 1; q <= 9; q++) {
for (uint8_t w = 0; w <= 9; w++) {
for (uint8_t e = 0; e <= 9; e++) {
for (uint8_t r = 0; r <= 9; r++) {
for (uint8_t t = 0; t <= 9; t++) {
// now instead of calculating these factorials, just look them up in the look-up table
uint32_t sum = lut[q] + lut[w] + lut[e] + lut[r] + lut[t];
uint32_t result = 10000 * q + 1000 * w + 100 * e + 10 * r + t * 1;
if (sum == result) {
printf("Solution: %" PRIu32 "\n", result);
}
}
}
}
}
}
}
// populate your lookup table with the factorials of digits 0-9
void populate_lut(uint32_t *lut) {
lut[0] = 1;
lut[1] = 1;
for(uint8_t i = 2; i < 10; ++i) {
lut[i] = lut[i-1] * i;
}
}

implementation of trapezoidal numerical integration in C

I'm trying to implement numerical integration using the trapezoidal approximation using this formula :
My problem is I don't get how to implement this correctly. To test I wrote a file with 22050 double values all equal to 2 like :
....................
value =2.0;
for ( index = 0 ; index < 22050;index++){
fwrite(&value,sizeof(double),1,inp2);
}
to keep the question simple, say I want to the integral value of each 100 samples:
X Area integral value
0-100 should be 200
100-200 should be 200
..... ...........
22000-22050 should be 100
to do that I 've wrote a program that should do that but the result that get is 4387950 for 100 samples here is my code :
..............................
// opening the files
double* inputData= NULL;
unsigned int N = 100;
double h= 0.0;
unsigned int index= 0;
FILE* inputFile=NULL;
double value =0.0;
int i =0,j=0;
inputFile = fopen("sinusD","rb");
outputFile=fopen("Trapez","wb+");
if( inputFile==NULL || outputFile==NULL){
printf("Couldn't open the files \n");
return -1;
}
inputData = (double*) malloc(sizeof(double)*N);
h=22050/2;
while((i = fread(inputData,sizeof(double),N,inputFile))==N){
value += inputData[0] +inputData[N];
for(index=1;index<N;index++){
value+=(2*inputData[index]);
}
value *=h;
fprintf(outputFile,"%lf ",value);
value =0;
}
if(i!=0){
value = 0;
i=-i;
printf("i value %i\n", i);
fseek(inputFile,i*sizeof(double),SEEK_END);
fread(inputData,sizeof(double),i,inputFile);
for(index=0;index<-i;index++){
printf("index %d\n",index);
value += inputData[0] +inputData[i];
value+=(2*inputData[index]);
}
value *=h;
fprintf(outputFile,"%lf ",value);
value =0;
}
fclose(inputFile);
fclose(outputFile);
free(inputData);
return 0;}
any idea how to do that ?
UPDATE
while((i = fread(inputData,sizeof(double),N,inputFile))==N){
value = (inputData[0] + inputData[N])/2.0;
for(index=1;index<N;index++){
value+=inputData[index];
}
value *=h;
fprintf(outputFile,"%lf ",value);
printf(" value %lf\n",value);
value =0;
}
I get 199.000 as a result for each segment .
Why you didn't start with something simple. Let's say you have the following data {1,2,3,4,5,6,7,8,9,10} and assume h = 1. This is simple,
#include <stdio.h>
#define SIZE 10
int main()
{
double a[SIZE] = {1,2,3,4,5,6,7,8,9,10}, sum = 0.0, trapz;
int h = 1;
int i = 0;
for ( i; i < SIZE; ++i){
if ( i == 0 || i == SIZE-1 ) // for the first and last elements
sum += a[i]/2;
else
sum += a[i]; // the rest of data
}
trapz = sum*h; // the result
printf("Result: %f \n", trapz);
return 0;
}
This is the result
Result: 49.500000
Double check your work with Matlab:
Y = [1 2 3 4 5 6 7 8 9 10];
Q = trapz(Y)
Q =
49.5000
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
Edit: For your question in the comment:
This is the matlab code:
X = 0:pi/100:pi; % --> h = pi/100
Y = sin(X); % get values as many as the size of X
Q = trapz(X,Y);
Q =
1.9998
Now to fulfil same scenario in C, do the following
#include <stdio.h>
#include <math.h>
#define SIZE 101
#define PI 3.14159265358
int main()
{
double X[SIZE], Y[SIZE], incr = 0.0, h = PI/100.0, sum = 0.0, trapz;
int i = 0, k = 0, j = 0;
// Generate samples
for ( i; i < SIZE; ++i)
{
X[i] = incr;
incr += h;
}
// Generate the function Y = sin(X)
for ( k; k < SIZE; ++k)
{
Y[k] = sin(X[k]);
}
// Compute the integral of sin(X) using Trapezoidal numerical integration method
for ( j; j < SIZE; ++j){
if ( j == 0 || j == SIZE-1 ) // for the first and last elements
sum += Y[j]/2;
else
sum += Y[j]; // the rest of data
}
trapz = sum * h; // compute the integral
printf("Result: %f \n", trapz);
return 0;
}
The result is
Result: 1.999836
First, your equation is correct, so that's a good start. However, there are a number of variable declarations that you don't supply in your question, so we're left to guess.
First, let's start with the math. For the integral from 0 to 100 to equal 200 with each value being equal to 2.0 implies that h = 1 but your code seems to use a value of 22050/2 which is probably not really what you want.
The code within the loop should look like this:
double value = (inputData[0] + inputData[N])/2.0;
for(index = 1; index < N; ++index){
value += inputData[index];
}
value *= h;
This will give the integral from 0 to N. If you wish to calculate between two arbitrary values, you will have to modify the code appropriately:
int a = 100; // lower limit
int b = 200; // upper limit
double value = (inputData[a] + inputData[b])/2.0;
for(index = a+1; index < b; ++index){
value += inputData[index];
}
value *= h;
As a full example of use, here's a program to calculate the integral of sin(x) from x=pi/4 to x=pi/2:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define M_PI 3.14159265358979323846
int main()
{
int a = 45; // 45 degrees = pi/4 radians
int b = 90; // 90 degrees = pi/2 radians
double h = M_PI/180; // how far apart are samples?
double *inputData = malloc(360*sizeof(double));
if (inputData == NULL) {
printf("Error: ran out of memory!\n");
exit(1);
}
for (int i=0; i<360; ++i)
inputData[i] = sin(i*h);
double value = (inputData[a] + inputData[b])/2.0;
for (int index = a+1; index < b; ++index)
value += inputData[index];
value *= h;
printf("integral from %d to %d = %f\n", a, b, value);
double expected = 1.0/sqrt(2);
printf("(expected value = %f, error = %f)\n", expected, expected-value);
free(inputData);
}
Output from this program on my machine:
integral from 45 to 90 = 0.707089
(expected value = 0.707107, error = 0.000018)

Triangulation algorithm

I've decided to create a simple demo, dividing a polygon into triangle set. Here what i've got so far:
A sequential vertex list is given (P1) forming polygon edges (polygon is not convex in most cases); a triangle set is needed
Loop through all the vertices within the polygon P1 and find the one (v), which will satisfy next clauses:
remove v from polygon and save the new one to P2 previous vertex to v
connected to its next one form a
line which do not cross any of P2
edges
v is not inside P2
If these are satisfied, we can replace P1 with (P2 + triangle( prev(v), v, next(v)) ) and repeat this action until P1 contains more than 3 vertices.
So, the questions are: is this algorithm correct and how it could be implemented using C / C++ using the most obvious and simple way?
I think you're describing the ear clipping method. There's code for that method at http://cs.smith.edu/~orourke/books/ftp.html ; it's the code described in the book Computational Geometry in C.
Seems that i'm done with this algorithm implementation. Please, verify it someone. Thanks!
typedef struct Point
{
float x, y;
};
class MooPolygon
{
private:
vector<Point> points;
int isVertexEar(int n, const vector<Point> &p)
{
return (isVertexInsideNewPoly(n, p) && !isEdgeIntersect(n, p));
}
int isEdgeIntersect(int n, const vector<Point> &p)
{
Point v = p[n];
vector<Point> a;
for (size_t i = 0; i < p.size(); i++)
if (i != n)
a.push_back(p[i]);
int c = 0, cnt = a.size(), prev = (cnt + (n - 1)) % cnt, next = n % cnt;
Point v1 = a[prev], v2 = a[next];
for (size_t i = 0, j = cnt - 1; i < cnt; j = i++)
{
if (prev == i || prev == j || next == i || next == j)
continue;
Point v4 = a[j], v3 = a[i];
float denominator = ((v4.y - v3.y) * (v2.x - v1.x)) - ((v4.x - v3.x) * (v2.y - v1.y));
if (!denominator)
continue;
float ua = (((v4.x - v3.x) * (v1.y - v3.y)) - ((v4.y - v3.y) * (v1.x - v3.x))) / denominator;
float ub = (((v2.x - v1.x) * (v1.y - v3.y)) - ((v2.y - v1.y) * (v1.x - v3.x))) / denominator;
//float x = v1.x + (ua * (v2.x - v1.x)), y = v1.y + (ua * (v2.y - v1.y));
if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1)
{
c = 1;
break;
}
}
return c;
}
int isVertexInsideNewPoly(int n, const vector<Point> &p)
{
Point v = p[n];
vector<Point> a;
for (size_t i = 0; i < p.size(); i++)
if (i != n)
a.push_back(p[i]);
int c = 1;
for (size_t i = 0, j = a.size() - 1; i < a.size(); j = i++)
{
if ((((a[i].y <= v.y) && (v.y < a[j].y)) || ((a[j].y <= v.y) && (v.y < a[i].y))) && (v.x > (a[j].x - a[i].x) * (v.y - a[i].y) / (a[j].y - a[i].y) + a[i].x))
c = !c;
}
return c;
}
float dist(Point a, Point b)
{
return sqrt( ((a.x - b.x) * (a.x - b.x)) + (((a.y - b.y) * (a.y - b.y))) );
}
public:
void push(const Point &p)
{
for (size_t i = 0; i < points.size(); i++)
{
if (dist(points[i], p) < 7.f)
{
points.push_back(points[i]);
return;
}
}
points.push_back(p);
}
void pop()
{
if (points.size() > 0)
points.pop_back();
}
void clear()
{
points.clear();
}
Point v(int index)
{
return points[index];
}
size_t size()
{
return points.size();
}
void triangulate()
{
vector<Point> a;
for (size_t i = 0; i < points.size(); i++)
{
a.push_back(points[i]);
}
points.clear();
for (size_t t = a.size() - 1, i = 0, j = 1; i < a.size(); t = i++, j = (i + 1) % a.size())
{
if (a.size() == 3)
{
points.push_back(a[0]);
points.push_back(a[1]);
points.push_back(a[2]);
break;
}
if (isVertexEar(i, a))
{
points.push_back(a[t]);
points.push_back(a[i]);
points.push_back(a[j]);
a.erase(a.begin() + i, a.begin() + i + 1);
t = a.size() - 1;
i = 0;
j = 1;
}
}
}
};
The code has an error on the line below. The line is in the for loop in the push() function of your class:
points.push_back(points[i]);
You are not passing the pushed Point, but an empty element of the vector itself. I changed the line to
points.push_back(p);
and it worked.

Resources