diff --git a/bouncer/src/repo/core/model/bson/repo_bson_calibration.h b/bouncer/src/repo/core/model/bson/repo_bson_calibration.h
new file mode 100644
index 000000000..5adbf09a2
--- /dev/null
+++ b/bouncer/src/repo/core/model/bson/repo_bson_calibration.h
@@ -0,0 +1,42 @@
+/**
+* Copyright (C) 2024 3D Repo Ltd
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License as
+* published by the Free Software Foundation, either version 3 of the
+* License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see .
+*/
+
+/**
+* Assets BSON
+*/
+
+#pragma once
+
+#include "repo_bson.h"
+
+namespace repo {
+ namespace core {
+ namespace model {
+
+ class REPO_API_EXPORT RepoCalibration : public RepoBSON
+ {
+ public:
+
+ RepoCalibration() : RepoBSON() {}
+
+ RepoCalibration(RepoBSON bson) : RepoBSON(bson) {}
+
+ ~RepoCalibration() {}
+ };
+ }// end namespace model
+ } // end namespace core
+} // end namespace repo
diff --git a/bouncer/src/repo/core/model/bson/repo_bson_factory.cpp b/bouncer/src/repo/core/model/bson/repo_bson_factory.cpp
index aeb6528c2..a84a67f5a 100644
--- a/bouncer/src/repo/core/model/bson/repo_bson_factory.cpp
+++ b/bouncer/src/repo/core/model/bson/repo_bson_factory.cpp
@@ -742,6 +742,74 @@ RepoAssets RepoBSONFactory::makeRepoBundleAssets(
return RepoAssets(builder.obj());
}
+RepoCalibration repo::core::model::RepoBSONFactory::makeRepoCalibration(
+ const repo::lib::RepoUUID& projectId,
+ const repo::lib::RepoUUID& drawingId,
+ const repo::lib::RepoUUID& revisionId,
+ const std::vector& horizontal3d,
+ const std::vector& horizontal2d,
+ const std::vector& verticalRange,
+ const std::string& units)
+{
+ RepoBSONBuilder bsonBuilder;
+ bsonBuilder.append(REPO_LABEL_ID, repo::lib::RepoUUID::createUUID());
+ bsonBuilder.append(REPO_LABEL_PROJECT, projectId);
+ bsonBuilder.append(REPO_LABEL_DRAWING, drawingId);
+ bsonBuilder.append(REPO_LABEL_REVISION, revisionId);
+ bsonBuilder.appendTimeStamp(REPO_LABEL_CREATEDAT);
+
+ RepoBSONBuilder horizontalBuilder;
+ if (horizontal3d.size() == 2) {
+ std::vector>arrays;
+ std::vector arr1;
+ arr1.push_back(horizontal3d[0].x);
+ arr1.push_back(horizontal3d[0].y);
+ arr1.push_back(horizontal3d[0].z);
+ arrays.push_back(arr1);
+
+ std::vector arr2;
+ arr2.push_back(horizontal3d[1].x);
+ arr2.push_back(horizontal3d[1].y);
+ arr2.push_back(horizontal3d[1].z);
+ arrays.push_back(arr2);
+
+ horizontalBuilder.appendArray(REPO_LABEL_MODEL, arrays);
+ }
+ else {
+ repoError << "Incorrect amount of horizontal 3D vectors supplied to makeRepoCalibration" << std::endl;
+ }
+
+ if (horizontal2d.size() == 2) {
+ std::vector>arrays;
+ std::vector arr1;
+ arr1.push_back(horizontal2d[0].x);
+ arr1.push_back(horizontal2d[0].y);
+ arrays.push_back(arr1);
+
+ std::vector arr2;
+ arr2.push_back(horizontal2d[1].x);
+ arr2.push_back(horizontal2d[1].y);
+ arrays.push_back(arr2);
+
+ horizontalBuilder.appendArray(REPO_LABEL_DRAWING, arrays);
+ }
+ else {
+ repoError << "Incorrect amount of horizontal 2D vectors supplied to makeRepoCalibration" << std::endl;
+ }
+ bsonBuilder.append(REPO_LABEL_HORIZONTAL, horizontalBuilder.obj());
+
+ if (verticalRange.size() == 2) {
+ bsonBuilder.appendArray(REPO_LABEL_VERTICALRANGE, verticalRange);
+ }
+ else {
+ repoError << "Incorrect amount of values for vertical range supplied to makeRepoCalibration" << std::endl;
+ }
+
+ bsonBuilder.append(REPO_LABEL_UNITS, units);
+
+ return RepoCalibration(bsonBuilder.obj());
+}
+
ReferenceNode RepoBSONFactory::makeReferenceNode(
const std::string &database,
const std::string &project,
diff --git a/bouncer/src/repo/core/model/bson/repo_bson_factory.h b/bouncer/src/repo/core/model/bson/repo_bson_factory.h
index ac4dfdf4b..85b68aa84 100644
--- a/bouncer/src/repo/core/model/bson/repo_bson_factory.h
+++ b/bouncer/src/repo/core/model/bson/repo_bson_factory.h
@@ -29,6 +29,7 @@
#include "repo_bson_task.h"
#include "repo_bson_user.h"
#include "repo_bson_assets.h"
+#include "repo_bson_calibration.h"
#include "repo_node.h"
#include "repo_node_camera.h"
#include "repo_node_metadata.h"
@@ -162,6 +163,27 @@ namespace repo {
const std::vector& repoJsonFiles,
const std::vector metadata);
+ /**
+ * Create a Drawing Calibration BSON
+ * @param projectId uuid of the project
+ * @param drawingId uuid of the drawing
+ * @param revisionId uuid of the revision
+ * @param horizontal3d two reference points in the 3d space
+ * @param horizontal2d two reference points in the 2d space
+ * @param verticalRange two values marking the vertical range
+ * @param units the units used for the values.
+ * @return returns a RepoCalibration
+ */
+ static RepoCalibration makeRepoCalibration(
+ const repo::lib::RepoUUID& projectId,
+ const repo::lib::RepoUUID& drawingId,
+ const repo::lib::RepoUUID& revisionId,
+ const std::vector& horizontal3d,
+ const std::vector& horizontal2d,
+ const std::vector& verticalRange,
+ const std::string& units
+ );
+
/*
* -------------------- REPO NODES ------------------------
*/
diff --git a/bouncer/src/repo/core/model/repo_model_global.h b/bouncer/src/repo/core/model/repo_model_global.h
index 24b523a38..c50652439 100644
--- a/bouncer/src/repo/core/model/repo_model_global.h
+++ b/bouncer/src/repo/core/model/repo_model_global.h
@@ -81,6 +81,15 @@
// Vertex/triangle map propeties
#define REPO_LABEL_MERGED_NODES "merged_nodes"
+// Drawing calibration properties
+#define REPO_LABEL_DRAWING "drawing"
+#define REPO_LABEL_REVISION "revision"
+#define REPO_LABEL_CREATEDAT "createdAt"
+#define REPO_LABEL_CREATEDBY "createdBy"
+#define REPO_LABEL_HORIZONTAL "horizontal"
+#define REPO_LABEL_VERTICALRANGE "verticalRange"
+#define REPO_LABEL_UNITS "units"
+
#define REPO_COMMAND_UPDATE "update"
#define REPO_COMMAND_UPDATES "updates"
#define REPO_COMMAND_DELETE "delete"
@@ -105,6 +114,7 @@
#define REPO_COLLECTION_SEQUENCE "sequences"
#define REPO_COLLECTION_TASK "activities"
#define REPO_COLLECTION_DRAWINGS "drawings.history"
+#define REPO_COLLECTION_CALIBRATIONS "drawings.revisions.calibrations"
#define REPO_COLLECTION_SETTINGS "settings"
diff --git a/bouncer/src/repo/manipulator/modelconvertor/import/odaHelper/file_processor_dgn.cpp b/bouncer/src/repo/manipulator/modelconvertor/import/odaHelper/file_processor_dgn.cpp
index 303c360e5..cd447ba0a 100644
--- a/bouncer/src/repo/manipulator/modelconvertor/import/odaHelper/file_processor_dgn.cpp
+++ b/bouncer/src/repo/manipulator/modelconvertor/import/odaHelper/file_processor_dgn.cpp
@@ -358,10 +358,50 @@ void FileProcessorDgn::importDrawing(OdDgDatabasePtr pDb, const ODCOLORREF* pPal
// to the 3D coordinates above. Add these to the appropriate schema when
// it is ready...
- std::vector points;
- points.push_back(worldToDeviceMatrix * a);
- points.push_back(worldToDeviceMatrix * b);
- points.push_back(worldToDeviceMatrix * c);
+ //std::vector points;
+ //points.push_back(worldToDeviceMatrix * a);
+ //points.push_back(worldToDeviceMatrix * b);
+ //points.push_back(worldToDeviceMatrix * c);
+
+ // Calculate points in SVG space
+ OdGePoint3d aS = worldToDeviceMatrix * a;
+ OdGePoint3d bS = worldToDeviceMatrix * b;
+
+ // Convert to 2D by dropping z component (note: have not thought about it. Just conceptually).
+ repo::lib::RepoVector2D aS2d = repo::lib::RepoVector2D(aS.x, aS.y);
+ repo::lib::RepoVector2D bS2d = repo::lib::RepoVector2D(bS.x, bS.y);
+
+ // Convert 3d vectors from ODA format to 3d repo format
+ repo::lib::RepoVector3D a3d = repo::lib::RepoVector3D(a.x, a.y, a.z);
+ repo::lib::RepoVector3D b3d = repo::lib::RepoVector3D(b.x, b.y, b.z);
+
+ // Assemble calibration outcome
+ std::vector horizontal3d;
+ horizontal3d.push_back(a3d);
+ horizontal3d.push_back(b3d);
+
+ std::vector horizontal2d;
+ horizontal2d.push_back(aS2d);
+ horizontal2d.push_back(bS2d);
+
+ repo::manipulator::modelutility::DrawingCalibration calibration;
+ calibration.horizontalCalibration3d = horizontal3d;
+ calibration.horizontalCalibration2d = horizontal2d;
+
+ calibration.verticalRange = { 0, 10 }; // TODO: how do I calculate that?
+
+ OdDgElementId elementActId = pDb->getActiveModelId();
+ OdDgModelPtr pModel = elementActId.safeOpenObject();
+
+ repo::manipulator::modelconvertor::ModelUnits units = determineModelUnits(pModel->getMasterUnit());
+
+ calibration.units = repo::manipulator::modelconvertor::toUnitsString(units);
+
+
+
+ // Pass calibration outcome to collector
+ drawingCollector->drawingCalibration = calibration;
+
// The call to update is what will create the svg in the memory stream
diff --git a/bouncer/src/repo/manipulator/modelconvertor/import/odaHelper/file_processor_dwg.cpp b/bouncer/src/repo/manipulator/modelconvertor/import/odaHelper/file_processor_dwg.cpp
index 5940a6486..275c546ab 100644
--- a/bouncer/src/repo/manipulator/modelconvertor/import/odaHelper/file_processor_dwg.cpp
+++ b/bouncer/src/repo/manipulator/modelconvertor/import/odaHelper/file_processor_dwg.cpp
@@ -35,6 +35,9 @@
#include "data_processor_dwg.h"
+#include
+#include
+
using namespace repo::manipulator::modelconvertor::odaHelper;
class VectoriseDeviceDwg : public OdGsBaseVectorizeDevice
@@ -84,7 +87,7 @@ class DeviceModuleDwg : public OdGsBaseModule
};
ODRX_DEFINE_PSEUDO_STATIC_MODULE(DeviceModuleDwg);
-void importModel(OdDbDatabasePtr pDb, GeometryCollector* collector)
+void FileProcessorDwg::importModel(OdDbDatabasePtr pDb)
{
// Create the vectorizer device that will render the DWG database. This will
// use the GeometryCollector underneath.
@@ -108,7 +111,7 @@ void importModel(OdDbDatabasePtr pDb, GeometryCollector* collector)
pGsModule.release();
}
-void importDrawing(OdDbDatabasePtr pDb, repo::manipulator::modelutility::DrawingImageInfo* collector)
+void FileProcessorDwg::importDrawing(OdDbDatabasePtr pDb)
{
OdGsModulePtr pModule = ::odrxDynamicLinker()->loadModule(OdSvgExportModuleName, false);
OdGsDevicePtr dev = pModule->createDevice();
@@ -142,8 +145,67 @@ void importDrawing(OdDbDatabasePtr pDb, repo::manipulator::modelutility::Drawing
pHelperDevice->onSize(OdGsDCRect(0, 1024, 768, 0));
- // Here we can extract the calibration in the same way as file_processor_dgn when ready...
+ // This section extracts the view information which can be used to map
+ // betweeen the SVG and world coordinate systems.
+ // The graphics system (Gs) view https://docs.opendesign.com/tv/gs_OdGsView.html
+ // is used to derive points that map between the WCS of the drawing and
+ // the svg file.
+
+ const OdGsView* pGsView = pDeviceSvg->viewAt(0);
+
+ auto worldToDeviceMatrix = pGsView->worldToDeviceMatrix();
+ auto objectToDeviceMatrix = pGsView->objectToDeviceMatrix();
+
+ // Pick three points (two vectors) to describe the map. The transform
+ // can be computed from these each time from then on.
+
+ OdGePoint3d a(0, 0, 0);
+ OdGePoint3d b(1, 0, 0);
+ OdGePoint3d c(0, 1, 0);
+
+ // The following vector contains the points in the SVG file corresponding
+ // to the 3D coordinates above. Add these to the appropriate schema when
+ // it is ready...
+
+ //std::vector points;
+ //points.push_back(worldToDeviceMatrix * a);
+ //points.push_back(worldToDeviceMatrix * b);
+ //points.push_back(worldToDeviceMatrix * c);
+
+ // Calculate points in SVG space
+ OdGePoint3d aS = worldToDeviceMatrix * a;
+ OdGePoint3d bS = worldToDeviceMatrix * b;
+
+ // Convert to 2D by dropping z component (note: have not thought about it. Just conceptually).
+ repo::lib::RepoVector2D aS2d = repo::lib::RepoVector2D(aS.x, aS.y);
+ repo::lib::RepoVector2D bS2d = repo::lib::RepoVector2D(bS.x, bS.y);
+
+ // Convert 3d vectors from ODA format to 3d repo format
+ repo::lib::RepoVector3D a3d = repo::lib::RepoVector3D(a.x, a.y, a.z);
+ repo::lib::RepoVector3D b3d = repo::lib::RepoVector3D(b.x, b.y, b.z);
+ // Assemble calibration outcome
+ std::vector horizontal3d;
+ horizontal3d.push_back(a3d);
+ horizontal3d.push_back(b3d);
+
+ std::vector horizontal2d;
+ horizontal2d.push_back(aS2d);
+ horizontal2d.push_back(bS2d);
+
+ repo::manipulator::modelutility::DrawingCalibration calibration;
+ calibration.horizontalCalibration3d = horizontal3d;
+ calibration.horizontalCalibration2d = horizontal2d;
+
+ calibration.verticalRange = { 0, 10 }; // TODO: how do I calculate that?
+
+ repo::manipulator::modelconvertor::ModelUnits units = determineModelUnits(pDb->getINSUNITS());
+ calibration.units = repo::manipulator::modelconvertor::toUnitsString(units);
+
+ // Pass calibration outcome to collector
+ drawingCollector->drawingCalibration = calibration;
+
+
pHelperDevice->update();
// Copy the SVG contents into a string
@@ -161,7 +223,21 @@ void importDrawing(OdDbDatabasePtr pDb, repo::manipulator::modelutility::Drawing
// Provide the string to the collector as a vector
- std::copy(svg.c_str(), svg.c_str() + svg.length(), std::back_inserter(collector->data));
+ std::copy(svg.c_str(), svg.c_str() + svg.length(), std::back_inserter(drawingCollector->data));
+ }
+}
+
+repo::manipulator::modelconvertor::ModelUnits FileProcessorDwg::determineModelUnits(const OdDb::UnitsValue units){
+ switch (units) {
+ case OdDb::kUnitsMeters: return ModelUnits::METRES;
+ case OdDb::kUnitsDecimeters: return ModelUnits::DECIMETRES;
+ case OdDb::kUnitsCentimeters: return ModelUnits::CENTIMETRES;
+ case OdDb::kUnitsMillimeters: return ModelUnits::MILLIMETRES;
+ case OdDb::kUnitsFeet: return ModelUnits::FEET;
+ case OdDb::kUnitsInches: return ModelUnits::INCHES;
+ default:
+ repoWarning << "Unrecognised unit measure: " << (int)units;
+ return ModelUnits::UNKNOWN;
}
}
@@ -187,12 +263,12 @@ uint8_t FileProcessorDwg::readFile()
if (collector)
{
- importModel(pDb, collector);
+ importModel(pDb);
}
if (drawingCollector)
{
- importDrawing(pDb, drawingCollector);
+ importDrawing(pDb);
}
pDb.release();
diff --git a/bouncer/src/repo/manipulator/modelconvertor/import/odaHelper/file_processor_dwg.h b/bouncer/src/repo/manipulator/modelconvertor/import/odaHelper/file_processor_dwg.h
index 4a6d95bb9..b4d5e6f8e 100644
--- a/bouncer/src/repo/manipulator/modelconvertor/import/odaHelper/file_processor_dwg.h
+++ b/bouncer/src/repo/manipulator/modelconvertor/import/odaHelper/file_processor_dwg.h
@@ -47,6 +47,11 @@ namespace repo {
protected:
OdStaticRxObject svcs;
+
+ private:
+ void importModel(OdDbDatabasePtr pDb);
+ void importDrawing(OdDbDatabasePtr pDb);
+ ModelUnits determineModelUnits(const OdDb::UnitsValue units);
};
}
}
diff --git a/bouncer/src/repo/manipulator/modelutility/repo_drawing.h b/bouncer/src/repo/manipulator/modelutility/repo_drawing.h
index 3715e0dda..e9dc029a1 100644
--- a/bouncer/src/repo/manipulator/modelutility/repo_drawing.h
+++ b/bouncer/src/repo/manipulator/modelutility/repo_drawing.h
@@ -19,11 +19,22 @@
#include
#include
+#include "repo/lib/datastructure/repo_vector.h"
namespace repo {
namespace manipulator {
namespace modelutility {
+ /**
+ * Holds outcome of the autocalibration
+ */
+ struct DrawingCalibration {
+ std::vector horizontalCalibration3d;
+ std::vector horizontalCalibration2d;
+ std::vector verticalRange;
+ std::string units;
+ };
+
/**
* Holds complete information about an imported drawing at runtime
*/
@@ -31,6 +42,7 @@ namespace repo {
{
std::string name; // The name of the original file (e.g. "Floor1.DWG")
std::vector data; // The drawing in svg format
+ DrawingCalibration drawingCalibration;
};
}
}
diff --git a/bouncer/src/repo/manipulator/modelutility/repo_drawing_manager.cpp b/bouncer/src/repo/manipulator/modelutility/repo_drawing_manager.cpp
index d836e0b7c..413d4b03b 100644
--- a/bouncer/src/repo/manipulator/modelutility/repo_drawing_manager.cpp
+++ b/bouncer/src/repo/manipulator/modelutility/repo_drawing_manager.cpp
@@ -18,6 +18,7 @@
#include "../../core/model/bson/repo_bson_builder.h"
#include "../../core/model/bson/repo_bson_ref.h"
+#include "../../core/model/bson/repo_bson_factory.h"
#include "../../error_codes.h"
using namespace repo::manipulator::modelutility;
@@ -45,11 +46,12 @@ uint8_t DrawingManager::commitImage(
auto name = drawing.name.substr(0, drawing.name.size() - 3) + "svg"; // The name should be the drawing's original name with an updated extension
repo::core::model::RepoBSONBuilder metadata;
+ auto revId = revision.getUniqueID();
metadata.append(REPO_NODE_LABEL_NAME, name);
metadata.append(REPO_LABEL_MEDIA_TYPE, REPO_MEDIA_TYPE_SVG);
metadata.append(REPO_LABEL_PROJECT, revision.getProject());
metadata.append(REPO_LABEL_MODEL, revision.getModel());
- metadata.append(REPO_NODE_REVISION_ID, revision.getUniqueID());
+ metadata.append(REPO_NODE_REVISION_ID, revId);
fileManager->uploadFileAndCommit(
teamspace,
@@ -58,7 +60,7 @@ uint8_t DrawingManager::commitImage(
drawing.data,
metadata.obj()
);
-
+
auto updated = revision.cloneAndAddImage(drawingRefNodeId);
std::string error;
@@ -70,5 +72,27 @@ uint8_t DrawingManager::commitImage(
return REPOERR_UPLOAD_FAILED;
}
+ // Retreive and process calibration
+ auto calibration = drawing.drawingCalibration;
+
+ auto calibrationBSON = repo::core::model::RepoBSONFactory::makeRepoCalibration(
+ revision.getProject(),
+ revision.getModel(),
+ revId,
+ calibration.horizontalCalibration3d,
+ calibration.horizontalCalibration2d,
+ calibration.verticalRange,
+ calibration.units
+ );
+
+ handler->insertDocument(teamspace, REPO_COLLECTION_CALIBRATIONS, calibrationBSON, error);
+
+ if (error.size())
+ {
+ repoError << "Error committing calibration: " << error;
+ return REPOERR_UPLOAD_FAILED;
+ }
+
+
return REPOERR_OK;
}
\ No newline at end of file