| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582 |
- 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<ColorMappingParams> {
- 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<SpaceMappingParams> {
- 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<MaterialMappingParams> {
- 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
- };
- }
- }
|