commit 4830256131d61d59e7ff8945beb44990f469a04e Author: mattmcw Date: Sun Aug 27 20:06:37 2023 -0400 Start porting to Typescript. C++ next diff --git a/c14n_stl.js b/c14n_stl.js new file mode 100644 index 0000000..e4eddfa --- /dev/null +++ b/c14n_stl.js @@ -0,0 +1,46 @@ +function cmz(x) { + return x === '-0' ? '0' : x; +} +var Vertex = /** @class */ (function () { + function Vertex(_x, _y, _z) { + this.x = _x; + this.y = _y; + this.z = _z; + this.key = [parseFloat(_x), parseFloat(_y), parseFloat(_z)]; + } + return Vertex; +}()); +var Normal = /** @class */ (function () { + function Normal(_dx, _dy, _dz) { + this.dx = _dx; + this.dy = _dy; + this.dz = _dz; + } + return Normal; +}()); +var Facet = /** @class */ (function () { + function Facet(_normal, _v1, _v2, _v3) { + this.normal = _normal; + } + return Facet; +}()); +/* +class Facet: + def __init__(self, normal, v1, v2, v3): + self.normal = normal + if v1.key < v2.key: + if v1.key < v3.key: + self.vertices = (v1, v2, v3) #v1 is the smallest + else: + self.vertices = (v3, v1, v2) #v3 is the smallest + else: + if v2.key < v3.key: + self.vertices = (v2, v3, v1) #v2 is the smallest + else: + self.vertices = (v3, v1, v2) #v3 is the smallest + + def key(self): + return (self.vertices[0].x, self.vertices[0].y, self.vertices[0].z, + self.vertices[1].x, self.vertices[1].y, self.vertices[1].z, + self.vertices[2].x, self.vertices[2].y, self.vertices[2].z) + */ diff --git a/c14n_stl.py b/c14n_stl.py new file mode 100644 index 0000000..9ba5d4d --- /dev/null +++ b/c14n_stl.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python + +# +# NopSCADlib Copyright Chris Palmer 2018 +# nop.head@gmail.com +# hydraraptor.blogspot.com +# +# This file is part of NopSCADlib. +# +# NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the +# GNU General Public License as published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with NopSCADlib. +# If not, see . +# + +# +#! OpenSCAD produces randomly ordered STL files. This script re-orders them consistently so that GIT can tell if they have changed or not. +# +# OpenSCAD produces randomly ordered STL files so source control like GIT can't tell if they have changed or not. +# This scrip orders each triangle to start with the lowest vertex first (comparing x, then y, then z) +# It then sorts the triangles to start with the one with the lowest vertices first (comparing first vertex, second, then third) +# This has no effect on the model but makes the STL consistent. I.e. it makes a canonical form. +# + +from __future__ import print_function + +import sys + +def cmz(x): + ''' Convert "-0" to "0". ''' + return '0' if x == '-0' else x + +class Vertex: + def __init__(self, x, y, z): + self.x, self.y, self.z = x, y, z + self.key = (float(x), float(y), float(z)) + +class Normal: + def __init__(self, dx, dy, dz): + self.dx, self.dy, self.dz = dx, dy, dz + +class Facet: + def __init__(self, normal, v1, v2, v3): + self.normal = normal + if v1.key < v2.key: + if v1.key < v3.key: + self.vertices = (v1, v2, v3) #v1 is the smallest + else: + self.vertices = (v3, v1, v2) #v3 is the smallest + else: + if v2.key < v3.key: + self.vertices = (v2, v3, v1) #v2 is the smallest + else: + self.vertices = (v3, v1, v2) #v3 is the smallest + + def key(self): + return (self.vertices[0].x, self.vertices[0].y, self.vertices[0].z, + self.vertices[1].x, self.vertices[1].y, self.vertices[1].z, + self.vertices[2].x, self.vertices[2].y, self.vertices[2].z) + +class STL: + def __init__(self, fname): + self.facets = [] + + with open(fname) as f: + words = [cmz(s.strip()) for s in f.read().split()] + + if words[0] == 'solid' and words[1] == 'OpenSCAD_Model': + i = 2 + while words[i] == 'facet': + norm = Normal(words[i + 2], words[i + 3], words[i + 4]) + v1 = Vertex(words[i + 8], words[i + 9], words[i + 10]) + v2 = Vertex(words[i + 12], words[i + 13], words[i + 14]) + v3 = Vertex(words[i + 16], words[i + 17], words[i + 18]) + i += 21 + self.facets.append(Facet(norm, v1, v2, v3)) + + self.facets.sort(key = Facet.key) + else: + print("Not an OpenSCAD ascii STL file") + sys.exit(1) + + def write(self, fname): + mins = [float('inf'), float('inf'), float('inf')] + maxs = [float('-inf'), float('-inf'), float('-inf')] + with open(fname,"wt") as f: + print('solid OpenSCAD_Model', file=f) + for facet in self.facets: + print(' facet normal %s %s %s' % (facet.normal.dx, facet.normal.dy, facet.normal.dz), file=f) + print(' outer loop', file=f) + for vertex in facet.vertices: + print(' vertex %s %s %s' % (vertex.x, vertex.y, vertex.z), file=f) + for i in range(3): + ordinate = vertex.key[i] + if ordinate > maxs[i]: maxs[i] = ordinate + if ordinate < mins[i]: mins[i] = ordinate + print(' endloop', file=f) + print(' endfacet', file=f) + print('endsolid OpenSCAD_Model', file=f) + return mins, maxs + +def canonicalise(fname): + stl = STL(fname) + return stl.write(fname) + +if __name__ == '__main__': + if len(sys.argv) == 2: + canonicalise(sys.argv[1]) + else: + print("\nusage:\n\t c14n_stl file - Canonicalise an STL file created by OpenSCAD.") + sys.exit(1) \ No newline at end of file diff --git a/c14n_stl.ts b/c14n_stl.ts new file mode 100644 index 0000000..0598a55 --- /dev/null +++ b/c14n_stl.ts @@ -0,0 +1,61 @@ +function cmz (x : string) : string { + return x === '-0' ? '0' : x; +} + +class Vertex { + public x : string; + public y : string; + public z : string; + public key : number[]; + + constructor (_x : string, _y : string, _z : string) { + this.x = _x; + this.y = _y; + this.z = _z; + this.key = [parseFloat(_x), parseFloat(_y), parseFloat(_z)]; + } + + public compare (vka : number[], vkb : number[]) : number { + + } +} + +class Normal { + public dx : string; + public dy : string; + public dz : string; + + constructor (_dx : string, _dy : string, _dz : string) { + this.dx = _dx; + this.dy = _dy; + this.dz = _dz; + } +} + +class Facet { + public normal : Normal; + public key : number[]; + constructor (_normal : Normal, _v1 : Vertex, _v2 : Vertex, _v3 : Vertex) { + this.normal = _normal; + } +} +/* +class Facet: + def __init__(self, normal, v1, v2, v3): + self.normal = normal + if v1.key < v2.key: + if v1.key < v3.key: + self.vertices = (v1, v2, v3) #v1 is the smallest + else: + self.vertices = (v3, v1, v2) #v3 is the smallest + else: + if v2.key < v3.key: + self.vertices = (v2, v3, v1) #v2 is the smallest + else: + self.vertices = (v3, v1, v2) #v3 is the smallest + + def key(self): + return (self.vertices[0].x, self.vertices[0].y, self.vertices[0].z, + self.vertices[1].x, self.vertices[1].y, self.vertices[1].z, + self.vertices[2].x, self.vertices[2].y, self.vertices[2].z) + */ \ No newline at end of file diff --git a/compile_ts.sh b/compile_ts.sh new file mode 100644 index 0000000..598261c --- /dev/null +++ b/compile_ts.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +tsc --extendedDiagnostics -outFile c14n_stl.js c14n \ No newline at end of file