diff --git a/source/import/importero3dv.js b/source/import/importero3dv.js index 704d530..46542ea 100644 --- a/source/import/importero3dv.js +++ b/source/import/importero3dv.js @@ -115,6 +115,13 @@ OV.ImporterO3dv = class extends OV.ImporterBase let smooth = OV.ValueOrDefault (parameters.smooth, true); const mesh = OV.GenerateSphere (genParams, parameters.radius, segments, smooth); this.model.AddMesh (mesh); + } else if (meshContent.type === 'platonic') { + if (parameters.solid_type === undefined) { + return; + } + let radius = OV.ValueOrDefault (parameters.radius, 1.0); + const mesh = OV.GeneratePlatonicSolid (genParams, parameters.solid_type, radius); + this.model.AddMesh (mesh); } } }; diff --git a/source/model/generator.js b/source/model/generator.js index db1843d..16bc57e 100644 --- a/source/model/generator.js +++ b/source/model/generator.js @@ -261,3 +261,137 @@ OV.GenerateSphere = function (genParams, radius, segments, smooth) return generator.GetMesh (); }; + +OV.GeneratePlatonicSolid = function (genParams, type, radius) +{ + function AddVertex (generator, radius, x, y, z) + { + let vertex = new OV.Coord3D (x, y, z); + vertex.MultiplyScalar (radius / vertex.Length ()); + generator.AddVertex (vertex.x, vertex.y, vertex.z); + } + + if (OV.IsZero (radius)) { + return null; + } + + let generator = new OV.Generator (genParams); + if (type === 'tetrahedron') { + let a = 1.0; + AddVertex (generator, radius, +a, +a, +a); + AddVertex (generator, radius, -a, -a, +a); + AddVertex (generator, radius, -a, +a, -a); + AddVertex (generator, radius, +a, -a, -a); + generator.AddTriangle (0, 1, 3); + generator.AddTriangle (0, 2, 1); + generator.AddTriangle (0, 3, 2); + generator.AddTriangle (1, 2, 3); + } else if (type === 'hexahedron') { + let a = 1.0; + AddVertex (generator, radius, +a, +a, +a); + AddVertex (generator, radius, +a, +a, -a); + AddVertex (generator, radius, +a, -a, +a); + AddVertex (generator, radius, +a, -a, -a); + AddVertex (generator, radius, -a, +a, +a); + AddVertex (generator, radius, -a, +a, -a); + AddVertex (generator, radius, -a, -a, +a); + AddVertex (generator, radius, -a, -a, -a); + generator.AddConvexPolygon ([0, 1, 5, 4]); + generator.AddConvexPolygon ([0, 2, 3, 1]); + generator.AddConvexPolygon ([0, 4, 6, 2]); + generator.AddConvexPolygon ([1, 3, 7, 5]); + generator.AddConvexPolygon ([2, 6, 7, 3]); + generator.AddConvexPolygon ([4, 5, 7, 6]); + } else if (type === 'octahedron') { + let a = 1.0; + let b = 0.0; + AddVertex (generator, radius, +a, +b, +b); + AddVertex (generator, radius, -a, +b, +b); + AddVertex (generator, radius, +b, +a, +b); + AddVertex (generator, radius, +b, -a, +b); + AddVertex (generator, radius, +b, +b, +a); + AddVertex (generator, radius, +b, +b, -a); + generator.AddTriangle (0, 2, 4); + generator.AddTriangle (0, 3, 5); + generator.AddTriangle (0, 4, 3); + generator.AddTriangle (0, 5, 2); + generator.AddTriangle (1, 2, 5); + generator.AddTriangle (1, 3, 4); + generator.AddTriangle (1, 4, 2); + generator.AddTriangle (1, 5, 3); + } else if (type === 'dodecahedron') { + let a = 1.0; + let b = 0.0; + let c = (1.0 + Math.sqrt (5.0)) / 2.0; + let d = 1.0 / c; + AddVertex (generator, radius, +a, +a, +a); + AddVertex (generator, radius, +a, +a, -a); + AddVertex (generator, radius, +a, -a, +a); + AddVertex (generator, radius, -a, +a, +a); + AddVertex (generator, radius, +a, -a, -a); + AddVertex (generator, radius, -a, +a, -a); + AddVertex (generator, radius, -a, -a, +a); + AddVertex (generator, radius, -a, -a, -a); + AddVertex (generator, radius, +b, +d, +c); + AddVertex (generator, radius, +b, +d, -c); + AddVertex (generator, radius, +b, -d, +c); + AddVertex (generator, radius, +b, -d, -c); + AddVertex (generator, radius, +d, +c, +b); + AddVertex (generator, radius, +d, -c, +b); + AddVertex (generator, radius, -d, +c, +b); + AddVertex (generator, radius, -d, -c, +b); + AddVertex (generator, radius, +c, +b, +d); + AddVertex (generator, radius, -c, +b, +d); + AddVertex (generator, radius, +c, +b, -d); + AddVertex (generator, radius, -c, +b, -d); + generator.AddConvexPolygon ([0, 8, 10, 2, 16]); + generator.AddConvexPolygon ([0, 16, 18, 1, 12]); + generator.AddConvexPolygon ([0, 12, 14, 3, 8]); + generator.AddConvexPolygon ([1, 9, 5, 14, 12]); + generator.AddConvexPolygon ([1, 18, 4, 11, 9]); + generator.AddConvexPolygon ([2, 10, 6, 15, 13]); + generator.AddConvexPolygon ([2, 13, 4, 18, 16]); + generator.AddConvexPolygon ([3, 14, 5, 19, 17]); + generator.AddConvexPolygon ([3, 17, 6, 10, 8]); + generator.AddConvexPolygon ([4, 13, 15, 7, 11]); + generator.AddConvexPolygon ([5, 9, 11, 7, 19]); + generator.AddConvexPolygon ([6, 17, 19, 7, 15]); + } else if (type === 'icosahedron') { + let a = 1.0; + let b = 0.0; + let c = (1.0 + Math.sqrt (5.0)) / 2.0; + AddVertex (generator, radius, +b, +a, +c); + AddVertex (generator, radius, +b, +a, -c); + AddVertex (generator, radius, +b, -a, +c); + AddVertex (generator, radius, +b, -a, -c); + AddVertex (generator, radius, +a, +c, +b); + AddVertex (generator, radius, +a, -c, +b); + AddVertex (generator, radius, -a, +c, +b); + AddVertex (generator, radius, -a, -c, +b); + AddVertex (generator, radius, +c, +b, +a); + AddVertex (generator, radius, +c, +b, -a); + AddVertex (generator, radius, -c, +b, +a); + AddVertex (generator, radius, -c, +b, -a); + generator.AddTriangle (0, 2, 8); + generator.AddTriangle (0, 4, 6); + generator.AddTriangle (0, 6, 10); + generator.AddTriangle (0, 8, 4); + generator.AddTriangle (0, 10, 2); + generator.AddTriangle (1, 3, 11); + generator.AddTriangle (1, 4, 9); + generator.AddTriangle (1, 6, 4); + generator.AddTriangle (1, 9, 3); + generator.AddTriangle (1, 11, 6); + generator.AddTriangle (2, 5, 8); + generator.AddTriangle (2, 7, 5); + generator.AddTriangle (2, 10, 7); + generator.AddTriangle (3, 5, 7); + generator.AddTriangle (3, 7, 11); + generator.AddTriangle (3, 9, 5); + generator.AddTriangle (4, 8, 9); + generator.AddTriangle (5, 9, 8); + generator.AddTriangle (6, 11, 10); + generator.AddTriangle (7, 10, 11); + } + return generator.GetMesh (); +}; diff --git a/test/testfiles/o3dv/solids.o3dv b/test/testfiles/o3dv/solids.o3dv new file mode 100644 index 0000000..54d778b --- /dev/null +++ b/test/testfiles/o3dv/solids.o3dv @@ -0,0 +1,54 @@ +{ + "meshes" : [ + { + "type" : "platonic", + "parameters" : { + "solid_type" : "tetrahedron", + "radius" : 1.0 + }, + "transformation" : { + "translation" : [0.0, 0.0, 0.0] + } + }, + { + "type" : "platonic", + "parameters" : { + "solid_type" : "hexahedron", + "radius" : 1.0 + }, + "transformation" : { + "translation" : [0.0, 0.0, 3.0] + } + }, + { + "type" : "platonic", + "parameters" : { + "solid_type" : "octahedron", + "radius" : 1.0 + }, + "transformation" : { + "translation" : [3.0, 0.0, 0.0] + } + }, + { + "type" : "platonic", + "parameters" : { + "solid_type" : "dodecahedron", + "radius" : 1.0 + }, + "transformation" : { + "translation" : [3.0, 0.0, 3.0] + } + }, + { + "type" : "platonic", + "parameters" : { + "solid_type" : "icosahedron", + "radius" : 1.0 + }, + "transformation" : { + "translation" : [6.0, 0.0, 1.5] + } + } + ] +} diff --git a/test/tests/generator_test.js b/test/tests/generator_test.js index 135547d..9ee13df 100644 --- a/test/tests/generator_test.js +++ b/test/tests/generator_test.js @@ -39,4 +39,26 @@ describe ('Generator', function () { assert (OV.IsSolid (cylinder)); assert (OV.IsEqualEps (OV.CalculateVolume (cylinder), Math.PI * 0.5 * 0.5 * 0.5 * 4.0 / 3.0, 0.1)); }); + + it ('Platonic Solids', function () { + let tetrahedron = OV.GeneratePlatonicSolid (null, 'tetrahedron', 1.0); + assert (OV.IsSolid (tetrahedron)); + assert (OV.IsEqual (OV.CalculateVolume (tetrahedron), 0.5132002392796676)); + + let hexahedron = OV.GeneratePlatonicSolid (null, 'hexahedron', 1.0); + assert (OV.IsSolid (hexahedron)); + assert (OV.IsEqual (OV.CalculateVolume (hexahedron), 1.5396007178390028)); + + let octahedron = OV.GeneratePlatonicSolid (null, 'octahedron', 1.0); + assert (OV.IsSolid (octahedron)); + assert (OV.IsEqual (OV.CalculateVolume (octahedron), 1.3333333333333333)); + + let dodecahedron = OV.GeneratePlatonicSolid (null, 'dodecahedron', 1.0); + assert (OV.IsSolid (dodecahedron)); + assert (OV.IsEqual (OV.CalculateVolume (dodecahedron), 2.7851638631226248)); + + let icosahedron = OV.GeneratePlatonicSolid (null, 'icosahedron', 1.0); + assert (OV.IsSolid (icosahedron)); + assert (OV.IsEqual (OV.CalculateVolume (icosahedron), 2.5361507101204093)); + }); });