Exemple #1
0
        public void ThrowsOnArrayWriteWhenValueExpected()
        {
            var elements = new List <PlyElement>()
            {
                new PlyElement("vertex", 1, new List <PlyProperty>()
                {
                    new PlyProperty("x", PlyType.Float),
                }),
                new PlyElement("face", 1, new List <PlyProperty>()
                {
                    new PlyArrayProperty("vertex_index", PlyType.Int, PlyType.Int)
                })
            };

            var header = new PlyHeader(PlyFormat.Ascii, elements);

            using (var stream = new MemoryStream())
            {
                var writer = new PlyAsciiWriter(stream, header);
                Assert.Throws <UnexpectedDataTypeException>(() => writer.WriteArray(1, 2, 3));
                Assert.DoesNotThrow(() => writer.WriteValue(1.2f));
                Assert.Throws <UnexpectedDataTypeException>(() => writer.WriteValue(12.0f));
                Assert.Throws <InvalidOperationException>(() => writer.Dispose());
                Assert.DoesNotThrow(() => writer.WriteArray(1, 2, 3));
                Assert.DoesNotThrow(() => writer.Dispose());
            }
        }
Exemple #2
0
        public void ThrowsWhenTooManyValuesWritten()
        {
            var elements = new List <PlyElement>()
            {
                new PlyElement("vertex", 1, new List <PlyProperty>()
                {
                    new PlyProperty("x", PlyType.Float),
                }),
                new PlyElement("face", 1, new List <PlyProperty>()
                {
                    new PlyArrayProperty("vertex_index", PlyType.Int, PlyType.Int)
                })
            };

            var header = new PlyHeader(PlyFormat.Ascii, elements);

            using (var stream = new MemoryStream())
            {
                using (var writer = new PlyAsciiWriter(stream, header))
                {
                    writer.WriteValue(1.0f);
                    writer.WriteArray(new int[] { 12, 16, 45 });
                    Assert.Throws <InvalidOperationException>(() => writer.WriteArray(new int[] { 1, 2, 3 }));
                }
            }
        }
        public void Setup()
        {
            var elements = new List <PlyElement>()
            {
                new PlyElement("vertex", 3, new List <PlyProperty>()
                {
                    new PlyProperty("p1", PlyType.Char),
                    new PlyProperty("p2", PlyType.Double),
                    new PlyProperty("p3", PlyType.Float),
                    new PlyProperty("p4", PlyType.Int),
                    new PlyProperty("p5", PlyType.Short),
                    new PlyProperty("p6", PlyType.Uchar),
                    new PlyProperty("p7", PlyType.Uint),
                    new PlyProperty("p8", PlyType.Ushort),
                }),
                new PlyElement("face", 100000000, new List <PlyProperty>()
                {
                    new PlyArrayProperty("p1", PlyType.Char, PlyType.Int),
                    new PlyArrayProperty("p2", PlyType.Int, PlyType.Int),
                    new PlyArrayProperty("p3", PlyType.Short, PlyType.Int),
                    new PlyArrayProperty("p4", PlyType.Uchar, PlyType.Int),
                    new PlyArrayProperty("p5", PlyType.Uint, PlyType.Int),
                    new PlyArrayProperty("p6", PlyType.Ushort, PlyType.Int),
                })
            };

            ValidHeader = new PlyHeader(PlyFormat.Ascii, "Comment", null, elements);
        }
Exemple #4
0
 public PlyAsciiWriter(Stream targetStream, PlyHeader header)
     : base(targetStream, header)
 {
     if (header.Format != PlyFormat.Ascii)
     {
         throw new NotSupportedException($"The {nameof(PlyAsciiWriter)} does not support binary encoding.");
     }
     _writer = new StreamWriter(targetStream, Encoding.Default, 1024, leaveOpen: true);
 }
Exemple #5
0
        public PlyAsciiReader(ITextReader sourceReader, PlyHeader header)
            : base(header)
        {
            if (header.Format != PlyFormat.Ascii)
            {
                throw new NotSupportedException($"The {nameof(PlyAsciiReader)} does not support binary data.");
            }

            _textReader = sourceReader;
        }
