Пример #1
0
        /// <summary>
        /// Save geometries into xml files
        /// </summary>
        /// <param name="path">xml file path</param>
        /// <param name="geometries">geometries</param>
        /// <param name="fileSizeLimit">file size limit for each xml file</param>
        /// <param name="threshold">threshold of triangle count for mesh decimation</param>
        /// <param name="quality">quality for mesh decimation</param>
        public static void SaveGeometries(string path, ref Dictionary <string, GeometryStore> geometries, double fileSizeLimit, int threshold, double quality)
        {
            string baseName = path.Substring(0, path.Length - 4);

            // xml content holder
            StringBuilder doc = new StringBuilder();

            // name index for each output xml file
            int nameIndex = 0;

            foreach (string globalId in geometries.Keys)
            {
                // before processing the next geometry, check whether we should output the current document
                // reach file size limit. write to file and start a new document
                if (doc.Length >= fileSizeLimit)
                {
                    // add end tag
                    doc.Append("</IfcModel>");

                    // write to xml file
                    using (var writer = new StreamWriter(baseName + "_" + nameIndex + ".xml", false, Encoding.UTF8))
                    {
                        writer.Write(doc.ToString());
                    }

                    doc.Clear();
                    nameIndex++;
                }

                // empty document, add the first two lines
                if (doc.Length == 0)
                {
                    doc.Append("<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n")
                    .Append("<IfcModel>\n");
                }

                var geometry = geometries[globalId];

                // add Element start tag
                doc.Append(string.Format("\t<Element ElementId=\"{0}\" LevelName=\"\" Name=\"{1}\">\n", geometry.GlobalId, geometry.Name.Replace('"', '\'')));

                // an element node can have multiple mesh nodes
                for (int i = 0; i < geometry.Meshes.Count; ++i)
                {
                    var meshStore = geometry.Meshes[i];
                    // add mesh start tag, lod0 start tag, uvs tag(empty), uvindexes tag(empty)
                    doc.Append(string.Format("\t\t<Mesh ElementId=\"{0}\" Color=\"{1}\" Material=\"\">\n", geometry.GlobalId, meshStore.Color))
                    .Append("\t\t\t<Lod0>\n")
                    .Append("\t\t\t\t<UVs />\n")
                    .Append("\t\t\t\t<UVIndexes />\n");

                    // decimate mesh if needed
                    int originTriangleCount = meshStore.Indexes.Count / 3;
                    if (originTriangleCount >= threshold)
                    {
                        Logger.Info("Origin mesh vertice count: {0}, triangle count: {1}", meshStore.Vertexes.Count / 3, originTriangleCount);
                        int targetTriangleCount = (int)Math.Ceiling(originTriangleCount * quality);
                        MeshDecimator.Decimate(ref meshStore, targetTriangleCount);
                        Logger.Info("Decimated mesh vertice count: {0}, triangle count: {1}", meshStore.Vertexes.Count / 3, meshStore.Indexes.Count / 3);
                    }

                    // add vertices tag
                    doc.Append("\t\t\t\t<Vertices>");
                    foreach (var vertex in meshStore.Vertexes)
                    {
                        doc.Append(vertex).Append(",");
                    }
                    doc.Remove(doc.Length - 1, 1) // remove the last ","
                    .Append("</Vertices>\n");

                    // add pointindexes tag
                    if (meshStore.Indexes.Count / 3 > 500)
                    {
                        Console.WriteLine("face number:{0}", meshStore.Indexes.Count / 3);
                    }
                    doc.Append("\t\t\t\t<PointIndexes>");
                    foreach (var index in meshStore.Indexes)
                    {
                        doc.Append(index).Append(",");
                    }
                    doc.Remove(doc.Length - 1, 1)
                    .Append("</PointIndexes>\n");

                    // end lod0 tag
                    doc.Append("\t\t\t</Lod0>\n");

                    // ... can add lod1 lod2 lod3, but currently they are the same so we ignore them

                    // end this mesh
                    doc.Append("\t\t</Mesh>\n");
                }
                // end this geometry
                doc.Append("\t</Element>\n");
            }
            // the last document may not reach the file size limit
            if (doc.Length != 0)
            {
                // add end tag
                doc.Append("</IfcModel>");

                // write to xml file
                using (var writer = new StreamWriter(baseName + "_" + nameIndex + ".xml", false, Encoding.UTF8))
                {
                    writer.Write(doc.ToString());
                }

                doc.Clear();
            }
        }
