Replace depth window and Top-K mechanism with direct occlusion detection algorithm. Changes: - Remove depth window calculations and Top-K fallback - Implement AABB/OBB projection range calculation - Add getCorners() method to OBB structure - Extract magic numbers to constants - Fix compilation errors with std::pair declarations The algorithm now uses pure geometric occlusion detection: 1. Calculate projection ranges for all components 2. Sort by maximum projection (farthest first) 3. Mark visible components based on occlusion boundary 4. No fallback mechanisms or safety nets This follows the coding standards: - Core requirement first (occlusion detection) - No defensive programming - Fast fail principle - Minimal complexity 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
720 lines
26 KiB
C++
720 lines
26 KiB
C++
#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>
|
||
|
||
// 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);
|
||
|
||
// 薄壳化分析功能
|
||
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;
|
||
};
|
||
|
||
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();
|
||
|
||
// 字符串转换辅助函数
|
||
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();
|
||
}
|
||
};
|
||
|
||
// 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
|
||
|
||
// 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:
|
||
// 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);
|
||
|
||
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);
|
||
};
|