Browse Source

Implemented text comparison that allow rounding errors.

David Piuva 5 years ago
parent
commit
d504a28f46
1 changed files with 51 additions and 1 deletions
  1. 51 1
      Source/SDK/sandbox/sprite/spriteAPI.cpp

+ 51 - 1
Source/SDK/sandbox/sprite/spriteAPI.cpp

@@ -952,6 +952,56 @@ void sprite_generateFromModel(ImageRgbaU8& targetAtlas, String& targetConfigText
 	}
 }
 
+static bool isDigit(DsrChar c) {
+	return c >= U'0' && c <= U'9';
+}
+static bool isValue(DsrChar c) {
+	return c == U'-' || c == U'.' || isDigit(c);
+}
+
+// Allowing the last decimals to deviate a bit because floating-point operations are rounded differently between computers
+static bool approximateTextMatch(const ReadableString &a, const ReadableString &b, double tolerance = 0.00002) {
+	int readerA = 0, readerB = 0;
+	while (readerA < a.length() && readerB < b.length()) {
+		DsrChar charA = a[readerA];
+		DsrChar charB = b[readerB];
+		if (isValue(charA) && isValue(charB)) {
+			// Scan forward on both sides while consuming content and comparing the actual value
+			int startA = readerA;
+			int startB = readerB;
+			// Only move forward on valid characters
+			if (a[readerA] == U'-') { readerA++; }
+			if (b[readerB] == U'-') { readerB++; }
+			while (isDigit(a[readerA])) { readerA++; }
+			while (isDigit(b[readerB])) { readerB++; }
+			if (a[readerA] == U'.') { readerA++; }
+			if (b[readerB] == U'.') { readerB++; }
+			while (isDigit(a[readerA])) { readerA++; }
+			while (isDigit(b[readerB])) { readerB++; }
+			// Approximate values
+			double valueA = string_parseDouble(a.exclusiveRange(startA, readerA));
+			double valueB = string_parseDouble(b.exclusiveRange(startB, readerB));
+			// Check the difference
+			double diff = valueB - valueA;
+			if (diff > tolerance || diff < -tolerance) {
+				// Too big difference, this is probably not a rounding error
+				return false;
+			}
+		} else if (charA != charB) {
+			// Difference with a non-value involved
+			return false;
+		}
+		readerA++;
+		readerB++;
+	}
+	if (readerA < a.length() - 1 || readerB < b.length() - 1) {
+		// One text had unmatched remains after the other reached its end
+		return false;
+	} else {
+		return true;
+	}
+}
+
 void sprite_generateFromModel(const Model& visibleModel, const Model& shadowModel, const OrthoSystem& ortho, const String& targetPath, int cameraAngles, bool debug) {
 	// Generate an image and a configuration file from the visible model
 	ImageRgbaU8 atlasImage; String configText;
@@ -980,7 +1030,7 @@ void sprite_generateFromModel(const Model& visibleModel, const Model& shadowMode
 		// Save the configuration
 		String configPath = targetPath + U".ini";
 		String oldConfixText = string_load(configPath, false);
-		if (string_match(configText, oldConfixText)) {
+		if (approximateTextMatch(configText, oldConfixText)) {
 			printText("  No significant changes against ", targetPath, ".\n\n");
 		} else {
 			string_save(targetPath + U".ini", configText);