Exemple #6
0
        /// <summary>
        /// Loads a ply file from the <see cref="Stream"/>.
        /// </summary>
        /// <param name="s">The stream containing the ply file.</param>
        public void Load(Stream s)
        {
            Header = new PlyHeader();
            Body   = new List <PlyElement>();
            var plyFileData = LoadPlyFile(s);

            Header = plyFileData.Item1;
            Body   = plyFileData.Item2;
            //var location = "";
            //DumpFileAsASCII(location, plyHeader, plyBody);
        }
        public void WritesCorrectlySimpleDecimals()
        {
            var simpleElements = new List <PlyElement>()
            {
                new PlyElement("vertex", 2, new List <PlyProperty>()
                {
                    new PlyProperty("x", PlyType.Float),
                    new PlyProperty("y", PlyType.Float),
                    new PlyProperty("z", PlyType.Float)
                }),
                new PlyElement("face", 2, new List <PlyProperty>()
                {
                    new PlyArrayProperty("vertex_index", PlyType.Int, PlyType.Int)
                })
            };

            var endianess    = BitConverter.IsLittleEndian ? PlyFormat.BinaryLittleEndian : PlyFormat.BinaryBigEndian;
            var simpleHeader = new PlyHeader(endianess, simpleElements);

            using (var memoryStream = new MemoryStream())
            {
                using (var writer = new PlyBinaryWriter(memoryStream, simpleHeader))
                {
                    writer.WriteValue(3.0f);
                    writer.WriteValue(5.1113f);
                    writer.WriteValue(-6.14f);

                    writer.WriteValue(3.0f);
                    writer.WriteValue(5.1113f);
                    writer.WriteValue(-6.14f);

                    writer.WriteArray(1, 2, 3);
                    writer.WriteArray(-1, 5, 9);
                }
                using (var reader = new BinaryReader(memoryStream))
                {
                    memoryStream.Seek(-sizeof(int) * 8 - sizeof(float) * 3, SeekOrigin.End);

                    Assert.AreEqual(3.0f, reader.ReadSingle());
                    Assert.AreEqual(5.1113f, reader.ReadSingle());
                    Assert.AreEqual(-6.14f, reader.ReadSingle());

                    Assert.AreEqual(3, reader.ReadInt32());
                    Assert.AreEqual(1, reader.ReadInt32());
                    Assert.AreEqual(2, reader.ReadInt32());
                    Assert.AreEqual(3, reader.ReadInt32());
                    Assert.AreEqual(3, reader.ReadInt32());
                    Assert.AreEqual(-1, reader.ReadInt32());
                    Assert.AreEqual(5, reader.ReadInt32());
                    Assert.AreEqual(9, reader.ReadInt32());
                }
            }
        }
Exemple #8
0
        public PlyBinaryReader(IBinaryReader binaryReader, PlyHeader header)
            : base(header)
        {
            if (header.Format == PlyFormat.Ascii)
            {
                throw new NotSupportedException($"The {nameof(PlyBinaryReader)} does not support ASCII encoded data.");
            }

            _binaryReader = binaryReader;
            bool littleEndian = header.Format == PlyFormat.BinaryLittleEndian;

            _reverseByteOrder = BitConverter.IsLittleEndian != littleEndian;
        }
Exemple #9
0
        public static PlyReader GetDataReader(this PlyHeader header, BufferedStreamReader streamReader)
        {
            if (header.Format == PlyFormat.Ascii)
            {
                return(new PlyAsciiReader(streamReader, header));
            }
            else if (header.Format == PlyFormat.BinaryBigEndian)
            {
                return(new PlyBinaryReader(streamReader, header));
            }

            throw new ArgumentException("Unknown header format.");
        }
Exemple #10
0
        public PlyBinaryWriter(Stream targetStream, PlyHeader header)
            : base(targetStream, header)
        {
            if (header.Format == PlyFormat.Ascii)
            {
                throw new NotSupportedException($"The {nameof(PlyBinaryWriter)} does not support ascii format.");
            }

            _writer = new SystemBinaryWriter(targetStream, Encoding.BigEndianUnicode, leaveOpen: true);
            var isLittleEndian = header.Format == PlyFormat.BinaryLittleEndian;

            _reverseByteOrder = isLittleEndian != BitConverter.IsLittleEndian;
        }
Exemple #11
0
 private string GetWriterOutput(PlyHeader header, Action <PlyWriter> populateWriterFunc)
 {
     using (var stream = new MemoryStream())
     {
         using (var writer = new PlyAsciiWriter(stream, header))
         {
             populateWriterFunc(writer);
         }
         stream.Position = 0;
         using (var reader = new StreamReader(stream))
         {
             var actual = reader.ReadToEnd();
             return(actual);
         }
     }
 }
