scene-generation.service.ts 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. import { Injectable } from '@angular/core';
  2. import { Observable, of } from 'rxjs';
  3. import { map, switchMap } from 'rxjs/operators';
  4. import {
  5. RequirementMapping,
  6. SceneParams,
  7. SceneTemplate,
  8. LightingParams,
  9. EnvironmentParams,
  10. CompositionParams,
  11. StyleParams,
  12. MappingResult
  13. } from '../models/requirement-mapping.interface';
  14. import { AtmospherePreviewService } from './atmosphere-preview.service';
  15. @Injectable({
  16. providedIn: 'root'
  17. })
  18. export class SceneGenerationService {
  19. // 场景模板配置
  20. private sceneTemplates: Map<SceneTemplate, SceneParams> = new Map();
  21. constructor(private atmospherePreviewService: AtmospherePreviewService) {
  22. this.initializeSceneTemplates();
  23. }
  24. /**
  25. * 根据分析结果生成场景参数和预览图
  26. */
  27. generateSceneFromAnalysis(analysisResult: any, sceneType: SceneTemplate): Observable<MappingResult> {
  28. const baseParams = this.getSceneTemplate(sceneType);
  29. const adaptedParams = this.adaptParamsFromAnalysis(baseParams, analysisResult);
  30. // 生成氛围感预览图
  31. return this.atmospherePreviewService.generateAtmospherePreview(adaptedParams, sceneType).pipe(
  32. map(previewResult => {
  33. const confidence = this.calculateConfidence(analysisResult, adaptedParams);
  34. const suggestions = this.generateSuggestions(analysisResult, adaptedParams);
  35. return {
  36. success: true,
  37. sceneId: this.generateSceneId(sceneType),
  38. generatedParams: adaptedParams,
  39. previewUrl: previewResult.url,
  40. confidence,
  41. suggestions,
  42. metadata: {
  43. generatedAt: new Date(),
  44. analysisVersion: '1.0',
  45. processingTime: previewResult.metadata.processingTime
  46. }
  47. };
  48. })
  49. );
  50. }
  51. /**
  52. * 获取场景模板
  53. */
  54. getSceneTemplate(sceneType: SceneTemplate): SceneParams {
  55. return this.sceneTemplates.get(sceneType) || this.getDefaultSceneParams();
  56. }
  57. /**
  58. * 获取所有可用的场景模板
  59. */
  60. getAvailableScenes(): Array<{template: SceneTemplate, name: string, description: string}> {
  61. return [
  62. { template: SceneTemplate.LIVING_ROOM_MODERN, name: '现代客厅', description: '简约现代风格的客厅空间' },
  63. { template: SceneTemplate.LIVING_ROOM_CLASSIC, name: '经典客厅', description: '传统经典风格的客厅空间' },
  64. { template: SceneTemplate.BEDROOM_MINIMAL, name: '简约卧室', description: '极简主义风格的卧室空间' },
  65. { template: SceneTemplate.BEDROOM_COZY, name: '温馨卧室', description: '温馨舒适的卧室空间' },
  66. { template: SceneTemplate.KITCHEN_CONTEMPORARY, name: '现代厨房', description: '当代风格的厨房空间' },
  67. { template: SceneTemplate.KITCHEN_TRADITIONAL, name: '传统厨房', description: '传统风格的厨房空间' },
  68. { template: SceneTemplate.BATHROOM_LUXURY, name: '豪华浴室', description: '奢华风格的浴室空间' },
  69. { template: SceneTemplate.BATHROOM_MINIMAL, name: '简约浴室', description: '简约风格的浴室空间' },
  70. { template: SceneTemplate.OFFICE_MODERN, name: '现代办公室', description: '现代化的办公空间' },
  71. { template: SceneTemplate.OFFICE_TRADITIONAL, name: '传统办公室', description: '传统风格的办公空间' },
  72. { template: SceneTemplate.DINING_FORMAL, name: '正式餐厅', description: '正式的用餐空间' },
  73. { template: SceneTemplate.DINING_CASUAL, name: '休闲餐厅', description: '休闲的用餐空间' },
  74. { template: SceneTemplate.STUDIO_APARTMENT, name: '工作室公寓', description: '开放式的工作室公寓' },
  75. { template: SceneTemplate.OUTDOOR_PATIO, name: '户外露台', description: '户外露台空间' },
  76. { template: SceneTemplate.OUTDOOR_GARDEN, name: '花园景观', description: '花园景观空间' }
  77. ];
  78. }
  79. /**
  80. * 根据分析结果适配场景参数
  81. */
  82. private adaptParamsFromAnalysis(baseParams: SceneParams, analysisResult: any): SceneParams {
  83. const adaptedParams = JSON.parse(JSON.stringify(baseParams)); // 深拷贝
  84. // 适配灯光参数
  85. if (analysisResult.lightingAnalysis) {
  86. adaptedParams.lighting = this.adaptLightingParams(
  87. adaptedParams.lighting,
  88. analysisResult.lightingAnalysis
  89. );
  90. }
  91. // 适配环境参数
  92. if (analysisResult.enhancedColorAnalysis || analysisResult.textureAnalysis) {
  93. adaptedParams.environment = this.adaptEnvironmentParams(
  94. adaptedParams.environment,
  95. analysisResult
  96. );
  97. }
  98. // 适配风格参数
  99. if (analysisResult.formAnalysis || analysisResult.patternAnalysis) {
  100. adaptedParams.style = this.adaptStyleParams(
  101. adaptedParams.style,
  102. analysisResult
  103. );
  104. }
  105. return adaptedParams;
  106. }
  107. /**
  108. * 适配灯光参数
  109. */
  110. private adaptLightingParams(baseParams: LightingParams, lightingAnalysis: any): LightingParams {
  111. const adapted = { ...baseParams };
  112. // 主光源适配
  113. if (lightingAnalysis.lightSourceIdentification) {
  114. const primarySource = lightingAnalysis.lightSourceIdentification.primarySources?.[0];
  115. if (primarySource) {
  116. adapted.primaryLight.type = primarySource.type || adapted.primaryLight.type;
  117. adapted.primaryLight.intensity = primarySource.intensity || adapted.primaryLight.intensity;
  118. adapted.primaryLight.direction = primarySource.position?.direction || adapted.primaryLight.direction;
  119. }
  120. // 色温适配
  121. if (lightingAnalysis.illuminationAnalysis?.colorTemperature) {
  122. adapted.primaryLight.temperature = lightingAnalysis.illuminationAnalysis.colorTemperature.kelvin || adapted.primaryLight.temperature;
  123. }
  124. }
  125. // 环境光适配
  126. if (lightingAnalysis.ambientAnalysis) {
  127. adapted.ambientLight.strength = lightingAnalysis.ambientAnalysis.ambientLevel?.strength || adapted.ambientLight.strength;
  128. adapted.ambientLight.mood = lightingAnalysis.ambientAnalysis.lightingMood?.primary || adapted.ambientLight.mood;
  129. }
  130. // 阴影适配
  131. if (lightingAnalysis.shadowAnalysis) {
  132. adapted.shadows.intensity = lightingAnalysis.shadowAnalysis.shadowPresence?.intensity || adapted.shadows.intensity;
  133. const sharpnessMap: {[key: string]: number} = {
  134. 'very-soft': 20, 'soft': 40, 'medium': 60, 'sharp': 80, 'very-sharp': 100
  135. };
  136. const sharpness = lightingAnalysis.shadowAnalysis.shadowPresence?.sharpness;
  137. adapted.shadows.softness = 100 - (sharpnessMap[sharpness] || 60);
  138. }
  139. return adapted;
  140. }
  141. /**
  142. * 适配环境参数
  143. */
  144. private adaptEnvironmentParams(baseParams: EnvironmentParams, analysisResult: any): EnvironmentParams {
  145. const adapted = { ...baseParams };
  146. // 根据色彩分析适配氛围
  147. if (analysisResult.enhancedColorAnalysis?.colorPsychology) {
  148. const mood = analysisResult.enhancedColorAnalysis.colorPsychology.primaryMood;
  149. const atmosphereMap: {[key: string]: string} = {
  150. 'calm': 'minimal',
  151. 'energetic': 'modern',
  152. 'warm': 'cozy',
  153. 'sophisticated': 'luxurious',
  154. 'natural': 'natural',
  155. 'modern': 'modern'
  156. };
  157. adapted.atmosphere = atmosphereMap[mood] as any || adapted.atmosphere;
  158. }
  159. // 根据材质分析适配设置
  160. if (analysisResult.textureAnalysis?.materialClassification) {
  161. const primaryMaterial = analysisResult.textureAnalysis.materialClassification.primaryMaterial?.category;
  162. if (primaryMaterial === 'wood' || primaryMaterial === 'fabric') {
  163. adapted.setting = 'indoor';
  164. } else if (primaryMaterial === 'stone' || primaryMaterial === 'metal') {
  165. adapted.setting = adapted.setting === 'outdoor' ? 'outdoor' : 'indoor';
  166. }
  167. }
  168. return adapted;
  169. }
  170. /**
  171. * 适配风格参数
  172. */
  173. private adaptStyleParams(baseParams: StyleParams, analysisResult: any): StyleParams {
  174. const adapted = { ...baseParams };
  175. // 根据形体分析适配渲染风格
  176. if (analysisResult.formAnalysis?.overallAssessment) {
  177. const complexity = analysisResult.formAnalysis.overallAssessment.formComplexity;
  178. if (complexity > 70) {
  179. adapted.renderStyle = 'dramatic';
  180. adapted.textureDetail = 'high';
  181. } else if (complexity < 30) {
  182. adapted.renderStyle = 'minimalist';
  183. adapted.textureDetail = 'medium';
  184. }
  185. }
  186. // 根据纹理分析适配纹理细节
  187. if (analysisResult.patternAnalysis?.patternRecognition) {
  188. const patternCount = analysisResult.patternAnalysis.patternRecognition.primaryPatterns?.length || 0;
  189. if (patternCount > 2) {
  190. adapted.textureDetail = 'high';
  191. } else if (patternCount === 0) {
  192. adapted.textureDetail = 'low';
  193. }
  194. }
  195. // 根据色彩分析适配色彩分级
  196. if (analysisResult.enhancedColorAnalysis) {
  197. const saturation = analysisResult.enhancedColorAnalysis.colorWheel?.saturation;
  198. if (saturation > 70) {
  199. adapted.colorGrading = 'high-contrast';
  200. } else if (saturation < 30) {
  201. adapted.colorGrading = 'vintage';
  202. }
  203. }
  204. return adapted;
  205. }
  206. /**
  207. * 生成氛围感预览图URL
  208. */
  209. /**
  210. * 生成氛围感预览图URL(已弃用,使用 AtmospherePreviewService)
  211. * @deprecated 使用 AtmospherePreviewService.generateAtmospherePreview 替代
  212. */
  213. private generateAtmospherePreview(params: SceneParams, sceneType: SceneTemplate): string {
  214. // 这里应该调用实际的预览图生成服务
  215. // 目前返回模拟的URL
  216. const baseUrl = '/assets/previews/';
  217. const sceneId = sceneType.toString();
  218. const styleHash = this.generateStyleHash(params);
  219. return `${baseUrl}${sceneId}_${styleHash}.jpg`;
  220. }
  221. /**
  222. * 生成场景ID
  223. */
  224. private generateSceneId(sceneType: SceneTemplate): string {
  225. const timestamp = Date.now();
  226. return `${sceneType}_${timestamp}`;
  227. }
  228. /**
  229. * 计算映射置信度
  230. */
  231. private calculateConfidence(analysisResult: any, params: SceneParams): number {
  232. let confidence = 50; // 基础置信度
  233. // 根据分析结果的完整性调整置信度
  234. if (analysisResult.lightingAnalysis) confidence += 15;
  235. if (analysisResult.enhancedColorAnalysis) confidence += 15;
  236. if (analysisResult.textureAnalysis) confidence += 10;
  237. if (analysisResult.formAnalysis) confidence += 5;
  238. if (analysisResult.patternAnalysis) confidence += 5;
  239. return Math.min(confidence, 100);
  240. }
  241. /**
  242. * 生成优化建议
  243. */
  244. private generateSuggestions(analysisResult: any, params: SceneParams): string[] {
  245. const suggestions: string[] = [];
  246. // 基于灯光分析的建议
  247. if (analysisResult.lightingAnalysis?.ambientAnalysis?.lightingMood?.primary === 'dramatic') {
  248. suggestions.push('考虑增加重点照明以突出戏剧效果');
  249. }
  250. // 基于色彩分析的建议
  251. if (analysisResult.enhancedColorAnalysis?.colorWheel?.saturation < 30) {
  252. suggestions.push('可以适当增加色彩饱和度以提升视觉效果');
  253. }
  254. // 基于材质分析的建议
  255. if (analysisResult.textureAnalysis?.surfaceProperties?.roughness?.level === 'high') {
  256. suggestions.push('建议平衡粗糙和光滑材质的比例');
  257. }
  258. return suggestions;
  259. }
  260. /**
  261. * 生成风格哈希值
  262. */
  263. private generateStyleHash(params: SceneParams): string {
  264. const styleString = JSON.stringify({
  265. lighting: params.lighting.primaryLight.type,
  266. mood: params.lighting.ambientLight.mood,
  267. style: params.style.renderStyle,
  268. atmosphere: params.environment.atmosphere
  269. });
  270. // 简单的哈希函数
  271. let hash = 0;
  272. for (let i = 0; i < styleString.length; i++) {
  273. const char = styleString.charCodeAt(i);
  274. hash = ((hash << 5) - hash) + char;
  275. hash = hash & hash; // 转换为32位整数
  276. }
  277. return Math.abs(hash).toString(16).substring(0, 8);
  278. }
  279. /**
  280. * 获取默认场景参数
  281. */
  282. private getDefaultSceneParams(): SceneParams {
  283. return {
  284. lighting: {
  285. primaryLight: {
  286. type: 'natural',
  287. intensity: 70,
  288. temperature: 5500,
  289. direction: 'top'
  290. },
  291. ambientLight: {
  292. strength: 40,
  293. mood: 'calm'
  294. },
  295. shadows: {
  296. intensity: 50,
  297. softness: 60
  298. }
  299. },
  300. environment: {
  301. setting: 'indoor',
  302. atmosphere: 'modern',
  303. timeOfDay: 'afternoon',
  304. weatherCondition: 'sunny'
  305. },
  306. composition: {
  307. viewAngle: 'medium',
  308. perspective: 'eye-level',
  309. focusPoint: 'center',
  310. depth: 70
  311. },
  312. style: {
  313. renderStyle: 'photorealistic',
  314. colorGrading: 'natural',
  315. textureDetail: 'high'
  316. }
  317. };
  318. }
  319. /**
  320. * 初始化场景模板
  321. */
  322. private initializeSceneTemplates(): void {
  323. // 现代客厅
  324. this.sceneTemplates.set(SceneTemplate.LIVING_ROOM_MODERN, {
  325. lighting: {
  326. primaryLight: { type: 'natural', intensity: 75, temperature: 5500, direction: 'front' },
  327. ambientLight: { strength: 45, mood: 'calm' },
  328. shadows: { intensity: 40, softness: 70 }
  329. },
  330. environment: {
  331. setting: 'indoor',
  332. atmosphere: 'modern',
  333. timeOfDay: 'afternoon'
  334. },
  335. composition: {
  336. viewAngle: 'wide',
  337. perspective: 'eye-level',
  338. focusPoint: 'center',
  339. depth: 80
  340. },
  341. style: {
  342. renderStyle: 'photorealistic',
  343. colorGrading: 'modern',
  344. textureDetail: 'high'
  345. }
  346. });
  347. // 经典客厅
  348. this.sceneTemplates.set(SceneTemplate.LIVING_ROOM_CLASSIC, {
  349. lighting: {
  350. primaryLight: { type: 'artificial', intensity: 65, temperature: 3000, direction: 'top' },
  351. ambientLight: { strength: 55, mood: 'romantic' },
  352. shadows: { intensity: 60, softness: 50 }
  353. },
  354. environment: {
  355. setting: 'indoor',
  356. atmosphere: 'luxurious',
  357. timeOfDay: 'evening'
  358. },
  359. composition: {
  360. viewAngle: 'medium',
  361. perspective: 'eye-level',
  362. focusPoint: 'center',
  363. depth: 75
  364. },
  365. style: {
  366. renderStyle: 'artistic',
  367. colorGrading: 'warm',
  368. textureDetail: 'high'
  369. }
  370. });
  371. // 简约卧室
  372. this.sceneTemplates.set(SceneTemplate.BEDROOM_MINIMAL, {
  373. lighting: {
  374. primaryLight: { type: 'natural', intensity: 60, temperature: 5000, direction: 'left' },
  375. ambientLight: { strength: 30, mood: 'calm' },
  376. shadows: { intensity: 35, softness: 80 }
  377. },
  378. environment: {
  379. setting: 'indoor',
  380. atmosphere: 'minimal',
  381. timeOfDay: 'morning'
  382. },
  383. composition: {
  384. viewAngle: 'medium',
  385. perspective: 'eye-level',
  386. focusPoint: 'center',
  387. depth: 60
  388. },
  389. style: {
  390. renderStyle: 'minimalist',
  391. colorGrading: 'natural',
  392. textureDetail: 'medium'
  393. }
  394. });
  395. // 温馨卧室
  396. this.sceneTemplates.set(SceneTemplate.BEDROOM_COZY, {
  397. lighting: {
  398. primaryLight: { type: 'artificial', intensity: 50, temperature: 2700, direction: 'multiple' },
  399. ambientLight: { strength: 60, mood: 'romantic' },
  400. shadows: { intensity: 45, softness: 75 }
  401. },
  402. environment: {
  403. setting: 'indoor',
  404. atmosphere: 'cozy',
  405. timeOfDay: 'evening'
  406. },
  407. composition: {
  408. viewAngle: 'close-up',
  409. perspective: 'eye-level',
  410. focusPoint: 'center',
  411. depth: 50
  412. },
  413. style: {
  414. renderStyle: 'soft',
  415. colorGrading: 'warm',
  416. textureDetail: 'high'
  417. }
  418. });
  419. // 现代厨房
  420. this.sceneTemplates.set(SceneTemplate.KITCHEN_CONTEMPORARY, {
  421. lighting: {
  422. primaryLight: { type: 'artificial', intensity: 85, temperature: 4000, direction: 'top' },
  423. ambientLight: { strength: 40, mood: 'energetic' },
  424. shadows: { intensity: 50, softness: 60 }
  425. },
  426. environment: {
  427. setting: 'indoor',
  428. atmosphere: 'modern',
  429. timeOfDay: 'noon'
  430. },
  431. composition: {
  432. viewAngle: 'wide',
  433. perspective: 'eye-level',
  434. focusPoint: 'center',
  435. depth: 70
  436. },
  437. style: {
  438. renderStyle: 'photorealistic',
  439. colorGrading: 'high-contrast',
  440. textureDetail: 'high'
  441. }
  442. });
  443. // 添加更多模板...
  444. // 为了简洁,这里只展示几个主要模板的实现
  445. // 实际项目中应该为所有SceneTemplate枚举值提供对应的配置
  446. }
  447. }