import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; import { ColorMappingParams, SpaceMappingParams, MaterialMappingParams, ColorMapping, SpaceZone, MaterialMapping } from '../models/requirement-mapping.interface'; @Injectable({ providedIn: 'root' }) export class ParameterMappingService { constructor() {} /** * 映射颜色参数 * @param analysisResult 分析结果 */ mapColorParameters(analysisResult: any): Observable { try { const colorParams: ColorMappingParams = { primaryColors: this.generateColorMappings(analysisResult), colorHarmony: this.determineColorHarmony(analysisResult), saturation: this.calculateSaturationLevel(analysisResult), brightness: this.calculateBrightnessLevel(analysisResult), contrast: 50, temperature: 'neutral' }; return of(colorParams); } catch (error) { return of(this.getDefaultColorParams()); } } /** * 映射空间参数 * @param analysisResult 分析结果 */ mapSpaceParameters(analysisResult: any): Observable { try { const spaceParams: SpaceMappingParams = { dimensions: { width: 400, height: 280, depth: 400, unit: 'meter' }, layout: { type: this.determineLayout(analysisResult) as any, flow: 'linear', zones: this.identifySpaceZones(analysisResult) }, scale: { furniture: 70, ceiling: 80, openness: 60 } }; return of(spaceParams); } catch (error) { return of(this.getDefaultSpaceParams()); } } /** * 映射材质参数 * @param analysisResult 分析结果 */ mapMaterialParameters(analysisResult: any): Observable { try { const materialParams: MaterialMappingParams = { surfaceMaterials: this.generateMaterialMappings(analysisResult), textureScale: 50, reflectivity: 30, roughness: 50, metallic: 10 }; return of(materialParams); } catch (error) { return of(this.getDefaultMaterialParams()); } } /** * 综合映射所有参数 * @param analysisResult 分析结果 */ mapAllParameters(analysisResult: any): Observable<{ colorParams: ColorMappingParams; spaceParams: SpaceMappingParams; materialParams: MaterialMappingParams; }> { try { const colorParams = this.mapColorParameters(analysisResult); const spaceParams = this.mapSpaceParameters(analysisResult); const materialParams = this.mapMaterialParameters(analysisResult); return new Observable(observer => { Promise.all([ colorParams.toPromise(), spaceParams.toPromise(), materialParams.toPromise() ]).then(([color, space, material]) => { observer.next({ colorParams: color!, spaceParams: space!, materialParams: material! }); observer.complete(); }).catch(error => { observer.error(error); }); }); } catch (error) { return of({ colorParams: this.getDefaultColorParams(), spaceParams: this.getDefaultSpaceParams(), materialParams: this.getDefaultMaterialParams() }); } } // ==================== 颜色参数映射方法 ==================== /** * 提取主要颜色 */ private extractPrimaryColors(analysisResult: any): string[] { if (analysisResult.enhancedColorAnalysis?.colorWheel?.dominantColors) { return analysisResult.enhancedColorAnalysis.colorWheel.dominantColors .slice(0, 5) .map((color: any) => color.hex || color.name || '#FFFFFF'); } if (analysisResult.enhancedColorAnalysis?.colorPalette?.primaryColors) { return analysisResult.enhancedColorAnalysis.colorPalette.primaryColors .slice(0, 5) .map((color: any) => color.hex || color.value || '#FFFFFF'); } return ['#FFFFFF', '#F5F5F5', '#E0E0E0']; // 默认中性色 } /** * 确定色彩和谐度 */ private determineColorHarmony(analysisResult: any): 'monochromatic' | 'analogous' | 'complementary' | 'triadic' | 'split-complementary' { if (analysisResult.enhancedColorAnalysis?.colorHarmony?.harmonyType) { return analysisResult.enhancedColorAnalysis.colorHarmony.harmonyType; } // 基于色彩分布分析和谐度 const colors = this.extractPrimaryColors(analysisResult); if (colors.length <= 2) { return 'monochromatic'; } else if (colors.length === 3) { return 'triadic'; } else { return 'analogous'; } } /** * 计算饱和度级别 */ private calculateSaturationLevel(analysisResult: any): number { if (analysisResult.enhancedColorAnalysis?.colorWheel?.saturation) { return analysisResult.enhancedColorAnalysis.colorWheel.saturation; } if (analysisResult.enhancedColorAnalysis?.colorPalette?.averageSaturation) { return analysisResult.enhancedColorAnalysis.colorPalette.averageSaturation; } return 50; // 默认中等饱和度 } /** * 计算亮度级别 */ private calculateBrightnessLevel(analysisResult: any): number { if (analysisResult.lightingAnalysis?.illuminationAnalysis?.brightness?.overall) { return analysisResult.lightingAnalysis.illuminationAnalysis.brightness.overall; } if (analysisResult.enhancedColorAnalysis?.colorWheel?.brightness) { return analysisResult.enhancedColorAnalysis.colorWheel.brightness; } return 60; // 默认中等亮度 } /** * 生成颜色映射 */ private generateColorMappings(analysisResult: any): ColorMapping[] { const primaryColors = this.extractPrimaryColors(analysisResult); const mappings: ColorMapping[] = []; primaryColors.forEach((originalColor, index) => { mappings.push({ originalColor: originalColor, mappedColor: this.optimizeColorForSpace(originalColor, analysisResult), usage: this.determineColorUsage(index), weight: this.calculateColorCoverage(index, primaryColors.length) }); }); return mappings; } /** * 优化空间色彩 */ private optimizeColorForSpace(color: string, analysisResult: any): string { // 根据空间类型和光照条件优化颜色 // 这里实现简化的色彩优化逻辑 return color; // 暂时返回原色彩 } /** * 确定颜色用途 */ private determineColorUsage(index: number): 'primary' | 'secondary' | 'accent' | 'background' { switch (index) { case 0: return 'primary'; case 1: return 'secondary'; case 2: return 'accent'; default: return 'background'; } } /** * 计算颜色覆盖率 */ private calculateColorCoverage(index: number, totalColors: number): number { const baseCoverage = [40, 30, 20, 10]; // 主色、次色、强调色、中性色的基础覆盖率 return baseCoverage[index] || (100 - 90) / (totalColors - 3); } // ==================== 空间参数映射方法 ==================== /** * 确定房间类型 */ private determineRoomType(analysisResult: any): string { // 基于分析结果推断房间类型 if (analysisResult.formAnalysis?.objectRecognition) { const objects = analysisResult.formAnalysis.objectRecognition.identifiedObjects || []; // 检查特征物品来判断房间类型 if (objects.some((obj: any) => ['bed', 'pillow', 'nightstand'].includes(obj.category))) { return 'bedroom'; } if (objects.some((obj: any) => ['sofa', 'coffee table', 'tv'].includes(obj.category))) { return 'living_room'; } if (objects.some((obj: any) => ['stove', 'refrigerator', 'sink'].includes(obj.category))) { return 'kitchen'; } if (objects.some((obj: any) => ['toilet', 'shower', 'bathtub'].includes(obj.category))) { return 'bathroom'; } } return 'general'; // 默认通用空间 } /** * 估算空间尺寸 */ private estimateDimensions(analysisResult: any): { width: number; height: number; depth: number } { // 基于透视分析和物体比例估算尺寸 if (analysisResult.formAnalysis?.perspectiveAnalysis) { const perspective = analysisResult.formAnalysis.perspectiveAnalysis; return { width: perspective.estimatedWidth || 400, height: perspective.estimatedHeight || 280, depth: perspective.estimatedDepth || 400 }; } // 默认中等尺寸房间 (单位: cm) return { width: 400, height: 280, depth: 400 }; } /** * 确定布局类型 */ private determineLayout(analysisResult: any): 'open' | 'closed' | 'semi-open' | 'linear' | 'L-shaped' | 'U-shaped' { if (analysisResult.formAnalysis?.spaceAnalysis?.layoutType) { return analysisResult.formAnalysis.spaceAnalysis.layoutType; } // 基于物体分布分析布局 const roomType = this.determineRoomType(analysisResult); switch (roomType) { case 'living_room': return 'open'; case 'kitchen': return 'L-shaped'; case 'bedroom': return 'closed'; case 'bathroom': return 'linear'; default: return 'open'; } } /** * 识别空间区域 */ private identifySpaceZones(analysisResult: any): SpaceZone[] { const zones: SpaceZone[] = []; const roomType = this.determineRoomType(analysisResult); // 根据房间类型定义功能区域 switch (roomType) { case 'living_room': zones.push( { name: '会客区', function: 'seating', area: 40, position: 'center' }, { name: '娱乐区', function: 'entertainment', area: 25, position: 'corner' }, { name: '通道区', function: 'circulation', area: 35, position: 'entrance' } ); break; case 'bedroom': zones.push( { name: '睡眠区', function: 'sleeping', area: 50, position: 'center' }, { name: '储物区', function: 'storage', area: 30, position: 'wall' }, { name: '梳妆区', function: 'dressing', area: 20, position: 'window' } ); break; case 'kitchen': zones.push( { name: '烹饪区', function: 'cooking', area: 40, position: 'wall' }, { name: '清洗区', function: 'cleaning', area: 25, position: 'wall' }, { name: '储存区', function: 'storage', area: 35, position: 'corner' } ); break; default: zones.push( { name: '主要区域', function: 'primary', area: 70, position: 'center' }, { name: '辅助区域', function: 'secondary', area: 30, position: 'corner' } ); } return zones; } /** * 分析流线模式 */ private analyzeFlowPattern(analysisResult: any): 'linear' | 'circular' | 'radial' | 'grid' | 'organic' { const layout = this.determineLayout(analysisResult); // 根据布局类型推断流线模式 switch (layout) { case 'linear': return 'linear'; case 'L-shaped': case 'U-shaped': return 'circular'; case 'open': return 'radial'; default: return 'organic'; } } // ==================== 材质参数映射方法 ==================== /** * 提取主要材质 */ private extractPrimaryMaterials(analysisResult: any): string[] { if (analysisResult.textureAnalysis?.materialClassification) { const materials = []; const classification = analysisResult.textureAnalysis.materialClassification; if (classification.primaryMaterial) { materials.push(classification.primaryMaterial.category); } if (classification.secondaryMaterials) { materials.push(...classification.secondaryMaterials.map((m: any) => m.category)); } return materials.slice(0, 5); } return ['wood', 'fabric', 'metal']; // 默认材质组合 } /** * 计算纹理复杂度 */ private calculateTextureComplexity(analysisResult: any): 'low' | 'medium' | 'high' { if (analysisResult.patternAnalysis?.patternRecognition) { const patternCount = analysisResult.patternAnalysis.patternRecognition.primaryPatterns?.length || 0; if (patternCount > 3) return 'high'; if (patternCount > 1) return 'medium'; return 'low'; } if (analysisResult.textureAnalysis?.surfaceProperties?.roughness) { const roughness = analysisResult.textureAnalysis.surfaceProperties.roughness.level; if (roughness === 'high') return 'high'; if (roughness === 'medium') return 'medium'; return 'low'; } return 'medium'; } /** * 确定表面处理 */ private determineSurfaceFinish(analysisResult: any): 'matte' | 'satin' | 'semi-gloss' | 'gloss' | 'textured' { if (analysisResult.textureAnalysis?.surfaceProperties?.reflectivity) { const reflectivity = analysisResult.textureAnalysis.surfaceProperties.reflectivity.level; switch (reflectivity) { case 'high': return 'gloss'; case 'medium': return 'semi-gloss'; case 'low': return 'matte'; default: return 'satin'; } } return 'satin'; // 默认缎面处理 } /** * 生成材质映射 */ private generateMaterialMappings(analysisResult: any): MaterialMapping[] { const primaryMaterials = this.extractPrimaryMaterials(analysisResult); const mappings: MaterialMapping[] = []; primaryMaterials.forEach((originalMaterial, index) => { mappings.push({ category: originalMaterial as any, subtype: originalMaterial, finish: 'satin', color: '#8B4513', coverage: this.calculateMaterialCoverage(index, primaryMaterials.length), priority: this.determineMaterialUsage(index) as any }); }); return mappings; } /** * 优化空间材质 */ private optimizeMaterialForSpace(material: string, analysisResult: any): string { // 根据空间类型和使用需求优化材质选择 const roomType = this.determineRoomType(analysisResult); // 材质优化映射表 const optimizationMap: {[key: string]: {[key: string]: string}} = { 'bathroom': { 'wood': 'ceramic', 'fabric': 'vinyl', 'paper': 'ceramic' }, 'kitchen': { 'fabric': 'quartz', 'paper': 'ceramic', 'wood': 'laminate' } }; return optimizationMap[roomType]?.[material] || material; } /** * 获取材质属性 */ private getMaterialProperties(material: string): { durability: number; maintenance: 'low' | 'medium' | 'high'; cost: 'low' | 'medium' | 'high'; sustainability: number; } { const propertiesMap: {[key: string]: any} = { 'wood': { durability: 75, maintenance: 'medium', cost: 'medium', sustainability: 85 }, 'metal': { durability: 90, maintenance: 'low', cost: 'high', sustainability: 70 }, 'fabric': { durability: 60, maintenance: 'high', cost: 'low', sustainability: 60 }, 'ceramic': { durability: 85, maintenance: 'low', cost: 'medium', sustainability: 80 }, 'glass': { durability: 70, maintenance: 'medium', cost: 'medium', sustainability: 90 }, 'stone': { durability: 95, maintenance: 'low', cost: 'high', sustainability: 95 } }; return propertiesMap[material] || { durability: 70, maintenance: 'medium', cost: 'medium', sustainability: 70 }; } /** * 确定材质用途 */ private determineMaterialUsage(index: number): 'primary' | 'secondary' | 'accent' | 'functional' { switch (index) { case 0: return 'primary'; case 1: return 'secondary'; case 2: return 'accent'; default: return 'functional'; } } /** * 计算材质覆盖率 */ private calculateMaterialCoverage(index: number, totalMaterials: number): number { const baseCoverage = [50, 30, 15, 5]; // 主材质、次材质、强调材质、功能材质的基础覆盖率 return baseCoverage[index] || (100 - 95) / (totalMaterials - 3); } /** * 评估耐久性要求 */ private assessDurabilityRequirements(analysisResult: any): 'low' | 'medium' | 'high' { const roomType = this.determineRoomType(analysisResult); // 根据空间类型确定耐久性要求 switch (roomType) { case 'kitchen': case 'bathroom': return 'high'; case 'living_room': return 'medium'; case 'bedroom': return 'low'; default: return 'medium'; } } // ==================== 默认参数方法 ==================== private getDefaultColorParams(): ColorMappingParams { return { primaryColors: [ { originalColor: '#FFFFFF', mappedColor: '#FFFFFF', weight: 40, usage: 'primary' }, { originalColor: '#F5F5F5', mappedColor: '#F5F5F5', weight: 30, usage: 'secondary' }, { originalColor: '#E0E0E0', mappedColor: '#E0E0E0', weight: 30, usage: 'background' } ], colorHarmony: 'monochromatic', saturation: 50, brightness: 70, contrast: 50, temperature: 'neutral' }; } private getDefaultSpaceParams(): SpaceMappingParams { return { dimensions: { width: 400, height: 280, depth: 400, unit: 'meter' }, layout: { type: 'open', flow: 'linear', zones: [ { name: '主要区域', position: 'center', area: 70, function: '主要活动区域' }, { name: '辅助区域', position: 'corner', area: 30, function: '辅助功能区域' } ] }, scale: { furniture: 1.0, ceiling: 2.8, openness: 0.7 } }; } private getDefaultMaterialParams(): MaterialMappingParams { return { surfaceMaterials: [], textureScale: 50, reflectivity: 30, roughness: 50, metallic: 10 }; } }