Exemple #12
0
        public void WritesCorrectlyAllDataTypesAsArrayElementValues()
        {
            var elements = new List <PlyElement>()
            {
                new PlyElement("objects", 1, new List <PlyProperty>()
                {
                    new PlyArrayProperty("p1", PlyType.Int, PlyType.Char),
                    new PlyArrayProperty("p2", PlyType.Int, PlyType.Int),
                    new PlyArrayProperty("p3", PlyType.Int, PlyType.Short),
                    new PlyArrayProperty("p4", PlyType.Int, PlyType.Uchar),
                    new PlyArrayProperty("p5", PlyType.Int, PlyType.Uint),
                    new PlyArrayProperty("p6", PlyType.Int, PlyType.Ushort),
                    new PlyArrayProperty("p7", PlyType.Int, PlyType.Float),
                    new PlyArrayProperty("p8", PlyType.Int, PlyType.Double),
                })
            };

            var header = new PlyHeader(PlyFormat.Ascii, elements);
            var actual = GetWriterOutput(header, (PlyWriter writer) => {
                writer.WriteArray(sbyte.MinValue, sbyte.MaxValue);
                writer.WriteArray(int.MinValue, int.MaxValue);
                writer.WriteArray(short.MinValue, short.MaxValue);
                writer.WriteArray(byte.MinValue, byte.MaxValue);
                writer.WriteArray(uint.MinValue, uint.MaxValue);
                writer.WriteArray(ushort.MinValue, ushort.MaxValue);
                writer.WriteArray(float.MinValue, float.MaxValue);
                writer.WriteArray(double.MinValue, double.MaxValue);
            });

            var expected = @"ply
format ascii 1.0
element objects 1
property list int char p1
property list int int p2
property list int short p3
property list int uchar p4
property list int uint p5
property list int ushort p6
property list int float p7
property list int double p8
end_header
2 -128 127 2 -2147483648 2147483647 2 -32768 32767 2 0 255 2 0 4294967295 2 0 65535 2 -340282300000000000000000000000000000000 340282300000000000000000000000000000000 2 -179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";

            Assert.AreEqual(expected, actual);
        }
Exemple #13
0
        public void WritesCorrectlySimpleDecimals()
        {
            var simpleElements = new List <PlyElement>()
            {
                new PlyElement("vertex", 2, new List <PlyProperty>()
                {
                    new PlyProperty("x", PlyType.Float),
                    new PlyProperty("y", PlyType.Float),
                    new PlyProperty("z", PlyType.Float)
                }),
                new PlyElement("face", 2, new List <PlyProperty>()
                {
                    new PlyArrayProperty("vertex_index", PlyType.Int, PlyType.Int)
                })
            };

            var simpleHeader = new PlyHeader(PlyFormat.Ascii, simpleElements);

            var actual = GetWriterOutput(simpleHeader, (PlyWriter writer) => {
                writer.WriteValue(3.0f);
                writer.WriteValue(5.1113f);
                writer.WriteValue(-6.14f);

                writer.WriteValue(-0.1f, -0.000001f, 0f);

                writer.WriteArray(new int[] { 1, 2, 3 });
                writer.WriteArray(new int[] { -1, 5, 9 });
            });

            var expected = @"ply
format ascii 1.0
element vertex 2
property float x
property float y
property float z
element face 2
property list int int vertex_index
end_header
3 5.1113 -6.14
-0.1 -0.000001 0
3 1 2 3
3 -1 5 9";

            Assert.AreEqual(expected, actual);
        }
        public void Setup()
        {
            var elements = new List <PlyElement>()
            {
                new PlyElement("vertex", 2, new List <PlyProperty>()
                {
                    new PlyProperty("x", PlyType.Float),
                    new PlyProperty("y", PlyType.Float),
                    new PlyProperty("z", PlyType.Float)
                }),
                new PlyElement("face", 2, new List <PlyProperty>()
                {
                    new PlyArrayProperty("vertex_index", PlyType.Int, PlyType.Int)
                })
            };

            ValidHeader = new PlyHeader(PlyFormat.Ascii, "Comment", null, elements);
        }
