News Uni Dev Res Blag

SEPPLES -REVISITED-

2010/09/17 - 13:57

view old (non-inheritance) version
/* Dimensions - futanari linepoint implementation
 * Copyright (C) 2010  ed <irc.rizon.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, version 2, as
 * published by the Free Software Foundation.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, please refer to the following URL:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 */


/* Updated @ 2010/09/24 (12:03)
 * Added code to find shortest distance between a point and a line,
 * as well as the coordinates on which this line intersects with P,
 * effectively solving the third assignment as well.
 *
 * Updated @ 2010/10/01 (13:43)
 * Finished task 3 by implementing distance measurement through
 * inheritance of the CLine class. SOME ENTERPRISE UP IN HURR
 */


/* USER'S MANUAL
 * I don't even know
 */


/* ed@neetbook:~$ make clean; make && ./dimensions.bin
 * <TODO> add stdout pasta nevermind
 */

output

Finner korteste avstand til (11,10) fra
linjestk. (7,15) |19.3132| (25,8) ...

(Punkt på linje) |avstand| (mål):
(12.168,12.9902) |3.21024| (11,10)

makefile

#Dimensions makefile

dimensions.bin : main.o cdist.o cline.o cpoint.o kit.o
	g++ -o dimensions.bin main.o cdist.o cline.o cpoint.o kit.o

main.o: main.cpp awesome.h
	g++ -c main.cpp

cdist.o: cdist.cpp awesome.h
	g++ -c cdist.cpp

cline.o: cline.cpp awesome.h
	g++ -c cline.cpp

cpoint.o: cpoint.cpp awesome.h
	g++ -c cpoint.cpp

kit.o: kit.cpp awesome.h
	g++ -c kit.cpp

clean:
	rm *.o *.bin

#EOF

awesome.h

#pragma once
#include <iostream>
#include <cstring>
#include <cmath>
using std::endl;
using std::cin;
using std::cout;
using std::string;
using std::ostream;
#include "cpoint.h"
#include "cline.h"
#include "cdist.h"
#include "kit.h"

cpoint.h

#pragma once
#include "awesome.h"

class CLine;
class CPoint {
	private:
		bool m_3D;
		double m_x, m_y, m_z;
	public:
		friend class CLine;
		CPoint(double x, double y, double z);
		CPoint(double x, double y);
		CPoint();
		double getx();
		double gety();
		double getz();
		bool is3D();
		CLine operator+(CPoint &o);
		friend ostream &operator<< (ostream &s, const CPoint &p);
};

cline.h

#pragma once
#include "awesome.h"

class CPoint;
class CLine {
	protected:
		CPoint m_a, m_b;
	public:
		CLine(double x, double y, double z, double xb, double yb, double zb);
		CLine(double x, double y, double xb, double yb);
		CLine(CPoint &a, CPoint &b);
		CLine();
		CPoint geta();
		CPoint getb();
		double length();
		CLine operator* (double fact);
		CLine operator+ (CLine &o);
		CLine operator+ (double len);
		friend ostream &operator<< (ostream &s, CLine &p);
};

cdist.h

#pragma once
#include "awesome.h"

class CDist : public CLine {
	public:
		CLine distance(CPoint o, bool debug);
};

kit.h

#pragma once
#include "awesome.h"

void err(string msg);

main.h

#pragma once
#include "awesome.h"

// hurr

cpoint.cpp

#include "awesome.h"
#include "cpoint.h"

CPoint::CPoint() {};
CPoint::CPoint(double x, double y) {
	m_3D = false;
	m_x = x;
	m_y = y;
	m_z = 0;
}
CPoint::CPoint(double x, double y, double z) {
	m_3D = true;
	m_x = x;
	m_y = y;
	m_z = z;
}
double CPoint::getx() {return m_x;}
double CPoint::gety() {return m_y;}
double CPoint::getz() {return m_z;}
CLine CPoint::operator+(CPoint &o) {
	if ((*this).m_3D != o.m_3D) {
		err("Appending 2D and 3D point");
	}
	return CLine(*this, o);
}
ostream &operator<< (ostream &s, const CPoint &p) {
	s << "(" << p.m_x << "," << p.m_y;
	if (p.m_3D)     s << "," << p.m_z;
	s << ")";
	return s;
}

cline.cpp

#include "awesome.h"
#include "cline.h"

CLine::CLine(){};
CLine::CLine(CPoint &a, CPoint &b) {
	if (a.m_3D != b.m_3D) {
		err("Constructing using 2D and 3D point");
	}
	m_a = a;
	m_b = b;
}
CLine::CLine(double x, double y, double xb, double yb) {
	m_a = CPoint(x, y);
	m_b = CPoint(xb, yb);
}
CLine::CLine(double x, double y, double z, double xb, double yb, double zb) {
	m_a = CPoint(x, y, z);
	m_b = CPoint(xb, yb, zb);
}
CPoint CLine::geta() {return m_a;}
CPoint CLine::getb() {return m_b;}

