diff --git a/CreoManager.cpp b/CreoManager.cpp index 988a76c..0a7a0a1 100644 --- a/CreoManager.cpp +++ b/CreoManager.cpp @@ -29,6 +29,13 @@ #include #include +// Initialize specific internal models list +std::vector +CreoManager::ComponentClassifier::specificInternalModels = { + {"12v4000g03_herhang.prt", "ENGINE__ALTERNATOR_ASSEMBLY_HER.asm/ENGINE_ALTERNATOR_1250KVA_HERHA.asm"} + // Future models can be added here +}; + // Shell Analysis Algorithm Constants const int SHELL_ANALYSIS_NUM_DIRECTIONS = 6; // 6-direction orthogonal projection sampling const int SHELL_ANALYSIS_GRID_RESOLUTION = 96; // 网格分辨率96x96 @@ -1706,8 +1713,18 @@ CreoManager::ShellAnalysisResult CreoManager::AnalyzeShellFeaturesEnhanced(const visibilityRatio = (double)votesIter->second / numDirections; } - // Determine confidence based on visibility ratio - if (visibilityRatio >= SHELL_ANALYSIS_HIGH_VISIBILITY_THRESHOLD) { + // Check if this is a specific internal model that should be marked as internal + bool isSpecificInternal = ComponentClassifier::IsSpecificInternalModel(comp_name, item.path); + + // Determine confidence based on visibility ratio (or override for specific internal models) + if (isSpecificInternal) { + // Force mark as internal model regardless of visibility + item.confidence = 0.90; // High deletion confidence + item.recommendation = "DELETE"; + item.reason = "Marked as Internal Model (visibility: " + + std::to_string((int)(visibilityRatio * 100)) + "%)"; + result.internal_features_count++; + } else if (visibilityRatio >= SHELL_ANALYSIS_HIGH_VISIBILITY_THRESHOLD) { // Highly visible component - clearly on outer surface item.confidence = 0.1; // Very low deletion confidence item.recommendation = "KEEP"; @@ -1743,20 +1760,23 @@ CreoManager::ShellAnalysisResult CreoManager::AnalyzeShellFeaturesEnhanced(const unifiedName = nameIter->second; // Use name from ComponentItem for consistency } - if (ComponentClassifier::IsFastener(unifiedName)) { - item.confidence = std::min(0.95, item.confidence + 0.3); // Fasteners are typically deletable - item.reason += " [Pattern: Fastener]"; - if (item.recommendation == "KEEP") { - item.recommendation = "REVIEW"; // Reconsider visible fasteners - } - } else if (ComponentClassifier::IsInternalStructure(unifiedName)) { - item.confidence = std::min(0.90, item.confidence + 0.25); // Internal structures likely deletable - item.reason += " [Pattern: Internal structure]"; - } else if (ComponentClassifier::IsExternalShell(unifiedName)) { - item.confidence = std::max(0.1, item.confidence - 0.5); // External shells should be preserved - item.reason += " [Pattern: External shell]"; - if (item.recommendation == "DELETE") { - item.recommendation = "REVIEW"; // Reconsider deletion of shells + // Skip pattern-based adjustments for specific internal models + if (!isSpecificInternal) { + if (ComponentClassifier::IsFastener(unifiedName)) { + item.confidence = std::min(0.95, item.confidence + 0.3); // Fasteners are typically deletable + item.reason += " [Pattern: Fastener]"; + if (item.recommendation == "KEEP") { + item.recommendation = "REVIEW"; // Reconsider visible fasteners + } + } else if (ComponentClassifier::IsInternalStructure(unifiedName)) { + item.confidence = std::min(0.90, item.confidence + 0.25); // Internal structures likely deletable + item.reason += " [Pattern: Internal structure]"; + } else if (ComponentClassifier::IsExternalShell(unifiedName)) { + item.confidence = std::max(0.1, item.confidence - 0.5); // External shells should be preserved + item.reason += " [Pattern: External shell]"; + if (item.recommendation == "DELETE") { + item.recommendation = "REVIEW"; // Reconsider deletion of shells + } } } @@ -3145,6 +3165,40 @@ bool CreoManager::ComponentClassifier::IsExternalShell(const std::string& name) return MatchesPattern(name, patterns); } +bool CreoManager::ComponentClassifier::IsSpecificInternalModel(const std::string& name, const std::string& path) { + // Convert name to lowercase for case-insensitive comparison + std::string lowerName = name; + std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), ::tolower); + + // Convert path to lowercase for case-insensitive comparison + std::string lowerPath = path; + std::transform(lowerPath.begin(), lowerPath.end(), lowerPath.begin(), ::tolower); + + // Check each specific internal model + for (const auto& model : specificInternalModels) { + std::string modelNameLower = model.name; + std::transform(modelNameLower.begin(), modelNameLower.end(), modelNameLower.begin(), ::tolower); + + // Check if name matches + if (lowerName.find(modelNameLower) != std::string::npos) { + // If no path segment specified, match by name only + if (model.pathSegment.empty()) { + return true; + } + + // Check if path contains the required segment + std::string pathSegmentLower = model.pathSegment; + std::transform(pathSegmentLower.begin(), pathSegmentLower.end(), pathSegmentLower.begin(), ::tolower); + + if (lowerPath.find(pathSegmentLower) != std::string::npos) { + return true; + } + } + } + + return false; +} + bool CreoManager::ComponentClassifier::IsLikelyInternal(const AABB& compAABB, const AABB& globalAABB) { // Rule 1: Extremely small components (volume < 0.1% of total) Vector3D compSize = compAABB.diagonal(); @@ -3549,6 +3603,33 @@ bool CreoManager::IsComponentBlockedFromCenter(const Vector3D& globalCenter, // Debug for ID 7 (12V4000G03) bool isTarget12v = (component.featureId == 7); + // Debug: Log ray information for target component + if (isTarget12v) { + static int debugCallCount = 0; + debugCallCount++; + if (debugCallCount <= 6) { + try { + SessionInfo sessionInfo = GetSessionInfo(); + if (sessionInfo.is_valid) { + xstring workdir = sessionInfo.session->GetCurrentDirectory(); + std::string workingDir = XStringToString(workdir); + std::string debugPath = workingDir + "\\ray_debug.txt"; + std::ofstream debugFile; + debugFile.open(debugPath, debugCallCount == 1 ? std::ios::out : std::ios::app); + if (debugFile.is_open()) { + debugFile << "=== Direction " << debugCallCount << " ===" << std::endl; + debugFile << "Global Center: (" << globalCenter.x << ", " << globalCenter.y << ", " << globalCenter.z << ")" << std::endl; + debugFile << "Component Center: (" << componentCenter.x << ", " << componentCenter.y << ", " << componentCenter.z << ")" << std::endl; + debugFile << "Ray Direction: (" << rayDirection.x << ", " << rayDirection.y << ", " << rayDirection.z << ")" << std::endl; + debugFile << "Distance to Component: " << distToComponentCenter << std::endl; + debugFile << std::endl; + debugFile.close(); + } + } + } catch (...) {} + } + } + int checkedCount = 0; int intersectionCount = 0; int beyondCount = 0; // Count intersections beyond component center @@ -3565,7 +3646,7 @@ bool CreoManager::IsComponentBlockedFromCenter(const Vector3D& globalCenter, // AABB ray intersection test // We check if ray intersects other component's AABB beyond the component center - double tMin = 0.0; + double tMin = -std::numeric_limits::max(); double tMax = std::numeric_limits::max(); for (int i = 0; i < 3; i++) { @@ -3581,9 +3662,10 @@ bool CreoManager::IsComponentBlockedFromCenter(const Vector3D& globalCenter, if (std::abs(dir) < 1e-10) { // Ray is parallel to slab if (origin < minVal || origin > maxVal) { - // Ray is outside slab - tMin = tMax + 1; // Force no intersection - break; + // Ray is outside slab - no intersection possible + tMin = std::numeric_limits::max(); + tMax = -std::numeric_limits::max(); + // Don't break, let the loop complete all axes } } else { // Compute intersection t values @@ -3596,14 +3678,32 @@ bool CreoManager::IsComponentBlockedFromCenter(const Vector3D& globalCenter, tMin = std::max(tMin, t1); tMax = std::min(tMax, t2); - - if (tMin > tMax) { - // No intersection - break; - } } } + // Debug: Log detailed intersection test for first few components + if (isTarget12v && checkedCount <= 5) { + try { + SessionInfo sessionInfo = GetSessionInfo(); + if (sessionInfo.is_valid) { + xstring workdir = sessionInfo.session->GetCurrentDirectory(); + std::string workingDir = XStringToString(workdir); + std::string debugPath = workingDir + "\\ray_debug.txt"; + std::ofstream debugFile(debugPath, std::ios::app); + if (debugFile.is_open()) { + debugFile << "Component " << otherComp.featureId << " (" << otherComp.name << "):" << std::endl; + debugFile << " AABB: min=(" << otherComp.worldAABB.minPoint.x << ", " + << otherComp.worldAABB.minPoint.y << ", " << otherComp.worldAABB.minPoint.z + << ") max=(" << otherComp.worldAABB.maxPoint.x << ", " + << otherComp.worldAABB.maxPoint.y << ", " << otherComp.worldAABB.maxPoint.z << ")" << std::endl; + debugFile << " Final tMin=" << tMin << ", tMax=" << tMax << std::endl; + debugFile << " Intersection test: " << (tMin <= tMax ? "PASS" : "FAIL") << std::endl; + debugFile.close(); + } + } + } catch (...) {} + } + // Check if intersection exists if (tMin <= tMax) { // Calculate the actual distance of the intersection point diff --git a/CreoManager.h b/CreoManager.h index 162430f..6458858 100644 --- a/CreoManager.h +++ b/CreoManager.h @@ -835,6 +835,12 @@ private: // 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); @@ -850,6 +856,12 @@ private: // 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 specificInternalModels; + private: static bool MatchesPattern(const std::string& text, const std::vector& patterns); };