Exemple #15
0
 public void WritesCorrectlyAllDataTypesAsArrayIndexes()
 {
     var elements = new List <PlyElement>()
     {
         new PlyElement("face", 2, new List <PlyProperty>()
         {
             new PlyProperty("p1", PlyType.Char),
             new PlyProperty("p2", PlyType.Int),
             new PlyProperty("p3", PlyType.Short),
             new PlyProperty("p4", PlyType.Uchar),
             new PlyProperty("p5", PlyType.Uint),
             new PlyProperty("p6", PlyType.Ushort),
             new PlyProperty("p7", PlyType.Float),
             new PlyProperty("p8", PlyType.Double),
         }),
     };
     var header = new PlyHeader(PlyFormat.Ascii, elements);
 }
Exemple #16
0
        public void ThrowsOnUnexpectedDataType()
        {
            var elements = new List <PlyElement>()
            {
                new PlyElement("vertex", 1, new List <PlyProperty>()
                {
                    new PlyProperty("x", PlyType.Float),
                })
            };

            var header = new PlyHeader(PlyFormat.Ascii, elements);

            using (var stream = new MemoryStream())
            {
                var writer = new PlyAsciiWriter(stream, header);
                Assert.Throws <UnexpectedDataTypeException>(() => writer.WriteValue(12));
                writer.ForceDispose();
            }
        }
Exemple #17
0
        public PlyWriter(Stream targetStream, PlyHeader header)
        {
            if (targetStream == null)
            {
                throw new ArgumentNullException($"Cannot initialize {nameof(PlyWriter)}. Given {nameof(targetStream)} is null.", nameof(targetStream));
            }

            if (header == null)
            {
                throw new ArgumentNullException($"Cannot initialize {nameof(PlyWriter)}. Given {nameof(header)} is null.", nameof(header));
            }

            if (!targetStream.CanWrite)
            {
                throw new ArgumentException($"Cannot initialize {nameof(PlyWriter)}. Given {nameof(targetStream)} is readonly.", nameof(targetStream));
            }

            _stream   = targetStream;
            _iterator = new PlyHeaderIterator(header);
        }
Exemple #18
0
        public PlyHeaderNormalizer(PlyHeader header)
        {
            BaseHeader = header;
            int FindElement(IEnumerable <string> aliases)
            {
                return(header.Elements.FindIndex((e) => aliases.Contains(e.Name.ToLower())));
            }

            int FindProperty(int elemId, IEnumerable <string> aliases)
            {
                return(header.Elements[elemId].Properties.FindIndex((p) => aliases.Contains(p.Name.ToLower())));
            }

            VerticesId = FindElement(new[] { "vertex", "vertices", "points" });
            FacesId    = FindElement(new[] { "faces", "face", "triangles" });
            NormalsId  = FindElement(new[] { "normals", "normal" });
            if (VerticesId == -1)
            {
                throw new ArgumentException("Model must define vertices");
            }

            if (FacesId == -1)
            {
                throw new ArgumentException("Model must define faces");
            }

            VertexX       = FindProperty(VerticesId, new[] { "x" });
            VertexY       = FindProperty(VerticesId, new[] { "y" });
            VertexZ       = FindProperty(VerticesId, new[] { "z" });
            VertexIndices = FindProperty(FacesId, new[] { "vertex_indices", "vertex", "vertices", "vertex_indexes", "vertex_index", "index" });
            int ni = NormalsId == -1 ? VerticesId : NormalsId;

            NormalX = FindProperty(ni, new[] { "nx", "normal_x", "x_normal", "xnormal", "normalx" });
            NormalY = FindProperty(ni, new[] { "ny", "normal_y", "y_normal", "ynormal", "normaly" });
            NormalZ = FindProperty(ni, new[] { "nz", "normal_z", "z_normal", "znormal", "normalz" });
            if (NormalX != -1)
            {
                NormalsId = ni;
            }
        }
Exemple #19
0
        public void ThrowsWhenNotAllValuesWritten()
        {
            var elements = new List <PlyElement>()
            {
                new PlyElement("vertex", 1, new List <PlyProperty>()
                {
                    new PlyProperty("x", PlyType.Float),
                }),
                new PlyElement("face", 1, new List <PlyProperty>()
                {
                    new PlyArrayProperty("vertex_index", PlyType.Int, PlyType.Int)
                })
            };

            var header = new PlyHeader(PlyFormat.Ascii, elements);

            using (var stream = new MemoryStream())
            {
                var writer = new PlyAsciiWriter(stream, header);
                writer.WriteValue(1.0f);
                Assert.Throws <InvalidOperationException>(() => writer.Dispose());
                writer.ForceDispose();
            }
        }
 public void Teardown()
 {
     ValidHeader = null;
 }
