/
Team8
/
kittycad
Обзор
Документация
Войти
/
Team8
/
kittycad
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/data/assembly/solid_clone.cpp
277 строк
7 KB
levovix
fix: simplified thread displaying for dependant objects
09 янв 2026, 23:44
09 янв 2026, 23:44
0008553
Код
Авторство
О чём код?
#include "./solid_clone.h" #include <solid.h> #include <mesh.h> #include <model.h> #include <gcm_api.h> #include <cur_polyline.h> #include <vsn_scenesegment.h> #include <vsn_scenecontent.h> #include <vsn_geometryfactory.h> #include <vsn_selectionmanager.h> #include "data/assembly/assembly.h" #include "data/assembly/constraints.h" #include "data/sketch/sketch.h" #include "data/document.h" #include "graphics/drawable.h" using namespace VSN; using namespace c3d; void data::SolidClone::updateFromParams() { assert(m_propertyChanged && !m_dependencyChanged); m_propertyChanged = false; if (!solid) { markDependencyChanged(nullptr); updateFromDependencies(); return; } Mat3 reverseSolid; currentSolidTransform.Div(reverseSolid); currentSolidTransform = transformation(); solid->Transform(reverseSolid); solid->Transform(currentSolidTransform); for (const auto& d : drawables) { d->transform.Transform(reverseSolid); d->transform.Transform(currentSolidTransform); } if (visual) { visual->GetTransform().SetMatrix(reverseInitialTransformation * currentSolidTransform); } // пересобираем указатели на топологию if (gcmSystem != nullptr) { for (auto prim : primitives) { if (prim.gcmId != _GCM_NULL) { GCM_RemoveGeom(gcmSystem, prim.gcmId); } } primitives.clear(); registerInGcm(gcmSystem); } } void data::SolidClone::updateFromDependencies() { assert(m_dependencyChanged); markVisualChanged(); m_propertyChanged = false; m_dependencyChanged = false; solid = nullptr; if (targetSolid == nullptr || targetSolid->solid == nullptr) { return; } solid = SPtr<MbSolid>(static_cast<MbSolid*>(&targetSolid->solid->Duplicate())); if (solid == nullptr) { return; } currentSolidTransform = transformation(); solid->Transform(currentSolidTransform); for (const auto& d : targetSolid->drawables) { auto newD = d->clone(); newD->transform.Transform(currentSolidTransform); drawables.push_back(newD); } // пересобираем указатели на топологию if (gcmSystem != nullptr) { for (auto prim : primitives) { if (prim.gcmId != _GCM_NULL) { GCM_RemoveGeom(gcmSystem, prim.gcmId); } } primitives.clear(); registerInGcm(gcmSystem); } } void data::SolidClone::buildVisual() { assert(m_visualChanged); m_visualChanged = false; deleteVisual(); if (solid == nullptr) { return; } auto mathRep = GeometryFactory::Instance()->CreateMathRep( solid, CommandType::Synchronous, 0.05 ); SceneSegment* parent = nullptr; if (!parentAssembly.expired()) { if (parentAssembly.lock()->visual == nullptr) { parentAssembly.lock()->buildVisual(); } parent = parentAssembly.lock()->visual; } currentSolidTransform.Div(reverseInitialTransformation); visual = new SceneSegment(mathRep, parent); document.lock()->sceneContent->GetRootSegment()->AddSegment(visual); document.lock()->sceneToData[visual] = weak_from_this(); visual->SetVisible(visible); } std::string_view data::SolidClone::iconName() const { return "tool_solid_clone"; } void data::SolidClone::registerInGcm(GCM_system gcmSystem) { this->gcmSystem = gcmSystem; primitives.clear(); if (solid != nullptr) { primitives.push_back({ GCM_AddGeom(gcmSystem, GCM_SolidLCS(MbPlacement3D(transformation()))), nullptr, }); Mat3 inverseTransform; transformation().Div(inverseTransform); std::vector<MbVertex*> vertices; solid->GetVertices(vertices); for (auto vertex : vertices) { Point3 p = vertex->GetCartPoint(); p.Transform(inverseTransform); primitives.push_back({ GCM_SubGeom( gcmSystem, primitives[0].gcmId, GCM_Point(p) ), vertex, }); } std::vector<MbEdge*> edges; solid->GetEdges(edges); for (auto edge : edges) { Point3 start, end; edge->GetBegPoint(start); edge->GetEndPoint(end); start.Transform(inverseTransform); end.Transform(inverseTransform); primitives.push_back({ GCM_SubGeom( gcmSystem, primitives[0].gcmId, GCM_Line(start, end - start) ), edge, }); } std::vector<MbFace*> faces; solid->GetFaces(faces); for (auto face : faces) { if (face->IsPlanar()) { MbPlacement3D plane; face->GetPlanePlacement(plane); plane.Transform(inverseTransform); primitives.push_back({ GCM_SubGeom( gcmSystem, primitives[0].gcmId, GCM_Plane(plane.GetOrigin(), plane.GetAxisZ()) ), face, }); } else { MbAxis3D axis; face->GetCylinderAxis(axis); axis.Transform(inverseTransform); primitives.push_back({ GCM_SubGeom( gcmSystem, primitives[0].gcmId, GCM_Line(axis.GetOrigin(), axis.GetAxisZ()) ), face, }); } } } } void data::SolidClone::updateFromGcm(GCM_system gcmSystem) { if (primitives.size() == 0) { return; } MbPlacement3D placement = GCM_Placement(gcmSystem, primitives[0].gcmId); Mat3 mat = placement.GetMatrixFrom(); bool changed = false; if (position != placement.GetOrigin()) { position = placement.GetOrigin(); changed = true; } Vec3 newRotation; newRotation.y = -std::asin(mat.El(0, 2)); if (std::cos(newRotation.y) > 1e-6) { newRotation.x = -std::atan2(-mat.El(1, 2), mat.El(2, 2)); newRotation.z = -std::atan2(-mat.El(0, 1), mat.El(0, 0)); } else { newRotation.x = 0; newRotation.z = std::atan2(mat.El(1, 0), mat.El(1, 1)); } if (newRotation != rotation) { rotation = newRotation; changed = true; } // todo: для полного обратного преобразования не хватает scale, но пока он всегда 1 if (changed) { markPropertyChanged(); } } GCM_geom data::SolidClone::gcmIdAt(int index) { if (index >= 0 && index < primitives.size()) { return primitives[index].gcmId; } index -= primitives.size(); return _GCM_NULL; } int data::SolidClone::findGeom(VSN::SelectionItem* item) { if (item->GetSceneSegment() != visual) { return -1; } if (auto inst = dynamic_cast<InstSelectionItem*>(item)) { MbTopologyItem const* prim = inst->GetPrimitiveItem(); if (prim != nullptr) { for (int i = 1; i < primitives.size(); ++i) { if (primitives[i].mathRep == prim) { return i; } } } } return 0; } Mat3 data::SolidClone::transformation() const { Mat3 transform; transform.Move(-origin); transform.Scale(scale.x, scale.y, scale.z); transform.Rotate(AXIS_0X, rotation.x); transform.Rotate(AXIS_0Y, rotation.y); transform.Rotate(AXIS_0Z, rotation.z); transform.Move(origin + position); return transform; }