double CLine::length() {
	if (m_a.m_3D) return sqrt(
		pow(m_b.m_x - m_a.m_x, 2) +
		pow(m_b.m_y - m_a.m_y, 2) +
		pow(m_b.m_z - m_a.m_z, 2));
	else return sqrt(
		pow(m_b.m_x - m_a.m_x, 2) +
		pow(m_b.m_y - m_a.m_y, 2));
}
CLine CLine::operator* (double fact) {
	CPoint b;
	if (m_a.m_3D) {
		b = CPoint(
			m_a.m_x + (m_b.m_x - m_a.m_x) * fact,
			m_a.m_y + (m_b.m_y - m_a.m_y) * fact,
			m_a.m_z + (m_b.m_z - m_a.m_z) * fact);
	} else {
		b = CPoint(
			m_a.m_x + (m_b.m_x - m_a.m_x) * fact,
			m_a.m_y + (m_b.m_y - m_a.m_y) * fact);
	}
	return CLine(m_a, b);
}
CLine CLine::operator+ (CLine &o) {
	CPoint b;
	if (m_a.m_3D != o.m_a.m_3D) {
		err("Appending 2D and 3D line");
	} else {
		double dx = o.m_b.m_x - o.m_a.m_x;
		double dy = o.m_b.m_y - o.m_a.m_y;
		double dz = o.m_b.m_z - o.m_a.m_z;
		if (m_a.m_3D) {
			b = CPoint(
				m_b.m_x + dx,
				m_b.m_y + dy,
				m_b.m_z + dz);
		} else {
			b = CPoint(
				m_b.m_x + dx,
				m_b.m_y + dy);
		}
	}
	return CLine(m_a, b);
}
CLine CLine::operator+ (double len) {
	//len /= length();
	double dx = len * (m_b.m_x - m_a.m_x);
	double dy = len * (m_b.m_y - m_a.m_y);
	double dz = len * (m_b.m_z - m_a.m_z);
	if (m_a.m_3D) return CLine(
		m_a.m_x,
		m_a.m_y,
		m_a.m_z,
		dx + m_a.m_x,
		dy + m_a.m_y,
		dz + m_a.m_z);
	else return CLine(
		m_a.m_x,
		m_a.m_y,
		dx + m_a.m_x,
		dy + m_a.m_y);
}
ostream &operator<< (ostream &s, CLine &l) {
	s << l.geta() << " |" << l.length() << "| " << l.getb();
	return s;
}

cdist.cpp

#include "awesome.h"
#include "cdist.h"

/* Fullstendig klar over at dette ikke er verdens beste
 * fremgangsmåte, men antok at jeg ville lære mer av å lage
 * en selvutviklet løsning enn ved å implementere en formel.
 * 
 * Starter på midten av linjen, sammenlikner punktene 1/4
 * linjelengde til venstre og høyre. Deler stepsize på to
 * og gjentar rundt det nærmeste punktet til stepsize er
 * ubetydelig liten.
 */

CLine CDist::distance(CPoint o, bool debug) {
	CLine res;
	double pos = 0.50; //relative position on line [0..1]
	double stp = 0.25; //next stepsize to use
	while (stp > 0.000001) {
		CLine ba = *this + (pos+stp);
		CLine bb = *this + (pos-stp);
		CLine da = ba.getb() + o;
		CLine db = bb.getb() + o;
		double dla = da.length();
		double dlb = db.length();
		
		if (debug) {
			cout << pos << "(" << stp << ")? "
				<< ba.getb() << "@" << dla << ", "
				<< bb.getb() << "@" << dlb << endl;
		}
		
		if (fabs(fabs(dla)-fabs(dlb))<0.0001) {
			// do nothing, just reduce stepsize
		} else if (dla<dlb) {
			pos += stp;
			res = da;
		} else {
			pos -= stp;
			res = db;
		}
		stp /= 2;
	}
	return res;
}

kit.cpp

#include "awesome.h"
#include "kit.h"

void err(string msg) {
	cout << " -!- " << msg << endl;
}

main.cpp

#include "awesome.h"

int main(int argc, char **argv) {
	CPoint pa(7, 15);
	CPoint pb(25, 8);
	CPoint pc(11, 10);
	CLine lz = pa + pb;
	CDist la = (CDist&)lz;

	cout << "Finner korteste avstand til " << pc <<
		" fra\nlinjestk. " << lz << " ...\n\n";

	CLine res = la.distance(pc, false);
	cout << "(Punkt på linje) |avstand| (mål):\n" << res << endl;
}

/* Debug-kode for å teste minnebehandling etc:
 * CLine lz = pa + pb;  //19.313207916, 25.0 8.0 (null)
 * CLine lb = la + 0.9; //17.381887124, 23.2 8.7 (16.2 6.3)
 * CLine lc = la + 0.8; //15.450566333, 21.4 9.4 (14.4 5.6)
 * cout << la << endl; //OK
 * cout << lb << endl; //OK?
 * cout << lc << endl; //OK?
 * cout << la << endl; //OK!
 * cout << endl;
 */

Copyright © 2010 Ed Edland