Exemple #21
0
        public void WritesCorrectlyAllDataTypesAsValues()
        {
            var elements = new List <PlyElement>()
            {
                new PlyElement("vertex", 2, new List <PlyProperty>()
                {
                    new PlyProperty("p1", PlyType.Char),
                    new PlyProperty("p2", PlyType.Int),
                    new PlyProperty("p3", PlyType.Short),
                    new PlyProperty("p4", PlyType.Uchar),
                    new PlyProperty("p5", PlyType.Uint),
                    new PlyProperty("p6", PlyType.Ushort),
                    new PlyProperty("p7", PlyType.Float),
                    new PlyProperty("p8", PlyType.Double),
                }),
                new PlyElement("vertex2", 2, new List <PlyProperty>()
                {
                    new PlyProperty("float", PlyType.Float),
                    new PlyProperty("double", PlyType.Double)
                })
            };
            var header = new PlyHeader(PlyFormat.Ascii, elements);

            var actual = GetWriterOutput(header, (PlyWriter writer) => {
                writer.WriteValue(sbyte.MinValue);
                writer.WriteValue(int.MinValue);
                writer.WriteValue(short.MinValue);
                writer.WriteValue(byte.MinValue);
                writer.WriteValue(uint.MinValue);
                writer.WriteValue(ushort.MinValue);
                writer.WriteValue(float.MinValue);
                writer.WriteValue(double.MinValue);

                writer.WriteValue(sbyte.MaxValue);
                writer.WriteValue(int.MaxValue);
                writer.WriteValue(short.MaxValue);
                writer.WriteValue(byte.MaxValue);
                writer.WriteValue(uint.MaxValue);
                writer.WriteValue(ushort.MaxValue);
                writer.WriteValue(float.MaxValue);
                writer.WriteValue(double.MaxValue);

                writer.WriteValue(-123.00151f);
                writer.WriteValue(10000.04171d);
                writer.WriteValue(-100.0001f);
                writer.WriteValue(-100.00001d);
            });
            var expected = @"ply
format ascii 1.0
element vertex 2
property char p1
property int p2
property short p3
property uchar p4
property uint p5
property ushort p6
property float p7
property double p8
element vertex2 2
property float float
property double double
end_header
-128 -2147483648 -32768 0 0 0 -340282300000000000000000000000000000000 -179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
127 2147483647 32767 255 4294967295 65535 340282300000000000000000000000000000000 179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-123.0015 10000.04171
-100.0001 -100.00001";

            Assert.AreEqual(actual, expected);
        }
Exemple #22
0
        public PlyFile ReadFileStructure(string filePath)
        {
            var plyFile = new PlyFile(filePath);
            var header  = new PlyHeader(File.ReadLines(filePath).TakeUntilIncluding(x => x == PlyKeywords.EndHeader).ToList());

            plyFile.Header = header;

            foreach (var line in header.HeaderLines)
            {
                var tokens = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                switch (tokens[0])
                {
                case PlyKeywords.Format:
                {
                    if (tokens.Length != 3)
                    {
                        throw new Exception("Invalid header - format is invalid");
                    }

                    plyFile.Header.PlyFileFormat = (tokens[1]) switch
                    {
                        PlyKeywords.Ascii => PlyFileFormat.Ascii,
                        PlyKeywords.BinaryLittleEndian => PlyFileFormat.BinaryLittleEndian,
                        PlyKeywords.BinaryBigEndian => PlyFileFormat.BinaryBigEndian,
                        _ => throw new Exception("Invalid header - format is invalid"),
                    };
                    plyFile.Header.Version = Convert.ToSingle(tokens[2]);
                    break;
                }

                case PlyKeywords.Element:
                {
                    AddElement(plyFile, tokens);
                    break;
                }

                case PlyKeywords.Property:
                {
                    AddProperty(plyFile, tokens);
                    break;
                }

                case PlyKeywords.Comment:
                {
                    AddComment(plyFile, line);
                    break;
                }

                case PlyKeywords.ObjectInfo:
                {
                    AddObjectInfo(plyFile, line);
                    break;
                }

                case PlyKeywords.EndHeader:
                {
                    return(plyFile);
                }
                }
            }
            return(plyFile);
        }
