src/misc.cpp

changeset 500
cad8cdc42a64
parent 498
791c831c8020
child 501
8f314f3f5054
--- a/src/misc.cpp	Sun Oct 06 21:37:05 2013 +0300
+++ b/src/misc.cpp	Wed Oct 16 15:32:38 2013 +0300
@@ -25,6 +25,8 @@
 #include "dialogs.h"
 #include "ui_rotpoint.h"
 
+RingFinder g_RingFinder;
+
 // Prime number table.
 const int g_primes[NUM_PRIMES] =
 {	2,    3,    5,    7,   11,   13,   17,   19,   23,   29,
@@ -181,7 +183,7 @@
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-void simplify (short& numer, short& denom)
+void simplify (int& numer, int& denom)
 {	bool repeat;
 
 	do
@@ -274,7 +276,7 @@
 str join (initlist<StringFormatArg> vals, str delim)
 {	QStringList list;
 
-for (const StringFormatArg & arg : vals)
+	for (const StringFormatArg& arg : vals)
 		list << arg.value();
 
 	return list.join (delim);
@@ -301,3 +303,46 @@
 	delete[] buf;
 	return fval;
 }
+
+// =============================================================================
+// This is the main algorithm of the ring finder. It tries to use math to find
+// the one ring between r0 and r1. If it fails (the ring number is non-integral),
+// it finds an intermediate radius (ceil of the ring number times scale) and
+// splits the radius at this point, calling this function again to try find the
+// rings between r0 - r and r - r1.
+//
+// This does not always yield into usable results. If at some point r == r0 or
+// r == r1, there is no hope of finding the rings, at least with this algorithm,
+// as it would fall into an infinite recursion.
+// -----------------------------------------------------------------------------
+bool RingFinder::findRings (double r0, double r1)
+{	// Find the scale and number of a ring between r1 and r0.
+	double scale = r1 - r0;
+	double num = r0 / scale;
+
+	// If the ring number is integral, we have found a fitting ring to r0 -> r1!
+	if (isInteger (num))
+	{	SolutionComponent cmp;
+		cmp.scale = scale;
+		cmp.num = (int) ceil (num);
+		m_solution << cmp;
+	}
+	else
+	{	// If not, find an intermediate <r> between the radii
+		double r = ceil (num) * scale;
+
+		// If r is the same as r0 or r1, we simply cannot find any rings between
+		// r0 and r1. Stop and return failure.
+		if (isZero (r0 - r) || isZero (r1 - r))
+			return false;
+
+		// Split this ring into r0 -> r and r -> r1. Recurse to possibly find
+		// the rings for these. If either recurse fails, the entire algorithm
+		// fails as well.
+		if (!findRings (r0, r) || !findRings (r, r1))
+			return false;
+	}
+
+	// The algorithm did not fail, thus we succeeded!
+	return true;
+}
\ No newline at end of file

mercurial