Пример #2
0
        /// <summary>
        /// Output geometries (mesh decimated with quality) to xml file.
        /// </summary>
        /// <param name="path">xml path</param>
        /// <param name="geometries">Geometries to output</param>
        /// <param name="threshold">Threshold to decimate mesh</param>
        /// <param name="quality">Mesh decimation quality</param>
        public static void SaveGeometries(string path, ref List <GeometryStore> geometries, int threshold, double quality)
        {
            // xml content holder
            StringBuilder doc = new StringBuilder();

            // add first two line
            doc.Append("<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n")
            .Append("<IfcModel>\n");

            foreach (GeometryStore geometry in geometries)
            {
                // add Element start tag
                doc.Append(string.Format("\t<Element ElementId=\"{0}\" LevelName=\"\" Name=\"{1}\">\n", geometry.GlobalId, geometry.Name == null? "": geometry.Name.Replace('"', '\'')));

                // an element node can have multiple mesh nodes
                for (int i = 0; i < geometry.Meshes.Count; ++i)
                {
                    var meshStore = geometry.Meshes[i];
                    // add mesh start tag, lod0 start tag, uvs tag(empty), uvindexes tag(empty)
                    doc.Append(string.Format("\t\t<Mesh ElementId=\"{0}\" Color=\"{1}\" Material=\"\">\n", geometry.GlobalId, meshStore.Color))
                    .Append("\t\t\t<Lod0>\n")
                    .Append("\t\t\t\t<UVs />\n")
                    .Append("\t\t\t\t<UVIndexes />\n");

                    // decimate mesh
                    int originTriangleCount = meshStore.Indexes.Count / 3;
                    if (originTriangleCount > threshold)
                    {
                        Logger.Info("Origin mesh vertice count: {0}, triangle count: {1}", meshStore.Vertexes.Count / 3, originTriangleCount);
                        int targetTriangleCount = (int)Math.Ceiling(originTriangleCount * quality);
                        MeshDecimator.Decimate(ref meshStore, targetTriangleCount);
                        Logger.Info("Decimated mesh vertice count: {0}, triangle count: {1}", meshStore.Vertexes.Count / 3, meshStore.Indexes.Count / 3);
                    }

                    // add vertices tag
                    doc.Append("\t\t\t\t<Vertices>");
                    foreach (var vertex in meshStore.Vertexes)
                    {
                        doc.Append(vertex).Append(",");
                    }
                    doc.Remove(doc.Length - 1, 1) // remove the last ","
                    .Append("</Vertices>\n");

                    // add pointindexes tag
                    if (meshStore.Indexes.Count / 3 > 500)
                    {
                        Console.WriteLine("face number:{0}", meshStore.Indexes.Count / 3);
                    }
                    doc.Append("\t\t\t\t<PointIndexes>");
                    foreach (var index in meshStore.Indexes)
                    {
                        doc.Append(index).Append(",");
                    }
                    doc.Remove(doc.Length - 1, 1)
                    .Append("</PointIndexes>\n");

                    // end lod0 tag
                    doc.Append("\t\t\t</Lod0>\n");

                    // ... can add lod1 lod2 lod3, but currently they are the same so we ignore them

                    // end this mesh
                    doc.Append("\t\t</Mesh>\n");
                }
                // end this geometry
                doc.Append("\t</Element>\n");
            }

            // add end tag
            doc.Append("</IfcModel>");

            // write to xml file
            using (var writer = new StreamWriter(path, false, Encoding.UTF8))
            {
                writer.Write(doc.ToString());
            }
        }