CreoOtkPluging/CreoManager.h

904 lines
33 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
// 基础OTK头文件 - 确保正确的包含顺序
#include <pfcGlobal.h>
#include <pfcSession.h>
#include <wfcSession.h>
#include <wfcGlobal.h>
#include <pfcModel.h>
#include <pfcExceptions.h>
#include <pfcExport.h>
#include <pfcFeature.h>
#include <pfcComponentFeat.h>
#include <pfcFeature_s.h>
#include <pfcSolid.h>
#include <wfcSolid.h>
#include <wfcSolidInstructions.h>
#include <pfcInterference.h>
#include <pfcSelect.h>
#include <pfcGeometry.h>
#include <pfcAssembly.h>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <cmath>
#include <utility>
#include <limits>
// Prevent Windows macro conflicts with std::min/max
#ifdef max
#undef max
#endif
#ifdef min
#undef min
#endif
// Creo状态信息结构
struct CreoStatus {
bool is_connected = false;
std::string version;
std::string build;
std::string working_directory;
int session_id = 0;
};
// 模型状态信息结构
struct ModelStatus {
bool has_model = false;
std::string name;
std::string filename;
std::string type;
std::string software; // 从OTK API获取不设默认值
std::string version; // 从OTK API获取不设默认值
std::string connection_time;
bool is_assembly = false;
int total_parts = 0;
int assembly_levels = 0;
std::string file_size;
std::string connection_status;
std::string open_time;
bool is_modified = false; // 模型是否已修改(未保存)
};
// 导出结果结构
struct ExportResult {
bool success = false;
std::string export_path;
std::string file_size;
std::string format;
std::string export_time;
std::string software;
std::string original_file;
std::string dirname;
std::string filename;
std::string error_message;
};
// 保存结果结构
struct SaveResult {
bool success = false;
std::string file_size;
std::string save_time;
std::string software;
std::string original_file;
std::string error_message;
};
// 关闭结果结构
struct CloseResult {
bool success = false;
std::string model_name;
bool was_modified = false;
std::string close_time;
std::string error_message;
};
// 打开结果结构
struct OpenResult {
bool success = false;
std::string model_name;
std::string model_type;
std::string file_path;
std::string file_size;
std::string open_time;
bool is_assembly = false;
int total_parts = 0;
bool model_in_session = false; // 验证模型是否真的在会话中
bool window_model_match = false; // 验证窗口是否正确关联模型
std::string error_message;
};
// 层级分析组件信息结构
struct ComponentInfo {
std::string id;
std::string name;
std::string type; // "assembly" 或 "part"
int level;
int children_count;
std::string path;
std::string file_size;
std::string deletion_safety; // "forbidden", "risky", "moderate"
bool is_visible;
std::string model_type; // "MDL_ASSEMBLY", "MDL_PART", "MDL_DRAWING" 等
std::string full_path; // 完整的组件路径
};
// 层级分析请求结构
struct HierarchyAnalysisRequest {
std::string software_type;
std::string project_name;
int max_depth;
bool include_geometry;
int target_level = -1; // 新增:指定返回的层级,-1表示返回所有
std::map<std::string, std::string> analysis_options;
};
// 删除建议结构
struct DeletionRecommendation {
std::string component_id;
std::string component_name;
int level;
std::string reason;
std::vector<std::string> risk_factors;
double confidence;
};
// 层级分析结果结构
struct HierarchyAnalysisResult {
bool success = false;
std::string message;
std::string project_name;
int total_levels;
int total_components;
std::vector<std::vector<ComponentInfo>> hierarchy;
std::vector<DeletionRecommendation> safe_deletions;
std::vector<DeletionRecommendation> risky_deletions;
std::string error_message;
};
// Shell Analysis Constants
namespace ShellAnalysisConstants {
// Confidence thresholds
constexpr double CONFIDENCE_STANDARD_PART = 0.99;
constexpr double CONFIDENCE_INTERNAL_CUT = 0.95;
constexpr double CONFIDENCE_INTERNAL_HOLE = 0.90;
constexpr double CONFIDENCE_INTERNAL_GENERIC = 0.80;
constexpr double CONFIDENCE_SHELL_FEATURE = 0.20;
constexpr double CONFIDENCE_EXTERNAL_FEATURE = 0.05;
// Performance thresholds
constexpr int LARGE_MODEL_THRESHOLD = 500;
constexpr int VERY_LARGE_MODEL_THRESHOLD = 1000;
constexpr double SAMPLING_RATIO_FAST = 0.1;
constexpr double SAMPLING_RATIO_STANDARD = 0.33;
// Geometry calculation weights
constexpr double VOLUME_WEIGHT = 0.5;
constexpr double SURFACE_WEIGHT = 0.3;
constexpr double BBOX_WEIGHT = 0.2;
// Batch processing
constexpr int BATCH_SIZE = 50;
constexpr int MAX_PARALLEL_FEATURES = 100;
// Cache settings
constexpr int CACHE_TTL_SECONDS = 600; // 10 minutes
constexpr int MAX_CACHE_SIZE = 1000;
}
// Analysis modes for large models
enum ShellAnalysisMode {
SHELL_ANALYSIS_FAST = 0, // Fast mode: sampling analysis
SHELL_ANALYSIS_STANDARD = 1, // Standard mode: normal analysis
SHELL_ANALYSIS_DETAILED = 2 // Detailed mode: full analysis
};
// Creo管理器类
class CreoManager {
public:
// 会话管理(避免重复代码)
struct SessionInfo {
pfcSession_ptr session;
wfcWSession_ptr wSession;
bool is_valid;
std::string version;
std::string build;
};
static CreoManager& Instance();
// 状态检测
CreoStatus GetCreoStatus();
ModelStatus GetModelStatus();
// 基础操作
bool ShowMessage(const std::string& message);
// 导出功能
ExportResult ExportModelToSTEP(const std::string& export_path, const std::string& geom_flags = "solids");
// 保存功能
SaveResult SaveModel();
// 关闭功能
CloseResult CloseModel(bool force_close = false);
// 打开功能
OpenResult OpenModel(const std::string& file_path, const std::string& open_mode = "active");
// 层级分析功能
HierarchyAnalysisResult AnalyzeModelHierarchy(const HierarchyAnalysisRequest& request);
// 层级删除功能
struct HierarchyDeleteResult {
bool success = false;
std::string message;
int original_levels;
int target_level;
int final_levels;
std::map<int, std::vector<std::string>> deleted_components;
int total_deleted;
int successful;
int failed;
std::string error_message;
};
HierarchyDeleteResult DeleteHierarchyComponents(const std::string& project_name, int target_level);
// 子装配体层级删除功能 - 以指定子装配体为顶层进行层级删除
HierarchyDeleteResult DeleteSubassemblyHierarchyComponents(const std::string& subassembly_path, int target_level);
// 薄壳化分析功能
struct ShellAnalysisRequest {
std::string software_type;
std::string project_name = "current_model";
std::string analysis_type = "surface_shell";
bool preserve_external_surfaces = true;
double min_wall_thickness = 1.0;
double confidence_threshold = 0.75;
};
struct FeatureDeletion {
int id;
std::string name;
std::string type;
std::string reason;
double confidence;
double volume_reduction; // Changed from int to double for better precision
std::string part_file;
std::string part_path;
std::string component_type = "FEATURE";
std::string volume_units = "percentage"; // Added to clarify units
int vote_count = 0; // Number of votes this component received in multi-directional projection analysis
};
struct EstimatedReduction {
std::string volume_reduction;
std::string file_size_reduction;
std::string performance_improvement;
};
struct HierarchyAnalysisInfo {
bool enabled = true;
int total_parts = 0;
int outer_parts = 0;
int internal_parts = 0;
int containment_relationships = 0;
std::map<std::string, std::string> performance_stats;
};
struct ShellAnalysisParameters {
bool preserve_external_surfaces = true;
double min_wall_thickness = 1.0;
double confidence_threshold = 0.7;
int total_features = 0;
int deletable_features = 0;
int preserved_features = 0;
bool assembly_analysis = false;
std::string analysis_strategy = "multi_directional_projection_analysis";
int surface_count = 0;
int shell_surfaces = 0;
int internal_surfaces = 0;
int shell_feature_whitelist = 0;
HierarchyAnalysisInfo hierarchy_analysis;
};
// New structure for enhanced shell analysis
struct ShellAnalysisItem {
std::string name;
std::string type;
int feature_id;
double confidence;
std::string recommendation;
std::string reason;
std::string path; // 组件完整路径
bool is_deletable = false;
double volume_percentage = 0.0; // Component volume percentage
};
struct ShellAnalysisResult {
bool success = false;
std::vector<FeatureDeletion> safe_deletions;
std::vector<FeatureDeletion> suggested_deletions;
std::vector<FeatureDeletion> preserve_list;
EstimatedReduction estimated_reduction;
ShellAnalysisParameters analysis_parameters;
std::string error_message;
// Enhanced fields for new algorithm
std::vector<ShellAnalysisItem> features;
int total_features_analyzed = 0;
int shell_features_count = 0;
int internal_features_count = 0;
int total_deletable = 0;
double deletion_percentage = 0.0;
std::string model_name;
// OBB optimization statistics
int obb_usage_count = 0;
int aabb_usage_count = 0;
double obb_usage_percentage = 0.0;
};
ShellAnalysisResult AnalyzeShellFeatures(const ShellAnalysisRequest& request);
ShellAnalysisResult AnalyzeShellFeaturesEnhanced(const ShellAnalysisRequest& request);
// 薄壳化分析辅助方法
std::string GetFeatureTypeName(pfcFeatureType feat_type);
bool IsExternalSurface(pfcFeature_ptr feature, bool preserve_external);
bool CheckWallThickness(pfcFeature_ptr feature, double min_thickness);
// 薄壳化算法辅助方法基于真实OTK数据
bool IsStandardPart(const std::string& part_name);
bool IsInternalPart(pfcFeature_ptr feature, pfcModel_ptr model);
// 智能边界检测算法
bool IsOnAssemblyBoundary(pfcFeature_ptr component, pfcOutline3D_ptr assembly_bbox, double tolerance);
double CalculateBoundaryOverlap(pfcOutline3D_ptr comp_bbox, pfcOutline3D_ptr assembly_bbox, double tolerance);
double GetOptimalTolerance(pfcOutline3D_ptr assembly_bbox);
// 真实几何计算方法
double CalculateFeatureVolumeImpact(pfcFeature_ptr feature, pfcSolid_ptr solid);
std::vector<double> CalculateBatchFeatureVolumeImpacts(
const std::vector<pfcFeature_ptr>& features,
pfcSolid_ptr solid,
int batch_size = 10);
// LOO (Leave-One-Out) attribution for accurate feature impact calculation
std::vector<double> CalculateLOOAttribution(
const std::vector<pfcFeature_ptr>& features,
pfcSolid_ptr solid,
int top_k = 10);
// Check feature proximity to external surface
double CheckFeatureProximityToSurface(
pfcFeature_ptr feature,
pfcSolid_ptr solid,
double min_thickness);
// Enhanced geometric boundary detection functions
bool AnalyzeFeatureGeometryEnhanced(
pfcFeature_ptr feature,
pfcSolid_ptr solid,
pfcOutline3D_ptr globalOutline,
double tolerance);
std::vector<pfcSurface_ptr> GetFeatureAffectedSurfaces(pfcFeature_ptr feature, pfcSolid_ptr solid);
bool IsSurfaceOnBoundary(pfcSurface_ptr surface, pfcSolid_ptr solid, pfcOutline3D_ptr globalOutline, double tolerance);
bool CheckSurfaceBoundaryByBounds(pfcSurface_ptr surface, pfcOutline3D_ptr globalOutline, double tolerance);
double CalculateDistanceToExternalSurface(pfcFeature_ptr feature, pfcSolid_ptr solid);
// Enhanced assembly component occlusion analysis
bool IsComponentOccludedByOthers(
pfcFeature_ptr component,
pfcOutline3D_ptr assembly_bbox,
const std::vector<std::pair<pfcFeature_ptr, std::string>>& all_components,
double tolerance);
double CalculateOcclusionRatio(pfcFeature_ptr target, pfcFeature_ptr occluder);
bool HasInterferenceWith(pfcFeature_ptr comp1, pfcFeature_ptr comp2);
// Estimate feature scale based on type and parameters
double EstimateFeatureScale(pfcFeature_ptr feature);
// 大模型优化方法
ShellAnalysisMode DetermineAnalysisMode(int feature_count);
std::vector<int> GetSamplingIndices(int total_features, ShellAnalysisMode mode);
// 优化的估算方法
EstimatedReduction CalculateRealisticReduction(
const std::vector<FeatureDeletion>& deletions,
double original_volume,
int total_features);
// 辅助功能
std::string GetCurrentTimeString();
std::string GetCurrentTimeStringISO();
std::string GetFileSize(const std::string& filepath);
int SafeCalculateAssemblyLevels(wfcWAssembly_ptr assembly);
// 会话信息获取
SessionInfo GetSessionInfo();
// Volume calculation
double GetComponentVolume(pfcSolid_ptr solid);
// 字符串转换辅助函数
std::string XStringToString(const xstring& xstr);
// 组件路径构建函数
std::string BuildComponentFullPath(wfcWComponentPath_ptr componentPath, const std::string& assemblyName);
// 文件大小统计
std::string GetModelFileSize(pfcModel_ptr model);
std::string CalculateAssemblyTotalSize(pfcModel_ptr model);
double ParseMBFromSizeString(const std::string& size_str);
// Component analysis helper methods
std::string EvaluateDeletionSafety(const ComponentInfo& component);
std::string GetComponentFileSize(wfcWComponentPath_ptr component_path);
std::string GetModelTypeString(pfcModelType model_type);
int CountChildComponents(wfcWComponentPath_ptr component_path);
private:
CreoManager(); // 需要自定义构造函数来设置配置
~CreoManager() = default;
CreoManager(const CreoManager&) = delete;
CreoManager& operator=(const CreoManager&) = delete;
// 辅助函数
xstring StringToXString(const std::string& str);
std::pair<std::string, std::string> ParseFilePath(const std::string& file_path);
// 层级分析私有方法 (新SOTA算法)
void AnalyzeAssemblyNode(wfcWAssembly_ptr assembly,
int level,
const std::string& parentName,
const std::string& currentPath,
HierarchyAnalysisResult& result,
int target_level = -1); // 新增参数
ComponentInfo CreateComponentFromFeature(pfcComponentFeat_ptr compFeat,
int level,
const std::string& parentName,
const std::string& currentPath,
pfcModel_ptr preloadedModel = nullptr);
pfcModel_ptr LoadComponentModel(pfcComponentFeat_ptr compFeat);
// 薄壳化分析递归方法
void CollectAllComponentsForShellAnalysis(wfcWAssembly_ptr assembly,
const std::string& parentPath,
std::vector<std::pair<pfcFeature_ptr, std::string>>& allComponents);
// Shell Analysis Cache
class ShellAnalysisCache {
private:
struct FeatureCacheEntry {
double volume_impact;
double surface_impact;
double confidence;
std::time_t timestamp;
std::string model_version; // Added for cache validation
int64_t model_modified_time; // Added for cache validation
};
std::map<std::string, FeatureCacheEntry> cache;
public:
bool GetCachedImpact(const std::string& key, double& volume, double& surface,
const std::string& current_version = "",
int64_t current_modified_time = 0) {
auto it = cache.find(key);
if (it != cache.end()) {
// Check both TTL and model state consistency
bool ttl_valid = (std::time(nullptr) - it->second.timestamp < ShellAnalysisConstants::CACHE_TTL_SECONDS);
bool version_valid = (current_version.empty() || it->second.model_version == current_version);
bool time_valid = (current_modified_time == 0 || it->second.model_modified_time == current_modified_time);
if (ttl_valid && version_valid && time_valid) {
volume = it->second.volume_impact;
surface = it->second.surface_impact;
return true;
}
// Invalid cache entry, remove it
cache.erase(it);
}
return false;
}
void SetCachedImpact(const std::string& key, double volume, double surface,
const std::string& model_version = "",
int64_t model_modified_time = 0) {
FeatureCacheEntry entry;
entry.volume_impact = volume;
entry.surface_impact = surface;
entry.timestamp = std::time(nullptr);
entry.model_version = model_version;
entry.model_modified_time = model_modified_time;
cache[key] = entry;
// Limit cache size
if (cache.size() > ShellAnalysisConstants::MAX_CACHE_SIZE) {
auto oldest = cache.begin();
for (auto it = cache.begin(); it != cache.end(); ++it) {
if (it->second.timestamp < oldest->second.timestamp) {
oldest = it;
}
}
cache.erase(oldest);
}
}
void ClearCache() {
cache.clear();
}
};
// Cache instance
ShellAnalysisCache shell_analysis_cache;
// 真实几何分析方法
bool AnalyzeFeatureGeometry(pfcFeature_ptr feature, pfcOutline3D_ptr globalOutline, double tolerance);
// Multi-directional extreme value projection algorithm structures and functions
struct Vector3D {
double x, y, z;
Vector3D() : x(0), y(0), z(0) {}
Vector3D(double x_, double y_, double z_) : x(x_), y(y_), z(z_) {}
Vector3D operator-(const Vector3D& other) const {
return Vector3D(x - other.x, y - other.y, z - other.z);
}
Vector3D operator+(const Vector3D& other) const {
return Vector3D(x + other.x, y + other.y, z + other.z);
}
Vector3D operator*(double scalar) const {
return Vector3D(x * scalar, y * scalar, z * scalar);
}
double dot(const Vector3D& other) const {
return x * other.x + y * other.y + z * other.z;
}
Vector3D cross(const Vector3D& other) const {
return Vector3D(
y * other.z - z * other.y,
z * other.x - x * other.z,
x * other.y - y * other.x
);
}
double length() const {
return sqrt(x * x + y * y + z * z);
}
Vector3D normalize() const {
double len = length();
if (len > 1e-10) {
return Vector3D(x / len, y / len, z / len);
}
return Vector3D(0, 0, 1);
}
};
struct AABB {
Vector3D minPoint, maxPoint;
AABB() : minPoint(1e9, 1e9, 1e9), maxPoint(-1e9, -1e9, -1e9) {}
AABB(const Vector3D& min_pt, const Vector3D& max_pt)
: minPoint(min_pt), maxPoint(max_pt) {}
void expand(const Vector3D& point) {
if (point.x < minPoint.x) minPoint.x = point.x;
if (point.y < minPoint.y) minPoint.y = point.y;
if (point.z < minPoint.z) minPoint.z = point.z;
if (point.x > maxPoint.x) maxPoint.x = point.x;
if (point.y > maxPoint.y) maxPoint.y = point.y;
if (point.z > maxPoint.z) maxPoint.z = point.z;
}
Vector3D diagonal() const {
return maxPoint - minPoint;
}
double getDiagonalLength() const {
return diagonal().length();
}
// Get all 8 corners of AABB
std::vector<Vector3D> getCorners() const {
std::vector<Vector3D> corners;
corners.reserve(8);
for (int i = 0; i < 8; i++) {
corners.push_back(Vector3D(
(i & 1) ? maxPoint.x : minPoint.x,
(i & 2) ? maxPoint.y : minPoint.y,
(i & 4) ? maxPoint.z : minPoint.z
));
}
return corners;
}
};
// Forward declarations
struct OBB;
// 2D Screen Grid for visibility calculation
struct ScreenGrid {
struct Cell {
double depth = std::numeric_limits<double>::max();
int componentId = -1;
};
Vector3D origin; // Grid origin point
Vector3D uAxis, vAxis; // Orthonormal basis vectors
double width, height; // Grid dimensions
int gridSizeU, gridSizeV;
std::vector<std::vector<Cell>> cells;
ScreenGrid() : gridSizeU(0), gridSizeV(0), width(0), height(0) {}
ScreenGrid(const AABB& sceneBounds, const Vector3D& viewDir, int gridSize = 96) {
gridSizeU = gridSize;
gridSizeV = gridSize;
// Build orthonormal basis
if (std::abs(viewDir.x) > 0.9) {
uAxis = Vector3D(0, 1, 0).cross(viewDir).normalize();
} else {
uAxis = Vector3D(1, 0, 0).cross(viewDir).normalize();
}
vAxis = viewDir.cross(uAxis).normalize();
// Calculate grid bounds
std::vector<Vector3D> corners = sceneBounds.getCorners();
double minU = std::numeric_limits<double>::max();
double maxU = std::numeric_limits<double>::lowest();
double minV = std::numeric_limits<double>::max();
double maxV = std::numeric_limits<double>::lowest();
for (const auto& corner : corners) {
double u = corner.dot(uAxis);
double v = corner.dot(vAxis);
minU = std::min(minU, u);
maxU = std::max(maxU, u);
minV = std::min(minV, v);
maxV = std::max(maxV, v);
}
// Set origin and dimensions
origin = Vector3D(minU, minV, 0);
width = maxU - minU;
height = maxV - minV;
// Initialize cells
cells.resize(gridSizeU, std::vector<Cell>(gridSizeV));
}
void updateCell(int u, int v, double depth, int id) {
if (u >= 0 && u < gridSizeU && v >= 0 && v < gridSizeV) {
if (depth < cells[u][v].depth) {
cells[u][v].depth = depth;
cells[u][v].componentId = id;
}
}
}
std::pair<int, int> worldToGrid(const Vector3D& point) const {
double u = point.dot(uAxis) - origin.x;
double v = point.dot(vAxis) - origin.y;
int gridU = static_cast<int>((u / width) * gridSizeU);
int gridV = static_cast<int>((v / height) * gridSizeV);
return {gridU, gridV};
}
void projectAABB(const AABB& box, const Vector3D& viewDir, double minDepth, int componentId) {
std::vector<Vector3D> corners = box.getCorners();
// Find UV bounds of projection
int minGridU = gridSizeU, maxGridU = -1;
int minGridV = gridSizeV, maxGridV = -1;
for (const auto& corner : corners) {
std::pair<int, int> gridPos = worldToGrid(corner);
int u = gridPos.first;
int v = gridPos.second;
minGridU = std::min(minGridU, std::max(0, u));
maxGridU = std::max(maxGridU, std::min(gridSizeU - 1, u));
minGridV = std::min(minGridV, std::max(0, v));
maxGridV = std::max(maxGridV, std::min(gridSizeV - 1, v));
}
// Update cells in bounding rectangle
for (int u = minGridU; u <= maxGridU; u++) {
for (int v = minGridV; v <= maxGridV; v++) {
updateCell(u, v, minDepth, componentId);
}
}
}
void projectOBB(const OBB& box, const Vector3D& viewDir, double minDepth, int componentId) {
std::vector<Vector3D> corners = box.getCorners();
// Find UV bounds of projection
int minGridU = gridSizeU, maxGridU = -1;
int minGridV = gridSizeV, maxGridV = -1;
for (const auto& corner : corners) {
std::pair<int, int> gridPos = worldToGrid(corner);
int u = gridPos.first;
int v = gridPos.second;
minGridU = std::min(minGridU, std::max(0, u));
maxGridU = std::max(maxGridU, std::min(gridSizeU - 1, u));
minGridV = std::min(minGridV, std::max(0, v));
maxGridV = std::max(maxGridV, std::min(gridSizeV - 1, v));
}
// Update cells in bounding rectangle
for (int u = minGridU; u <= maxGridU; u++) {
for (int v = minGridV; v <= maxGridV; v++) {
updateCell(u, v, minDepth, componentId);
}
}
}
std::unordered_map<int, int> getVisibilityCount() const {
std::unordered_map<int, int> counts;
for (const auto& row : cells) {
for (const auto& cell : row) {
if (cell.componentId >= 0) {
counts[cell.componentId]++;
}
}
}
return counts;
}
};
// Oriented Bounding Box for enhanced precision
struct OBB {
Vector3D center; // Center point in world space
Vector3D halfExtents; // Half extents in local space
Vector3D axes[3]; // Three orthogonal axes in world space
OBB() : center(0, 0, 0), halfExtents(0, 0, 0) {
axes[0] = Vector3D(1, 0, 0);
axes[1] = Vector3D(0, 1, 0);
axes[2] = Vector3D(0, 0, 1);
}
// Calculate support point projection for OBB in given direction
double getSupport(const Vector3D& direction) const {
// Transform world direction to OBB local space
Vector3D localDir(
direction.dot(axes[0]),
direction.dot(axes[1]),
direction.dot(axes[2])
);
// Calculate local space support point
Vector3D support;
support.x = (localDir.x >= 0) ? halfExtents.x : -halfExtents.x;
support.y = (localDir.y >= 0) ? halfExtents.y : -halfExtents.y;
support.z = (localDir.z >= 0) ? halfExtents.z : -halfExtents.z;
// Transform back to world space and calculate projection
Vector3D worldSupport = center +
axes[0] * support.x +
axes[1] * support.y +
axes[2] * support.z;
return worldSupport.dot(direction);
}
// Get all 8 corners of the OBB
std::vector<Vector3D> getCorners() const {
std::vector<Vector3D> corners;
corners.reserve(8);
for (int i = 0; i < 8; i++) {
Vector3D corner = center;
corner = corner + axes[0] * ((i & 1) ? halfExtents.x : -halfExtents.x);
corner = corner + axes[1] * ((i & 2) ? halfExtents.y : -halfExtents.y);
corner = corner + axes[2] * ((i & 4) ? halfExtents.z : -halfExtents.z);
corners.push_back(corner);
}
return corners;
}
};
struct ComponentItem {
pfcComponentFeat_ptr component;
pfcSolid_ptr solid;
pfcComponentPath_ptr path;
AABB worldAABB; // Fast rough filtering
OBB worldOBB; // Precise oriented bounding box
int featureId;
std::string name;
};
// Projection analysis result data structure
struct ProjectionAnalysisData {
std::unordered_map<int, int> visibilityVotes; // component ID -> visibility count
std::unordered_set<int> outerComponentIds; // outer component IDs
std::vector<ComponentItem> components; // all components with AABB data
AABB globalAABB; // global assembly bounding box
std::unordered_map<int, double> visibilityRatios; // component ID -> continuous visibility ratio
// OBB optimization statistics
int obb_usage_count = 0;
int aabb_usage_count = 0;
double obb_usage_percentage = 0.0;
};
// Component classification based on naming patterns and geometry
class ComponentClassifier {
public:
// Structure for specific internal models
struct SpecificInternalModel {
std::string name; // Model name (e.g., "12v4000g03_herhang.prt")
std::string pathSegment; // Path segment for validation (optional)
};
// Check if component name indicates a fastener
static bool IsFastener(const std::string& name);
// Check if component name indicates internal structure
static bool IsInternalStructure(const std::string& name);
// Check if component name indicates external shell
static bool IsExternalShell(const std::string& name);
// Check if component is likely internal based on geometry
static bool IsLikelyInternal(const AABB& compAABB, const AABB& globalAABB);
// Check if component is elongated/thin (benefits from OBB)
static bool IsElongatedPart(const std::string& name);
// Check if component is a specific internal model
static bool IsSpecificInternalModel(const std::string& name, const std::string& path);
// List of specific models to be marked as internal
static std::vector<SpecificInternalModel> specificInternalModels;
private:
static bool MatchesPattern(const std::string& text, const std::vector<std::string>& patterns);
};
// Multi-directional projection algorithm functions
std::pair<double, double> CalculateAABBProjectionRange(const AABB& aabb, const Vector3D& direction);
std::pair<double, double> CalculateOBBProjectionRange(const OBB& obb, const Vector3D& direction);
ProjectionAnalysisData PerformMultiDirectionalProjectionAnalysis(pfcAssembly_ptr assembly);
std::vector<ComponentItem> CollectAllComponents(pfcAssembly_ptr assembly);
std::vector<Vector3D> SampleDirections(int count = 96);
AABB TransformAABB(const AABB& localAABB, pfcTransform3D_ptr transform);
pfcTransform3D_ptr GetComponentWorldTransform(pfcComponentPath_ptr path);
double CalculateProjectionSupport(const AABB& aabb, const Vector3D& direction);
Vector3D PfcPointToVector3D(pfcPoint3D_ptr point);
AABB PfcOutlineToAABB(pfcOutline3D_ptr outline);
// OBB-related functions for enhanced precision
OBB ExtractOBBFromTransform(const AABB& localAABB, pfcTransform3D_ptr transform);
OBB ComputePCABasedOBB(pfcSolid_ptr solid, pfcTransform3D_ptr transform);
std::vector<Vector3D> ExtractSolidVertices(pfcSolid_ptr solid, int maxVertices = 1000);
OBB ComputeOBBFromVertices(const std::vector<Vector3D>& vertices);
std::vector<Vector3D> ComputePrincipalAxes(const std::vector<Vector3D>& vertices);
double CalculateOBBProjectionSupport(const OBB& obb, const Vector3D& direction);
double CalculateOBBThickness(const OBB& obb, const Vector3D& direction);
bool ShouldUseOBB(const ComponentItem& comp);
// Ray-based verification for shell analysis
bool IsComponentBlockedFromCenter(const Vector3D& globalCenter,
const ComponentItem& component,
const std::vector<ComponentItem>& allComponents);
};