Draw object serialization

From Maria GDK Wiki
Jump to navigation Jump to search

Draw objects can be serialized to a byte array for easy transfer between different systems. Objects of type ISimpleDrawObject can be serialized using the TPG.DrawObjects.Serialize.dll component. The objects are serialized using protobuf version3 (proto3). The protobuf data can either be stored to file or retained as byte[] (see Accessing protobuf data). The serialization can be done using different interfaces offering slightly different functionality.

Interfaces

IDrawObjectCodex

The IDrawObjectCodec interface encapsulates the serialization and offers a very convenient interface to convert to/from byte[].

This interface is recommended if the purpose is to transfer draw object to/from byte[] as easily as possible.

Create an instance using new DrawObjectCodec().

Reducing size of serialized data

If size of data is important, it is very important that all redundant attributes are reset before the objects are serialized. See #Useful tips for more information.

Converting draw objects to protobuf

The #ISerializeDrawObjects interface is used to transfer from draw objects to protobuf.

Converting protobuf to draw objects

The conversion supports data created both by #ISerializeDrawObjects and #ISerializeCompleteDrawObjects. It is not necessary to check the origin of the byte[] data.

ISerializeDrawObjects

The ISerializeDrawObjects interface uses C2525 to reduce the size of serialized data. Only the differences from corresponding C2525 draw objects are serialized. All wellknown-information based on the C2525 codes are recreated when converting back to draw object thereby reducing serialized data.

Draw objects without valid C2525 codes are still supported by completely serialize all attributes.

Create an instance using new SerializeDrawObjects().

Reducing size of serialized data

If size of data is important, it is very important that all redundant attributes are reset before the objects are serialized. See #Useful tips for more information.

Serializing C2525 objects

The draw object's hierarchy code is used to get the corresponding C2525 code.

A temporary draw object is created based on the C2525 code and only the differences from the actual draw object is serialized.

All wellknown-information, based on the C2525 code, is not transferred, but recreated when converting back to a draw object. This reduces the serialized data.

Serializing unknown objects (not C2525)

The draw object is completely serialized if the draw object's hierarchy code can not be mapped to any C2525. This ensures that all draw objects are serialized even if they cant be "compressed".

There can be a mix of draw objects with and without known C2525 codes.

ISerializeCompleteDrawObjects

The ISerializeCompleteDrawObjects interface serializes the draw objects without C2525 "compression".

The ISerializeDrawObjects interface would normally be preferred, but this interface could be considered in the following scenarios:

  • No objects have valid C2525 codes - There is a small overhead using C2525 and using this interface will avoid this overhead.
  • C2525 conversion is not acceptable - Using the C2525 conversion, all “known” information is not transferred. Instead, this information is recreated when converting back to draw objects. Use this interface if this transfer method is not acceptable.

Create an instance using new SerializeCompleteDrawObjects().

Reducing size of serialized data

If size of data is important, it is very important that all redundant attributes are reset before the objects are serialized. See #Useful tips for more information.

Protobuf

An advantage of the protobuf serialization is that unset attributes do not result in transferred data. This means that the draw objects structure can be replicated without resulting in huge data transfer. The draw objects structure is replicated using protobuf version3 (proto3).

Even though the protobuf serializes the data quite smartly, there are some attributes that produce unnecessary overhead. To avoid this, some attributes are serialized indirectly using bit-mapping. Normally, the definition of the protobuf serialization is an internal issue and should be of no concern.

  • Boolean attributes - All boolean attributes in the draw object structure are bit-mapped into a common protobuf attribute.
  • Enum attributes - All enum attributes in the draw object structure are bit-shifted into protobuf attributes.

Accessing protobuf data

Both interfaces #ISerializeDrawObjects and #ISerializeCompleteDrawObjects convert between draw objects and protobuf objects.

In addition they also have methods to convert protobuf objects to/from byte[] and data file:

Method Description
GetBuffer Converts protobuf to byte[].
ReadFromBuffer Converts byte[] to protobuf.
ReadFromFile Converts data stored in file to protobuf.
SaveToFile Stores protobuf to given filename.

SerializeModes

Controls how the SimpleDrawObject is serialized and can be used to reduce the size of the serialized data.

