Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions docs/object-model-schema.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"VimFormatVersion": "1.0.0",
"SchemaVersion": "5.8.0",
"SchemaVersion": "5.9.0",
"Tables": {
"Vim.Area": [
"byte:IsGrossInterior",
Expand Down Expand Up @@ -151,6 +151,7 @@
"index:Vim.Room:Room",
"index:Vim.View:OwnerView",
"index:Vim.Workset:Workset",
"int:LocationSource",
"long:Id",
"string:Creator",
"string:FamilyName",
Expand Down Expand Up @@ -402,7 +403,8 @@
"string:Name"
],
"Vim.Shape": [
"index:Vim.Element:Element"
"index:Vim.Element:Element",
"int:Kind"
],
"Vim.ShapeCollection": [
"index:Vim.Element:Element"
Expand Down
6 changes: 6 additions & 0 deletions docs/schema-diff.json
Original file line number Diff line number Diff line change
Expand Up @@ -232,5 +232,11 @@
"Vim.SunAndShadowSettings__string:StartDateAndTime",
"Vim.SunAndShadowSettings__string:SunAndShadowType"
]
},
"5.8.0 to 5.9.0": {
"Added": [
"Vim.Element__int:LocationSource",
"Vim.Shape__int:Kind"
]
}
}
79 changes: 79 additions & 0 deletions src/cpp/vim/object-model.h
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,7 @@ namespace Vim
float mLocation_X;
float mLocation_Y;
float mLocation_Z;
int mLocationSource;
std::string mFamilyName;
bool mIsPinned;
std::string mCreator;
Expand Down Expand Up @@ -1061,6 +1062,7 @@ namespace Vim
element->mLocation_X = GetLocation_X(elementIndex);
element->mLocation_Y = GetLocation_Y(elementIndex);
element->mLocation_Z = GetLocation_Z(elementIndex);
element->mLocationSource = GetLocationSource(elementIndex);
element->mFamilyName = GetFamilyName(elementIndex);
element->mIsPinned = GetIsPinned(elementIndex);
element->mCreator = GetCreator(elementIndex);
Expand Down Expand Up @@ -1089,6 +1091,7 @@ namespace Vim
bool existsLocation_X = mEntityTable.column_exists("float:Location.X");
bool existsLocation_Y = mEntityTable.column_exists("float:Location.Y");
bool existsLocation_Z = mEntityTable.column_exists("float:Location.Z");
bool existsLocationSource = mEntityTable.column_exists("int:LocationSource");
bool existsFamilyName = mEntityTable.column_exists("string:FamilyName");
bool existsIsPinned = mEntityTable.column_exists("byte:IsPinned");
bool existsCreator = mEntityTable.column_exists("string:Creator");
Expand Down Expand Up @@ -1142,6 +1145,11 @@ namespace Vim
memcpy(location_ZData, mEntityTable.mDataColumns["float:Location.Z"].begin(), count * sizeof(float));
}

int* locationSourceData = new int[count];
if (mEntityTable.column_exists("int:LocationSource")) {
memcpy(locationSourceData, mEntityTable.mDataColumns["int:LocationSource"].begin(), count * sizeof(int));
}

const std::vector<int>& familyNameData = mEntityTable.column_exists("string:FamilyName") ? mEntityTable.mStringColumns["string:FamilyName"] : std::vector<int>();

bfast::byte* isPinnedData = new bfast::byte[count];
Expand Down Expand Up @@ -1185,6 +1193,8 @@ namespace Vim
entity.mLocation_Y = location_YData[i];
if (existsLocation_Z)
entity.mLocation_Z = location_ZData[i];
if (existsLocationSource)
entity.mLocationSource = locationSourceData[i];
if (existsFamilyName)
entity.mFamilyName = std::string(reinterpret_cast<const char*>(mStrings[familyNameData[i]]));
if (existsIsPinned)
Expand Down Expand Up @@ -1213,6 +1223,7 @@ namespace Vim
delete[] location_XData;
delete[] location_YData;
delete[] location_ZData;
delete[] locationSourceData;
delete[] isPinnedData;

