private SegmentHeader GetMetaDataSegmentHeader(JTNode node) { if (uniqueMetaDataSegmentHeaders.ContainsKey(node)) { return(uniqueMetaDataSegmentHeaders[node]); } var attributes = node.Attributes; if (attributes.Count == 0) { return(null); } var keys = new List <string>(attributes.Keys); var values = new List <object>(attributes.Values); var metaDataSegment = new MetaDataSegment(new PropertyProxyMetaDataElement(keys, values)); var compressedMetaDataSegment = CompressionUtils.Compress(metaDataSegment.Bytes); var metaDataSegmentHeaderZLIB = new LogicElementHeaderZLIB(2, compressedMetaDataSegment.Length + 1, 2); // CompressionAlgorithm field (of type Byte) is included in CompressedDataLength var metaDataSegmentHeader = new SegmentHeader(GUID.NewGUID(), 4, SegmentHeader.Size + metaDataSegmentHeaderZLIB.ByteCount + compressedMetaDataSegment.Length); uniqueMetaDataSegmentHeaders[node] = metaDataSegmentHeader; compressedMetaDataSegments.Add(compressedMetaDataSegment); metaDataSegmentHeadersZLIB.Add(metaDataSegmentHeaderZLIB); metaDataSegmentHeaders.Add(metaDataSegmentHeader); return(metaDataSegmentHeader); }
private void ProcessAttributes(JTNode node, int nodeElementId) { var attributes = new Dictionary <string, object>(node.Attributes.Count); foreach (var attribute in node.Attributes) { var key = attribute.Key.Trim(); var value = attribute.Value; while (key.EndsWith(":")) { key = key.Substring(0, key.Length - 1); } while (key.Contains("::")) { key = key.Replace("::", ":"); } if (key.Length == 0) { continue; } attributes[key + "::"] = value; } if (separateAttributeSegments) { var metaDataSegmentHeader = GetMetaDataSegmentHeader(new JTNode() { Attributes = attributes }); attributes.Clear(); if (metaDataSegmentHeader != null) { attributes["JT_LLPROP_METADATA"] = metaDataSegmentHeader; } } attributes["JT_PROP_MEASUREMENT_UNITS"] = node.MeasurementUnitAsString; //if (node.Number != null || node.Name != null) attributes["JT_PROP_NAME"] = string.Join(" - ", new[] { node.Number, node.Name }.Where(v => v != null).ToArray()) + "." + (node.Children.Count > 0 ? "asm" : "part") + ";0;0:"; if (node.Number != null || node.Name != null) { attributes["JT_PROP_NAME"] = string.Join(" - ", new[] { node.Number, node.Name }.Where(v => v != null)) + "." + (node.Children.Count > 0 || (((node.ReferencedFile ?? "").Length > 0) && !node.ReferencedFileIsPart) ? "asm" : "part") + ";0;0:"; } //if (node == this && node.Children.Count > 0) attributes["PartitionType"] = "Assembly"; if (node.GeometricSets.Length > 0) { attributes["JT_LLPROP_SHAPEIMPL"] = node.GeometricSets; } var attributesCount = attributes.Count; var keys = new List <int>(attributesCount); var values = new List <int>(attributesCount); foreach (var attribute in attributes) { var key = attribute.Key; var value = attribute.Value; var valueTypeName = value.GetType().Name; if (valueTypeName != "String" && valueTypeName != "Int32" && valueTypeName != "Single" && valueTypeName != "DateTime" && valueTypeName != "GeometricSet[]" && valueTypeName != "SegmentHeader") { throw new Exception(String.Format("Only String, Int32, Single, DateTime, GeometricSet[] and SegmentHeader value types are allowed. Current value is {0}.", valueTypeName)); } var keyLookupKey = String.Format("{0}-{1}", key.GetType().Name, key); int keyId; if (uniquePropertyIds.ContainsKey(keyLookupKey)) { keyId = uniquePropertyIds[keyLookupKey]; } else { keyId = IdGenUtils.NextId; propertyAtomElements.Add(new StringPropertyAtomElement(key, keyId)); uniquePropertyIds[keyLookupKey] = keyId; } keys.Add(keyId); var valueAsString = valueTypeName != "GeometricSet[]" ? value.ToString() : ((GeometricSet[])(value))[0].ToString(); var valueLookupKey = valueTypeName + "-" + valueAsString; int valueId; if (uniquePropertyIds.ContainsKey(valueLookupKey)) { valueId = uniquePropertyIds[valueLookupKey]; } else { valueId = IdGenUtils.NextId; uniquePropertyIds[valueLookupKey] = valueId; switch (valueTypeName) { case "String": propertyAtomElements.Add(new StringPropertyAtomElement((string)value, valueId)); break; case "Int32": propertyAtomElements.Add(new IntegerPropertyAtomElement((int)value, valueId)); break; case "Single": propertyAtomElements.Add(new FloatingPointPropertyAtomElement((float)value, valueId)); break; case "DateTime": propertyAtomElements.Add(new DatePropertyAtomElement((DateTime)value, valueId)); break; case "GeometricSet[]": var geometricSet = ((GeometricSet[])value)[0]; var shapeLODSegment = new ShapeLODSegment(new TriStripSetShapeLODElement(geometricSet.TriStrips, geometricSet.Positions, geometricSet.Normals)); var shapeLODSegmentHeader = new SegmentHeader(GUID.NewGUID(), 6, SegmentHeader.Size + shapeLODSegment.ByteCount); shapeLODSegments.Add(shapeLODSegment); shapeLODSegmentHeaders.Add(shapeLODSegmentHeader); propertyAtomElements.Add(new LateLoadedPropertyAtomElement(shapeLODSegmentHeader.SegmentID, shapeLODSegmentHeader.SegmentType, valueId)); break; case "SegmentHeader": var segmentHeader = (SegmentHeader)value; propertyAtomElements.Add(new LateLoadedPropertyAtomElement(segmentHeader.SegmentID, segmentHeader.SegmentType, valueId)); break; } } values.Add(valueId); } propertyTableContents.Add(nodeElementId, new NodePropertyTable(keys, values)); }
//public PartitionNodeElement Save(string path, bool monolithic = true, bool separateAttributeSegments = false) public byte[] ToBytes() { uniquePropertyIds.Clear(); uniqueAttributeIds.Clear(); uniqueMetaDataSegmentHeaders.Clear(); propertyTableContents.Clear(); elements.Clear(); propertyAtomElements.Clear(); savedFileIds.Clear(); shapeLODSegments.Clear(); shapeLODSegmentHeaders.Clear(); compressedMetaDataSegments.Clear(); metaDataSegmentHeadersZLIB.Clear(); metaDataSegmentHeaders.Clear(); /*this.monolithic = monolithic; * this.separateAttributeSegments = separateAttributeSegments;*/ this.monolithic = true; this.separateAttributeSegments = false; // this.savePath = Path.Combine(String.Join("_", Path.GetDirectoryName(path).Split(Path.GetInvalidPathChars())), String.Join("_", Path.GetFileName(path).Split(Path.GetInvalidFileNameChars()))); // File Header var fileHeader = new FileHeader("Version 8.1 JT", (Byte)(BitConverter.IsLittleEndian ? 0 : 1), FileHeader.Size, GUID.NewGUID()); // END File Header // Create all elements //FindInstancedNodes(this); CreateElement(this); // END Create all elements // LSG Segment var keys = new int[propertyTableContents.Keys.Count]; propertyTableContents.Keys.CopyTo(keys, 0); var values = new NodePropertyTable[propertyTableContents.Values.Count]; propertyTableContents.Values.CopyTo(values, 0); var lsgSegment = new LSGSegment(new List <BaseDataStructure>(elements), propertyAtomElements, new PropertyTable(keys, values)); // END LSG Segment // Compress LSG Segment var compressedLSGSegmentData = CompressionUtils.Compress(lsgSegment.Bytes); // END Compress LSG Segment // LSG Segment Logic Element Header ZLIB var lsgSegmentLogicElementHeaderZLIB = new LogicElementHeaderZLIB(2, compressedLSGSegmentData.Length + 1, 2); // CompressionAlgorithm field (of type Byte) is included in CompressedDataLength // END LSG Segment Logic Element Header ZLIB // Segment Header var lsgSegmentHeader = new SegmentHeader(fileHeader.LSGSegmentID, 1, SegmentHeader.Size + lsgSegmentLogicElementHeaderZLIB.ByteCount + compressedLSGSegmentData.Length); // END Segment Header // Toc Segments var lsgTOCEntry = new TOCEntry(lsgSegmentHeader.SegmentID, -1, lsgSegmentHeader.SegmentLength, (UInt32)(lsgSegmentHeader.SegmentType << 24)); var tocEntries = new List <TOCEntry>() { lsgTOCEntry }; for (int i = 0, c = shapeLODSegmentHeaders.Count; i < c; ++i) { var shapeLODSegmentHeader = shapeLODSegmentHeaders[i]; tocEntries.Add(new TOCEntry(shapeLODSegmentHeader.SegmentID, -1, shapeLODSegmentHeader.SegmentLength, (UInt32)(shapeLODSegmentHeader.SegmentType << 24))); } for (int i = 0, c = metaDataSegmentHeaders.Count; i < c; ++i) { var metaDataSegmentHeader = metaDataSegmentHeaders[i]; tocEntries.Add(new TOCEntry(metaDataSegmentHeader.SegmentID, -1, metaDataSegmentHeader.SegmentLength, (UInt32)(metaDataSegmentHeader.SegmentType << 24))); } if (tocEntries.Count == 1) { tocEntries.Add(lsgTOCEntry); } var tocSegment = new TOCSegment(tocEntries.ToArray()); var segmentTotalSizeTracker = 0; for (int i = 0, c = tocEntries.Count; i < c; ++i) { var tocEntry = tocEntries[i]; if (i > 0 && tocEntry == tocEntries[i - 1]) { continue; } tocEntry.SegmentOffset = fileHeader.ByteCount + tocSegment.ByteCount + segmentTotalSizeTracker; segmentTotalSizeTracker += tocEntry.SegmentLength; } // END Toc Segments // Write to file //using (var outputFileStream = new FileStream(savePath, FileMode.Create, FileAccess.Write)) using (var outputFileStream = new MemoryStream()) { outputFileStream.Write(fileHeader.Bytes, 0, fileHeader.ByteCount); outputFileStream.Write(tocSegment.Bytes, 0, tocSegment.ByteCount); outputFileStream.Write(lsgSegmentHeader.Bytes, 0, lsgSegmentHeader.ByteCount); outputFileStream.Write(lsgSegmentLogicElementHeaderZLIB.Bytes, 0, lsgSegmentLogicElementHeaderZLIB.ByteCount); outputFileStream.Write(compressedLSGSegmentData, 0, compressedLSGSegmentData.Length); for (int i = 0, c = shapeLODSegmentHeaders.Count; i < c; ++i) { var shapeLODSegmentHeader = shapeLODSegmentHeaders[i]; var shapeLODSegment = shapeLODSegments[i]; outputFileStream.Write(shapeLODSegmentHeader.Bytes, 0, shapeLODSegmentHeader.ByteCount); outputFileStream.Write(shapeLODSegment.Bytes, 0, shapeLODSegment.ByteCount); } for (int i = 0, c = metaDataSegmentHeaders.Count; i < c; ++i) { var metaDataSegmentHeader = metaDataSegmentHeaders[i]; var metaDataSegmentHeaderZLIB = metaDataSegmentHeadersZLIB[i]; var compressedMetaDataSegment = compressedMetaDataSegments[i]; outputFileStream.Write(metaDataSegmentHeader.Bytes, 0, metaDataSegmentHeader.ByteCount); outputFileStream.Write(metaDataSegmentHeaderZLIB.Bytes, 0, metaDataSegmentHeaderZLIB.ByteCount); outputFileStream.Write(compressedMetaDataSegment, 0, compressedMetaDataSegment.Length); } return(outputFileStream.ToArray()); } // END Write to file //return elements.Count > 0 ? (PartitionNodeElement)elements[0] : null; }