Photolog

Through the Looking-Glass
2010-10-12: Through the Looking-Glass
My radio speaks is binary!
2010-10-10: My radio speaks is binary!
Gigaminx: (present for my birthday)
2010-09-16: Gigaminx: (present for my birthday)
Trini on bike
2010-09-05: Trini on bike
Valporquero
2010-08-28: Valporquero
My new bike!
2010-08-22: My new bike!
Mario and Ana's wedding
2010-08-13: Mario and Ana's wedding
Canyoning in Guara
2010-08-07: Canyoning in Guara
Trini and Mari in Marbella
2010-08-05: Trini and Mari in Marbella
Trini and Chelo in Tabarca
2010-08-03: Trini and Chelo in Tabarca
Valid XHTML 1.1
Log in
Back to list of problems

Center of Masses

10002.c

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

typedef struct {
	double x;
	double y;
} punto;

typedef struct {
	punto p1;
	punto p2;
} segmento;

typedef struct {
	punto p;
	double mass;
} gravity;

int n;
punto pu[120];
gravity ga[120];

static int
minang(int o, int nl, punto *li) {
	int i,m=!o;
	for (i=0; i<nl; i++) {
		if (i==o) continue;
		if ((li[i].x-li[o].x)*(li[m].y-li[o].y)
			> (li[i].y-li[o].y)*(li[m].x-li[o].x)) {
			m=i;
		}
	}
	return m;
}

int
convex_hull(int N, punto * li) {
	int i,m=0;
	punto p;
	for (i=1; i<N; i++) {
		double c = li[i].y - li[m].y;
		if (c<0) m=i;
		if (!c && (li[i].x < li[m].x)) m=i;
	}
	p=li[0]; li[0]=li[m]; li[m]=p;
	i=0; m=1;
	while (1) {
		i = minang(m-1, N, li);
		if (i==0) return m;
		p=li[m]; li[m]=li[i]; li[i]=p;
		m++;
	}
}

double
modulo(punto p) {
	return sqrt(p.x*p.x + p.y*p.y);
}
punto
psub(punto p1, punto p2) {
	punto p;
	p.x = p1.x - p2.x;
	p.y = p1.y - p2.y;
	return p;
}
#define dist(a,b) modulo(psub(a,b))

double
coordy(segmento s, double x, int *ok) {
	if (s.p2.x == s.p1.x) {
		*ok = 0;
		return 0.0;
	}
	*ok = 1;
	return s.p1.y + (x-s.p1.x)*(s.p2.y-s.p1.y)/(s.p2.x-s.p1.x);
}

punto
corte(segmento s1, segmento s2, int *ok) {
	punto p;
	double A,B;
	*ok = 1;
	if (s1.p1.x == s1.p2.x) {
		p.x = s1.p1.x;
		p.y = coordy(s2, p.x, ok);
		return p;
	}
	if (s2.p1.x == s2.p2.x) {
		p.x = s2.p1.x;
		p.y = coordy(s1, p.x, ok);
		return p;
	}
	A = (s1.p2.y - s1.p1.y) / (s1.p2.x - s1.p1.x);
	B = (s2.p2.y - s2.p1.y) / (s2.p2.x - s2.p1.x);
	if (A==B) {
		*ok=0;
		return p;
	}
	p.x = (s2.p1.y - s1.p1.y + A*s1.p1.x - B*s2.p1.x) / (A-B);
	p.y = s1.p1.y + A*(p.x-s1.p1.x);
	return p;
}

gravity
grav_tri(punto p1, punto p2, punto p3) {
	gravity g;
	segmento s1, s2;
	int ok;
	double s = (dist(p1,p2) + dist(p2,p3) + dist(p1,p3))/2.0;

	s1.p1 = p1;
	s1.p2.x = (p2.x+p3.x)/2.0;
	s1.p2.y = (p2.y+p3.y)/2.0;

	s2.p1 = p2;
	s2.p2.x = (p1.x+p3.x)/2.0;
	s2.p2.y = (p1.y+p3.y)/2.0;

	g.p = corte(s1, s2, &ok);
	if (!ok) abort();
	g.mass = sqrt(s*(s-dist(p1,p2))*(s-dist(p2,p3))*(s-dist(p1,p3)));
	return g;
}

gravity
add_grav(gravity g1, gravity g2) {
	gravity g;
	g.mass = g1.mass + g2.mass;
	g.p.x = (g1.mass*g1.p.x + g2.mass*g2.p.x) / g.mass;
	g.p.y = (g1.mass*g1.p.y + g2.mass*g2.p.y) / g.mass;
	return g;
}

int
main(void) {
	int i;

	while (1) {
		scanf("%d", &n);
		if (n<3) {
			break;
		}
		for (i=0; i<n; i++) {
			scanf("%lf %lf", &pu[i].x, &pu[i].y);
		}

#if 0
		if (convex_hull(n, pu) != n) abort();
#endif
		n = convex_hull(n, pu);

		for (i=1; i<n-1; i++) {
			ga[i-1] = grav_tri(pu[0], pu[i], pu[i+1]);
		}
		for (i=1; i<n-2; i++) {
			ga[0] = add_grav(ga[0], ga[i]);
		}
		printf("%.3f %.3f\n", ga[0].p.x, ga[0].p.y);
	}
	return 0;
}