Exemple #23
0
 public PlyReader(PlyHeader header)
 {
     _iterator = new PlyHeaderIterator(header);
 }
Exemple #24
0
        /// <summary>
        /// Reads and validates the header lines of a ply file.
        /// </summary>
        /// <param name="headerLines">The lines to read.</param>
        /// <returns></returns>
        private PlyHeader ReadHeader(string[] headerLines)
        {
            if (headerLines.Length > 2 && (PlyHeaderItems)Enum.Parse(typeof(PlyHeaderItems), headerLines[0]) == PlyHeaderItems.ply &&
                (PlyHeaderItems)Enum.Parse(typeof(PlyHeaderItems), headerLines[headerLines.Length - 1]) == PlyHeaderItems.end_header)
            {
                var formatSpecLineParts = headerLines[1].Split(' ');
                var formatStr           = formatSpecLineParts[0];
                var formatTypeStr       = formatSpecLineParts[1];
                var fileVersion         = Version.Parse(formatSpecLineParts[2]);

                if ((PlyHeaderItems)Enum.Parse(typeof(PlyHeaderItems), formatStr) == PlyHeaderItems.format &&
                    Enum.TryParse(formatTypeStr, out PlyFormatTypes formatType) && fileVersion <= SUPPORTEDVERSION)
                {
                    var comments = new List <string>();
                    var objInfos = new List <Tuple <string, string> >();
                    var elements = new List <PlyElement>();

                    for (int i = 2; i < headerLines.Length - 1; i++)
                    {
                        var lineParts = headerLines[i].Split(' ');
                        if (Enum.TryParse(lineParts[0], out PlyHeaderItems headerItemType))
                        {
                            switch (headerItemType)
                            {
                            case PlyHeaderItems.element:
                            {
                                if (lineParts.Length == 3)
                                {
                                    var elementName  = lineParts[1];
                                    var elementCount = int.Parse(lineParts[2]);
                                    var element      = new PlyElement(elementName, elementCount, new List <PlyProperty[]> {
                                            new PlyProperty[] { }
                                        });
                                    elements.Add(element);
                                }
                                break;
                            }

                            case PlyHeaderItems.property:
                            {
                                if (lineParts.Length >= 3 && elements.Count > 0)
                                {
                                    if (lineParts[1] != "list" && lineParts.Length == 3)
                                    {
                                        if (Enum.TryParse($"_{lineParts[1]}", out PlyDataTypes propertyType))
                                        {
                                            var propertyName = lineParts[2];

                                            var property = new PlyProperty(propertyName, propertyType, null, false, PlyDataTypes._char, null);

                                            var newPropertyList = new List <PlyProperty>();
                                            for (int j = 0; j < elements.Last().Instances[0].Length; j++)
                                            {
                                                newPropertyList.Add(elements.Last().Instances[0][j]);
                                            }
                                            newPropertyList.Add(property);
                                            elements.Last().Instances[0] = newPropertyList.ToArray();
                                        }
                                        else
                                        {
                                            throw new InvalidDataException($"Invalid data type, {lineParts[1]}.");
                                        }
                                    }
                                    else if (lineParts[1] == "list" && lineParts.Length == 5)
                                    {
                                        //array property
                                        if (Enum.TryParse($"_{lineParts[2]}", out PlyDataTypes propertyType) && Enum.TryParse($"_{lineParts[3]}", out PlyDataTypes listContentType))
                                        {
                                            var propertyName = lineParts[4];

                                            var property = new PlyProperty(propertyName, propertyType, null, true, listContentType, null);

                                            var newPropertyList = new List <PlyProperty>();
                                            for (int j = 0; j < elements.Last().Instances[0].Length; j++)
                                            {
                                                newPropertyList.Add(elements.Last().Instances[0][j]);
                                            }
                                            newPropertyList.Add(property);
                                            elements.Last().Instances[0] = newPropertyList.ToArray();
                                        }
                                        else
                                        {
                                            throw new InvalidDataException($"Invalid data type, {lineParts[1]}.");
                                        }
                                    }
                                    else
                                    {
                                        throw new InvalidDataException("Invalid property definition.");
                                    }
                                }
                                break;
                            }

                            case PlyHeaderItems.obj_info:
                            {
                                if (lineParts.Length == 3)
                                {
                                    objInfos.Add(new Tuple <string, string>(lineParts[1], lineParts[2]));
                                }
                                else
                                {
                                    objInfos.Add(new Tuple <string, string>($"htk_info_{objInfos.Count}", headerLines[i].Substring(lineParts[0].Length + 1)));
                                }
                                break;
                            }

                            case PlyHeaderItems.comment:
                            {
                                comments.Add(headerLines[i].Substring(lineParts[0].Length + 1));
                                break;
                            }

                            default:
                            {
                                throw new InvalidDataException($"Unknown header item, {lineParts[0]}.");
                            }
                            }
                        }
                        else
                        {
                            throw new InvalidDataException($"Unknown header item, {lineParts[0]}.");
                        }
                    }

                    var plyHeader = new PlyHeader(formatType, fileVersion, elements.ToArray(), objInfos.ToArray(), comments.ToArray());
                    return(plyHeader);
                }
                else
                {
                    throw new InvalidDataException("Invalid format specification.");
                }
            }
Exemple #25
0
 /// <summary>
 /// Initializes a new <see cref="PlyReader"/>.
 /// </summary>
 /// <param name="dispatcher"></param>
 public PlyReader(Dispatcher dispatcher = null) : base(dispatcher)
 {
     Header = new PlyHeader();
     Body   = new List <PlyElement>();
 }
 public void Teardown()
 {
     Header = null;
 }
Exemple #27
0
        public static string GetHeader(PlyHeader header)
        {
            var sb = new StringBuilder();

            sb.AppendLine(PlyKeywords.MagicNumber);

            var formatKeyword = default(string);

            if (header.Format == PlyFormat.Ascii)
            {
                formatKeyword = PlyKeywords.AsciiFormat;
            }
            else if (header.Format == PlyFormat.BinaryBigEndian)
            {
                formatKeyword = PlyKeywords.BinaryBigEndianFormat;
            }
            else if (header.Format == PlyFormat.BinaryLittleEndian)
            {
                formatKeyword = PlyKeywords.BinaryLittleEndianFormat;
            }
            else
            {
                throw new NotSupportedException("The declared header file format is not supported.");
            }

            sb.AppendLine($"{formatKeyword} {FormatVersion}");

            if (header.Comment != null)
            {
                var escapedComment = EscapeNewLines(header.Comment);
                foreach (string comment in escapedComment)
                {
                    var commentDeclaration = $"{PlyKeywords.Comment} {comment}";
                    sb.AppendLine(commentDeclaration);
                }
            }

            if (header.ObjectInfo != null)
            {
                var escapedObjectInfo = EscapeNewLines(header.ObjectInfo);
                foreach (string objectInfo in escapedObjectInfo)
                {
                    var objectInfoDeclaration = $"{PlyKeywords.ObjectInfo} {objectInfo}";
                    sb.AppendLine(objectInfoDeclaration);
                }
            }

            foreach (PlyElement element in header.Elements)
            {
                var elementDeclaration = $"{PlyKeywords.Element} {element.Name} {element.InstanceCount}";
                sb.AppendLine(elementDeclaration);

                foreach (PlyProperty property in element.Properties)
                {
                    var valueType           = PlyTypeConverter.ToStringRepresentation(property.ValueType);
                    var propertyDeclaration = $"{PlyKeywords.Property} {valueType} {property.Name}";

                    if (property is PlyArrayProperty arrayProperty)
                    {
                        var arraySizeType = PlyTypeConverter.ToStringRepresentation(arrayProperty.ArraySizeType);
                        propertyDeclaration = $"{PlyKeywords.PropertyList} {arraySizeType} {valueType} {property.Name}";
                    }

                    sb.AppendLine(propertyDeclaration);
                }
            }

            sb.AppendLine(PlyKeywords.HeaderEnd);
            return(sb.ToString());
        }
        public MeshData Convert(PlyReader reader, PlyHeader header)
        {
            var normalizedHeader = new PlyHeaderNormalizer(header);

            var elements = normalizedHeader.BaseHeader.Elements;

            var faces = new List <IndexedTriangle>(elements[normalizedHeader.FacesId].InstanceCount);

            var meshData = new MeshData
            {
                Vertices = new Vector3[elements[normalizedHeader.VerticesId].InstanceCount],
                Faces    = null,
                Normals  = new Vector3[normalizedHeader.NormalsId == -1 ? 0 : elements[normalizedHeader.NormalsId].InstanceCount]
            };

            int currVertex            = 0;
            int currVertexPropWritten = 0;
            int currNormal            = 0;
            int currNormalPropWritten = 0;
            int currFace = 0;

            // calling progressReporter.Report is expensive, limit it.
            long totalLoad            = meshData.Vertices.Length + faces.Capacity + meshData.Normals.Length;
            int  lastProgressReported = 10;

            // since the structure of the file is not known
            // and will be determined at the runtime
            // we don't know what elements and properties come first.
            // not the prettiest but definitely the fastest way to do this.
            for (int i = 0; i < elements.Count; ++i)
            {
                for (int j = 0; j < elements[i].InstanceCount; ++j)
                {
                    // call the progressReporter function on every 10% progress
                    int progress = (int)((currVertex + currNormal + currFace) * 100 / totalLoad);
                    if (progress > lastProgressReported + 10 && ProgressReporter != null)
                    {
                        ProgressReporter.Report(progress);
                        lastProgressReported = progress;
                    }

                    // go through every property of the current element
                    for (int k = 0; k < elements[i].Properties.Count; ++k)
                    {
                        bool ignored = true;

                        // if the current element was found by the normalizedHeader
                        // to be a vertex element, parse the vertices
                        if (i == normalizedHeader.VerticesId)
                        {
                            if (k == normalizedHeader.VertexX)
                            {
                                meshData.Vertices[currVertex].X = reader.ReadProperty <float>();
                                currVertexPropWritten++;
                                ignored = false;
                            }
                            else if (k == normalizedHeader.VertexY)
                            {
                                meshData.Vertices[currVertex].Y = reader.ReadProperty <float>();
                                currVertexPropWritten++;
                                ignored = false;
                            }
                            else if (k == normalizedHeader.VertexZ)
                            {
                                meshData.Vertices[currVertex].Z = reader.ReadProperty <float>();
                                currVertexPropWritten++;
                                ignored = false;
                            }
                            if (currVertexPropWritten == 3)
                            {
                                currVertexPropWritten = 0;
                                currVertex++;
                            }
                        }
                        // if it is a normal element..
                        if (i == normalizedHeader.NormalsId)
                        {
                            if (k == normalizedHeader.NormalX)
                            {
                                meshData.Normals[currNormal].X = reader.ReadProperty <float>();
                                currNormalPropWritten++;
                                ignored = false;
                            }
                            else if (k == normalizedHeader.NormalY)
                            {
                                meshData.Normals[currNormal].X = reader.ReadProperty <float>();
                                currNormalPropWritten++;
                                ignored = false;
                            }
                            else if (k == normalizedHeader.NormalZ)
                            {
                                meshData.Normals[currNormal].X = reader.ReadProperty <float>();
                                currNormalPropWritten++;
                                ignored = false;
                            }
                            if (currNormalPropWritten == 3)
                            {
                                currNormal++;
                                currNormalPropWritten = 0;
                            }
                        }
                        // if it is a face element..
                        if (i == normalizedHeader.FacesId)
                        {
                            if (k == normalizedHeader.VerticesId)
                            {
                                // read the vertices of a face
                                List <int> verts = new List <int>(3);
                                foreach (int index in reader.ReadArray <int>())
                                {
                                    verts.Add(index);
                                }

                                // if we got 3 vertices, its a normal triangle
                                // and the triangle to the list
                                if (verts.Count == 3)
                                {
                                    var t = new IndexedTriangle
                                    {
                                        Vertex1 = verts[0],
                                        Vertex2 = verts[1],
                                        Vertex3 = verts[2]
                                    };
                                    faces.Add(t);
                                }
                                else if (verts.Count == 4)
                                {
                                    faces.Add(new IndexedTriangle(verts[0], verts[1], verts[3]));
                                    faces.Add(new IndexedTriangle(verts[1], verts[2], verts[3]));
                                }
                                else
                                {
                                    throw new NotSupportedException("Only triangular faces are currently supported.");
                                }
                                currFace++;
                                ignored = false;
                            }
                        }
                        if (ignored)
                        {
                            reader.SkipProperty();
                        }
                    }
                }
            }

            meshData.Faces = faces.ToArray();

            if (meshData.Normals.Length == 0)
            {
                meshData.Normals = null;
            }

            ProgressReporter?.Report(100);
            return(meshData);
        }