Property Description
FullPrecision Default value. Complete data is serialized
DoNotKeepInvalidFieldInformation Information about invalid fields will not be transferred. This information might not be necessary to transfer if 100% resemblance is not required.
PointAsShiftedIntPrecision Geographical points are transferred as shifted integer. This reduces the size of transferred data, but also reduces precision.
DoNotKeepSimpleDrawObjectId The DrawObjectData’s Id attribute will not be transferred. This information might not be necessary to transfer if the original Id is not required.

Example code

This lists different usage scenarios for the protobuf serialization.

Creating C2525 draw objects

The code examples uses a list of draw objects. For simplicity, the following code gives an example on how to create a C2525 draw object.

//create ISimpleDrawObjects
var simpleDrawObject = drawObjectDataFactory.CreateTacticalGraphic("TACGRP.TSK.DLY", 
                                                                    new SimpleDrawObjectFactory());
                              
var listObjects = new List`<ISimpleDrawObject>`();
listObjects.Add(simpleDrawObject);

Using IDrawObjectCodec

//listObjects contains draw objects to serialize

//create serialization factory
var serializeFactory = new DrawObjectCodec();

//converts draw objects to protobuf using C2525         
var serializedBuffer = serializeFactory.Encode(listObjects, SerializeModes.FullPrecision);
                                               
//converts protobuf back to ISimpleDrawObjects 
var serializedDrawObjects = serializeFactory.Decode(serializedBuffer);

Converting ISimpleDrawObjects to byte[] using ISerializeDrawObjects

//listObjects contains draw objects to serialize

//create serialization factory
var serializeFactory = new ISerializeDrawObjects();

//converts draw objects to protobuf using C2525 
var protobufC2525 = serializeFactory.CreateProtobufFromSimpleDrawObjects(listObjects, 
                                                                        SerializeModes.FullPrecision);

//get protobuf as byte[]
var buffer = serializeDataFactory.GetBuffer(protobufC2525);

Converting byte[] to ISimpleDrawObjects using ISerializeDrawObjects

//buffer is byte[] created using ISimpleDrawObjects 

//create serialization factory
var serializeFactory = new ISerializeDrawObjects();

//get protobuf objects from byte[]
var transferred = serializeFactory.ReadFromBuffer(buffer);

//convert protobuf to draw objects
var reCreatedSimpleDrawObjects = serializeDataFactory.CreateSimpleDrawObjects(transferred);

Save ISimpleDrawObjects to protobuf file using ISerializeDrawObjects

//listObjects contains draw objects to serialize

//create serialization factory
var serializeFactory = new ISerializeDrawObjects();

//converts draw objects to protobuf using C2525 
var protobufC2525 = serializeFactory.CreateProtobufFromSimpleDrawObjects(listObjects, 
                                                                        SerializeModes.FullPrecision);

//store protobuf to file
serializeFactory.SaveToFile(protobufC2525, filename);

Create ISimpleDrawObjects from protobuf file using ISerializeDrawObjects

//create serialization factory
var serializeFactory = new ISerializeDrawObjects();

//read protobuf from file
var protobufC2525 = serializeFactory.ReadFromFile(filename);

//create draw objects from protobuf5    
var transferedGdkObjects = serializeFactory.CreateSimpleDrawObjects(protobufC2525);

Search C2525

Use C2525CodeParser to find the C2525 code for a hierarchy code.

C2525CodeParser parser = new C2525CodeParser();
parser.Load();

//returns true if code is known. A draw object with this code will be "compressed".
var result = parser.FindHierarchyCode("TACGRP.TSK.DLY");

Useful tips

The protobuf serialization has been optimized, but it is also important that the draw objects do not carry unnecessary information.

This mean that attributes that do not have to be transferred should be reset:

  • Text = ""
  • Number = 0
  • Lists = empty

Also, the Extra Fields attribute can significantly increase the data size since values are represented both with attribute name and value.

The data size can be verified by checking the size of the protobuf buffer:

//converts draw objects to protobuf using C2525         
var serializedBuffer = serializeFactory.Encode(listObjects, SerializeModes.FullPrecision);
//get the size of the buffer                                             
var dataSize = serializedBuffer.Length;