return element;
Expand Down Expand Up @@ -1426,6 +1437,34 @@ namespace Vim
return result;
}

int GetLocationSource(int elementIndex)
{
if (elementIndex < 0 || elementIndex >= GetCount())
return {};

if (mEntityTable.column_exists("int:LocationSource")) {
return *reinterpret_cast<int*>(const_cast<bfast::byte*>(mEntityTable.mDataColumns["int:LocationSource"].begin() + elementIndex * sizeof(int)));
}

return {};
}

std::vector<int>* GetAllLocationSource()
{
const auto count = GetCount();

int* locationSourceData = new int[count];
if (mEntityTable.column_exists("int:LocationSource")) {
memcpy(locationSourceData, mEntityTable.mDataColumns["int:LocationSource"].begin(), count * sizeof(int));
}

std::vector<int>* result = new std::vector<int>(locationSourceData, locationSourceData + count);

delete[] locationSourceData;

return result;
}

std::string GetFamilyName(int elementIndex)
{
if (elementIndex < 0 || elementIndex >= GetCount())
Expand Down Expand Up @@ -10398,6 +10437,7 @@ namespace Vim
{
public:
int mIndex;
int mKind;

int mElementIndex;
Element* mElement;
Expand All @@ -10422,32 +10462,71 @@ namespace Vim
{
Shape* shape = new Shape();
shape->mIndex = shapeIndex;
shape->mKind = GetKind(shapeIndex);
shape->mElementIndex = GetElementIndex(shapeIndex);
return shape;
}

std::vector<Shape>* GetAll()
{
bool existsKind = mEntityTable.column_exists("int:Kind");
bool existsElement = mEntityTable.column_exists("index:Vim.Element:Element");

const auto count = GetCount();

std::vector<Shape>* shape = new std::vector<Shape>();
shape->reserve(count);

int* kindData = new int[count];
if (mEntityTable.column_exists("int:Kind")) {
memcpy(kindData, mEntityTable.mDataColumns["int:Kind"].begin(), count * sizeof(int));
}

const std::vector<int>& elementData = mEntityTable.column_exists("index:Vim.Element:Element") ? mEntityTable.mIndexColumns["index:Vim.Element:Element"] : std::vector<int>();

for (int i = 0; i < count; ++i)
{
Shape entity;
entity.mIndex = i;
if (existsKind)
entity.mKind = kindData[i];
entity.mElementIndex = existsElement ? elementData[i] : -1;
shape->push_back(entity);
}

delete[] kindData;

return shape;
}

int GetKind(int shapeIndex)
{
if (shapeIndex < 0 || shapeIndex >= GetCount())
return {};

if (mEntityTable.column_exists("int:Kind")) {
return *reinterpret_cast<int*>(const_cast<bfast::byte*>(mEntityTable.mDataColumns["int:Kind"].begin() + shapeIndex * sizeof(int)));
}

return {};
}

std::vector<int>* GetAllKind()
{
const auto count = GetCount();

int* kindData = new int[count];
if (mEntityTable.column_exists("int:Kind")) {
memcpy(kindData, mEntityTable.mDataColumns["int:Kind"].begin(), count * sizeof(int));
}

std::vector<int>* result = new std::vector<int>(kindData, kindData + count);

delete[] kindData;

return result;
}

int GetElementIndex(int shapeIndex)
{
if (!mEntityTable.column_exists("index:Vim.Element:Element")) {
Expand Down
78 changes: 78 additions & 0 deletions src/cs/vim/Vim.Format.Tests/DrawingCurveEntityTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using System.IO;
using System.Linq;
using NUnit.Framework;
using Vim.Format.ObjectModel;
using Vim.Format.SceneBuilder;
using Vim.LinqArray;
using Vim.Math3d;
using Vim.Util.Tests;

namespace Vim.Format.Tests
{
/// <summary>
/// Object model 5.9.0: Shape.Kind (what a polyline draws) and Element.LocationSource (where Element.Location comes from)
/// round-trip through a VIM file, and the shape polylines stay in the G3D shape buffers in Shape row order.
/// </summary>
[TestFixture]
public static class DrawingCurveEntityTests
{
[Test]
public static void TestShapeKindAndLocationSourceRoundTrip()
{
var ctx = new CallerTestContext();
var dir = ctx.PrepareDirectory();

var store = new ObjectModelStore();
var omb = store.ObjectModelBuilder;

var bimDocument = new BimDocument { Name = "Drawing curves", Title = "Drawing curves" };
var bimDocumentElement = omb.ElementBuilder.Add(bimDocument.CreateParameterHolderElement()).Entity;
bimDocument._Element.Index = bimDocumentElement.Index;
omb.BimDocumentBuilder.Add(bimDocument);

var door = omb.ElementBuilder.Add(new Element
{
Id = 30, Name = "Door", UniqueId = "door",
Location = new Vector3(3, -26, 0),
LocationSource = (int) ElementLocationSource.LocationPoint,
}).Entity;
var empty = omb.ElementBuilder.Add(new Element
{
Id = 31, Name = "Empty family", UniqueId = "empty",
Location = new Vector3(19, -26, 0),
LocationSource = (int) ElementLocationSource.InstanceOrigin,
}).Entity;
var type = omb.ElementBuilder.Add(new Element { Id = 32, Name = "A type", UniqueId = "type", LocationSource = (int) ElementLocationSource.None }).Entity;

// A door swing (symbolic arc, 3 points) and a void edge (2 points) on the door.
store.Shapes.Add(new DocumentBuilder.Shape { Vertices = new[] { new Vector3(2, -27, 0), new Vector3(2.7f, -26.7f, 0), new Vector3(3, -26, 0) }.ToList(), Color = new Vector4(0, 0, 0, 1), Width = 1 });
omb.ShapeBuilder.AddUntracked(new Shape { _Element = { Index = door.Index }, Kind = (int) ShapeKind.SymbolicCurve });
store.Shapes.Add(new DocumentBuilder.Shape { Vertices = new[] { new Vector3(2, -26, 0), new Vector3(2, -26, 2) }.ToList(), Color = new Vector4(0, 0, 0, 1), Width = 1 });
omb.ShapeBuilder.AddUntracked(new Shape { _Element = { Index = door.Index }, Kind = (int) ShapeKind.VoidEdge });

var path = Path.Combine(dir, "drawing-curves.vim");
store.ToDocumentBuilder(nameof(DrawingCurveEntityTests), "0.0.0").Write(path);

var vim = VimScene.LoadVim(path);
vim.Validate();
var dm = vim.DocumentModel;

Assert.AreEqual(SchemaVersion.Current.ToString(), vim.Document.Header.Schema.ToString());
Assert.AreEqual(ElementLocationSource.LocationPoint, dm.GetElement(door.Index).GetLocationSource());
Assert.AreEqual(ElementLocationSource.InstanceOrigin, dm.GetElement(empty.Index).GetLocationSource());
Assert.AreEqual(new Vector3(19, -26, 0), dm.GetElement(empty.Index).Location);
Assert.AreEqual(ElementLocationSource.None, dm.GetElement(type.Index).GetLocationSource());

Assert.AreEqual(2, dm.NumShape);
Assert.AreEqual(ShapeKind.SymbolicCurve, dm.GetShape(0).GetKind());
Assert.AreEqual(ShapeKind.VoidEdge, dm.GetShape(1).GetKind());
Assert.AreEqual("door", dm.GetShape(1).Element.UniqueId);

var g = vim.Document.Geometry;
Assert.AreEqual(2, g.ShapeVertexOffsets.Count);
Assert.AreEqual(5, g.ShapeVertices.Count);
Assert.AreEqual(3, g.ShapeVertexOffsets[1]);
Assert.AreEqual(new Vector3(2, -26, 2), g.ShapeVertices[4]);
}
}
}
Loading