lighting-analysis.service.ts 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  1. import { Injectable } from '@angular/core';
  2. import { Observable, of } from 'rxjs';
  3. // 灯光分析结果接口
  4. export interface LightingAnalysisResult {
  5. lightSourceIdentification: LightSourceIdentification;
  6. illuminationAnalysis: IlluminationAnalysis;
  7. shadowAnalysis: ShadowAnalysis;
  8. ambientAnalysis: AmbientAnalysis;
  9. lightingRecommendations: string[];
  10. }
  11. // 光源识别
  12. export interface LightSourceIdentification {
  13. primarySources: Array<{
  14. type: 'natural' | 'artificial' | 'mixed';
  15. subtype: string; // 如:'sunlight', 'LED', 'fluorescent', 'incandescent', 'candle'
  16. position: {
  17. direction: 'top' | 'front' | 'back' | 'left' | 'right' | 'multiple';
  18. angle: number; // 0-360度
  19. distance: 'close' | 'medium' | 'far' | 'unknown';
  20. };
  21. intensity: number; // 0-100
  22. confidence: number; // 0-100
  23. }>;
  24. lightingSetup: {
  25. complexity: 'simple' | 'moderate' | 'complex' | 'professional';
  26. sourceCount: number;
  27. dominantSource: string;
  28. lightingStyle: 'dramatic' | 'soft' | 'even' | 'accent' | 'task' | 'ambient';
  29. };
  30. }
  31. // 照明效果分析
  32. export interface IlluminationAnalysis {
  33. brightness: {
  34. overall: number; // 0-100
  35. distribution: 'even' | 'uneven' | 'gradient' | 'spotty';
  36. dynamicRange: number; // 0-100
  37. exposure: 'underexposed' | 'well-exposed' | 'overexposed' | 'mixed';
  38. };
  39. contrast: {
  40. level: number; // 0-100
  41. type: 'low' | 'medium' | 'high' | 'extreme';
  42. areas: {
  43. highlights: number; // 0-100
  44. midtones: number; // 0-100
  45. shadows: number; // 0-100
  46. };
  47. };
  48. colorTemperature: {
  49. kelvin: number; // 色温值
  50. warmth: 'very-warm' | 'warm' | 'neutral' | 'cool' | 'very-cool';
  51. consistency: number; // 0-100
  52. mixedLighting: boolean;
  53. };
  54. lightQuality: {
  55. softness: number; // 0-100 (0=hard, 100=soft)
  56. diffusion: number; // 0-100
  57. directionality: number; // 0-100 (0=omnidirectional, 100=highly directional)
  58. evenness: number; // 0-100
  59. };
  60. }
  61. // 阴影分析
  62. export interface ShadowAnalysis {
  63. shadowPresence: {
  64. coverage: number; // 0-100
  65. intensity: number; // 0-100
  66. sharpness: 'very-soft' | 'soft' | 'medium' | 'sharp' | 'very-sharp';
  67. definition: number; // 0-100
  68. };
  69. shadowCharacteristics: {
  70. direction: string;
  71. length: 'short' | 'medium' | 'long' | 'varied';
  72. density: number; // 0-100
  73. falloff: 'gradual' | 'medium' | 'abrupt';
  74. };
  75. shadowTypes: Array<{
  76. type: 'cast' | 'form' | 'occlusion' | 'contact';
  77. prominence: number; // 0-100
  78. contribution: string;
  79. }>;
  80. dimensionalEffect: {
  81. depth: number; // 0-100
  82. volume: number; // 0-100
  83. threedimensionality: number; // 0-100
  84. };
  85. }
  86. // 环境光分析
  87. export interface AmbientAnalysis {
  88. ambientLevel: {
  89. strength: number; // 0-100
  90. uniformity: number; // 0-100
  91. contribution: number; // 0-100 (相对于直接光的贡献)
  92. };
  93. lightingMood: {
  94. primary: 'dramatic' | 'romantic' | 'energetic' | 'calm' | 'mysterious' | 'cheerful' | 'professional';
  95. intensity: number; // 0-100
  96. emotional_impact: string[];
  97. };
  98. atmosphericEffects: {
  99. haze: number; // 0-100
  100. glare: number; // 0-100
  101. reflections: number; // 0-100
  102. transparency: number; // 0-100
  103. };
  104. spatialPerception: {
  105. depth_enhancement: number; // 0-100
  106. space_definition: number; // 0-100
  107. focal_guidance: number; // 0-100
  108. };
  109. }
  110. @Injectable({
  111. providedIn: 'root'
  112. })
  113. export class LightingAnalysisService {
  114. constructor() { }
  115. /**
  116. * 分析图片中的灯光效果
  117. * @param imageFile 图片文件
  118. */
  119. analyzeImageLighting(imageFile: File): Observable<LightingAnalysisResult> {
  120. return of(this.simulateLightingAnalysis(imageFile));
  121. }
  122. /**
  123. * 分析URL图片的灯光效果
  124. * @param imageUrl 图片URL
  125. */
  126. analyzeLightingFromUrl(imageUrl: string): Observable<LightingAnalysisResult> {
  127. return of(this.simulateLightingAnalysisFromUrl(imageUrl));
  128. }
  129. /**
  130. * 模拟灯光分析
  131. */
  132. private simulateLightingAnalysis(imageFile: File): LightingAnalysisResult {
  133. const fileName = imageFile.name.toLowerCase();
  134. return this.generateLightingAnalysis(fileName);
  135. }
  136. private simulateLightingAnalysisFromUrl(imageUrl: string): LightingAnalysisResult {
  137. const urlLower = imageUrl.toLowerCase();
  138. return this.generateLightingAnalysis(urlLower);
  139. }
  140. private generateLightingAnalysis(context: string): LightingAnalysisResult {
  141. const lightingType = this.inferLightingType(context);
  142. return {
  143. lightSourceIdentification: this.generateLightSourceIdentification(lightingType, context),
  144. illuminationAnalysis: this.generateIlluminationAnalysis(lightingType, context),
  145. shadowAnalysis: this.generateShadowAnalysis(lightingType, context),
  146. ambientAnalysis: this.generateAmbientAnalysis(lightingType, context),
  147. lightingRecommendations: this.generateLightingRecommendations(lightingType, context)
  148. };
  149. }
  150. private inferLightingType(context: string): string {
  151. if (context.includes('natural') || context.includes('sun') || context.includes('daylight')) return 'natural';
  152. if (context.includes('artificial') || context.includes('led') || context.includes('lamp')) return 'artificial';
  153. if (context.includes('dramatic') || context.includes('shadow')) return 'dramatic';
  154. if (context.includes('soft') || context.includes('diffuse')) return 'soft';
  155. if (context.includes('bright') || context.includes('high')) return 'bright';
  156. if (context.includes('dim') || context.includes('low')) return 'dim';
  157. if (context.includes('warm')) return 'warm';
  158. if (context.includes('cool')) return 'cool';
  159. return 'mixed'; // 默认混合光源
  160. }
  161. private generateLightSourceIdentification(lightingType: string, context: string): LightSourceIdentification {
  162. const isNatural = lightingType === 'natural' || context.includes('outdoor');
  163. const isComplex = context.includes('complex') || context.includes('multiple');
  164. return {
  165. primarySources: this.generatePrimarySources(lightingType, isNatural, isComplex),
  166. lightingSetup: {
  167. complexity: isComplex ? 'complex' : this.getLightingComplexity(lightingType),
  168. sourceCount: isComplex ? 3 + Math.floor(Math.random() * 3) : this.getSourceCount(lightingType),
  169. dominantSource: this.getDominantSource(lightingType, isNatural),
  170. lightingStyle: this.getLightingStyle(lightingType)
  171. }
  172. };
  173. }
  174. private generatePrimarySources(lightingType: string, isNatural: boolean, isComplex: boolean): any[] {
  175. const sources = [];
  176. if (isNatural) {
  177. sources.push({
  178. type: 'natural',
  179. subtype: 'sunlight',
  180. position: {
  181. direction: 'top',
  182. angle: 45 + Math.random() * 90,
  183. distance: 'far'
  184. },
  185. intensity: 70 + Math.random() * 25,
  186. confidence: 85 + Math.random() * 10
  187. });
  188. } else {
  189. sources.push({
  190. type: 'artificial',
  191. subtype: this.getArtificialSubtype(lightingType),
  192. position: {
  193. direction: this.getLightDirection(lightingType),
  194. angle: Math.random() * 360,
  195. distance: this.getLightDistance(lightingType)
  196. },
  197. intensity: this.getLightIntensity(lightingType),
  198. confidence: 80 + Math.random() * 15
  199. });
  200. }
  201. if (isComplex) {
  202. // 添加辅助光源
  203. sources.push({
  204. type: 'artificial',
  205. subtype: 'LED',
  206. position: {
  207. direction: 'front',
  208. angle: 30 + Math.random() * 60,
  209. distance: 'medium'
  210. },
  211. intensity: 40 + Math.random() * 30,
  212. confidence: 70 + Math.random() * 20
  213. });
  214. }
  215. return sources;
  216. }
  217. private generateIlluminationAnalysis(lightingType: string, context: string): IlluminationAnalysis {
  218. const isBright = lightingType === 'bright' || context.includes('bright');
  219. const isDim = lightingType === 'dim' || context.includes('dim');
  220. const isWarm = lightingType === 'warm' || context.includes('warm');
  221. const isCool = lightingType === 'cool' || context.includes('cool');
  222. return {
  223. brightness: {
  224. overall: this.getBrightnessLevel(lightingType, isBright, isDim),
  225. distribution: this.getBrightnessDistribution(lightingType),
  226. dynamicRange: this.getDynamicRange(lightingType),
  227. exposure: this.getExposureLevel(lightingType, isBright, isDim)
  228. },
  229. contrast: {
  230. level: this.getContrastLevel(lightingType),
  231. type: this.getContrastType(lightingType),
  232. areas: {
  233. highlights: this.getHighlights(lightingType),
  234. midtones: this.getMidtones(lightingType),
  235. shadows: this.getShadowsLevel(lightingType)
  236. }
  237. },
  238. colorTemperature: {
  239. kelvin: this.getColorTemperature(lightingType, isWarm, isCool),
  240. warmth: this.getWarmthLevel(lightingType, isWarm, isCool),
  241. consistency: this.getTemperatureConsistency(lightingType),
  242. mixedLighting: lightingType === 'mixed' || context.includes('mixed')
  243. },
  244. lightQuality: {
  245. softness: this.getLightSoftness(lightingType),
  246. diffusion: this.getLightDiffusion(lightingType),
  247. directionality: this.getLightDirectionality(lightingType),
  248. evenness: this.getLightEvenness(lightingType)
  249. }
  250. };
  251. }
  252. private generateShadowAnalysis(lightingType: string, context: string): ShadowAnalysis {
  253. const isDramatic = lightingType === 'dramatic' || context.includes('dramatic');
  254. const isSoft = lightingType === 'soft' || context.includes('soft');
  255. return {
  256. shadowPresence: {
  257. coverage: this.getShadowCoverage(lightingType, isDramatic),
  258. intensity: this.getShadowIntensity(lightingType, isDramatic),
  259. sharpness: this.getShadowSharpness(lightingType, isSoft),
  260. definition: this.getShadowDefinition(lightingType)
  261. },
  262. shadowCharacteristics: {
  263. direction: this.getShadowDirection(lightingType),
  264. length: this.getShadowLength(lightingType),
  265. density: this.getShadowDensity(lightingType),
  266. falloff: this.getShadowFalloff(lightingType, isSoft)
  267. },
  268. shadowTypes: this.getShadowTypes(lightingType),
  269. dimensionalEffect: {
  270. depth: this.getDepthEffect(lightingType, isDramatic),
  271. volume: this.getVolumeEffect(lightingType),
  272. threedimensionality: this.get3DEffect(lightingType, isDramatic)
  273. }
  274. };
  275. }
  276. private generateAmbientAnalysis(lightingType: string, context: string): AmbientAnalysis {
  277. return {
  278. ambientLevel: {
  279. strength: this.getAmbientStrength(lightingType),
  280. uniformity: this.getAmbientUniformity(lightingType),
  281. contribution: this.getAmbientContribution(lightingType)
  282. },
  283. lightingMood: {
  284. primary: this.getLightingMood(lightingType, context),
  285. intensity: this.getMoodIntensity(lightingType),
  286. emotional_impact: this.getEmotionalImpact(lightingType, context)
  287. },
  288. atmosphericEffects: {
  289. haze: this.getHazeLevel(lightingType, context),
  290. glare: this.getGlareLevel(lightingType),
  291. reflections: this.getReflectionLevel(lightingType, context),
  292. transparency: this.getTransparencyLevel(lightingType)
  293. },
  294. spatialPerception: {
  295. depth_enhancement: this.getDepthEnhancement(lightingType),
  296. space_definition: this.getSpaceDefinition(lightingType),
  297. focal_guidance: this.getFocalGuidance(lightingType)
  298. }
  299. };
  300. }
  301. private generateLightingRecommendations(lightingType: string, context: string): string[] {
  302. const recommendations = [];
  303. // 基于光照类型的建议
  304. switch (lightingType) {
  305. case 'natural':
  306. recommendations.push('充分利用自然光的方向性和时间变化');
  307. recommendations.push('考虑添加辅助人工光源平衡光照');
  308. break;
  309. case 'artificial':
  310. recommendations.push('注意人工光源的色温一致性');
  311. recommendations.push('避免过度依赖单一光源');
  312. break;
  313. case 'dramatic':
  314. recommendations.push('保持强烈的明暗对比效果');
  315. recommendations.push('注意阴影的艺术表现力');
  316. break;
  317. case 'soft':
  318. recommendations.push('维持柔和均匀的光照效果');
  319. recommendations.push('避免产生过强的阴影');
  320. break;
  321. case 'bright':
  322. recommendations.push('控制过度曝光的风险');
  323. recommendations.push('注意高光区域的细节保留');
  324. break;
  325. case 'dim':
  326. recommendations.push('增强关键区域的照明');
  327. recommendations.push('注意暗部细节的可见性');
  328. break;
  329. }
  330. // 基于上下文的建议
  331. if (context.includes('interior')) {
  332. recommendations.push('考虑室内空间的光照层次');
  333. recommendations.push('注意光照对材质表现的影响');
  334. }
  335. if (context.includes('portrait')) {
  336. recommendations.push('优化面部光照的均匀性');
  337. recommendations.push('避免产生不利的阴影');
  338. }
  339. if (context.includes('product')) {
  340. recommendations.push('确保产品细节的清晰展示');
  341. recommendations.push('避免反光和眩光问题');
  342. }
  343. return recommendations.length > 0 ? recommendations : ['保持光照设计的整体协调性'];
  344. }
  345. // 辅助方法实现
  346. private getLightingComplexity(lightingType: string): 'simple' | 'moderate' | 'complex' | 'professional' {
  347. const complexities: { [key: string]: 'simple' | 'moderate' | 'complex' | 'professional' } = {
  348. natural: 'simple', artificial: 'moderate', dramatic: 'complex',
  349. soft: 'moderate', bright: 'simple', dim: 'moderate',
  350. warm: 'simple', cool: 'simple', mixed: 'complex'
  351. };
  352. return complexities[lightingType] || 'moderate';
  353. }
  354. private getSourceCount(lightingType: string): number {
  355. const counts: { [key: string]: number } = {
  356. natural: 1, artificial: 2, dramatic: 3, soft: 2,
  357. bright: 1, dim: 2, warm: 1, cool: 1, mixed: 3
  358. };
  359. return counts[lightingType] || 2;
  360. }
  361. private getDominantSource(lightingType: string, isNatural: boolean): string {
  362. if (isNatural) return 'sunlight';
  363. const sources: { [key: string]: string } = {
  364. artificial: 'LED', dramatic: 'spotlight', soft: 'softbox',
  365. bright: 'floodlight', dim: 'ambient', warm: 'incandescent',
  366. cool: 'fluorescent', mixed: 'multiple'
  367. };
  368. return sources[lightingType] || 'LED';
  369. }
  370. private getLightingStyle(lightingType: string): 'dramatic' | 'soft' | 'even' | 'accent' | 'task' | 'ambient' {
  371. const styles: { [key: string]: 'dramatic' | 'soft' | 'even' | 'accent' | 'task' | 'ambient' } = {
  372. natural: 'even', artificial: 'task', dramatic: 'dramatic',
  373. soft: 'soft', bright: 'even', dim: 'ambient',
  374. warm: 'ambient', cool: 'task', mixed: 'accent'
  375. };
  376. return styles[lightingType] || 'even';
  377. }
  378. private getArtificialSubtype(lightingType: string): string {
  379. const subtypes: { [key: string]: string } = {
  380. artificial: 'LED', dramatic: 'spotlight', soft: 'softbox',
  381. bright: 'floodlight', dim: 'ambient', warm: 'incandescent',
  382. cool: 'fluorescent', mixed: 'LED'
  383. };
  384. return subtypes[lightingType] || 'LED';
  385. }
  386. private getLightDirection(lightingType: string): 'top' | 'front' | 'back' | 'left' | 'right' | 'multiple' {
  387. const directions: { [key: string]: 'top' | 'front' | 'back' | 'left' | 'right' | 'multiple' } = {
  388. natural: 'top', artificial: 'front', dramatic: 'left',
  389. soft: 'front', bright: 'top', dim: 'multiple',
  390. warm: 'front', cool: 'top', mixed: 'multiple'
  391. };
  392. return directions[lightingType] || 'front';
  393. }
  394. private getLightDistance(lightingType: string): 'close' | 'medium' | 'far' | 'unknown' {
  395. const distances: { [key: string]: 'close' | 'medium' | 'far' | 'unknown' } = {
  396. natural: 'far', artificial: 'medium', dramatic: 'close',
  397. soft: 'medium', bright: 'far', dim: 'close',
  398. warm: 'close', cool: 'medium', mixed: 'medium'
  399. };
  400. return distances[lightingType] || 'medium';
  401. }
  402. private getLightIntensity(lightingType: string): number {
  403. const intensities: { [key: string]: number } = {
  404. natural: 80, artificial: 70, dramatic: 85, soft: 60,
  405. bright: 90, dim: 30, warm: 65, cool: 75, mixed: 70
  406. };
  407. return (intensities[lightingType] || 70) + Math.random() * 15;
  408. }
  409. private getBrightnessLevel(lightingType: string, isBright: boolean, isDim: boolean): number {
  410. if (isBright) return 80 + Math.random() * 15;
  411. if (isDim) return 20 + Math.random() * 20;
  412. const levels: { [key: string]: number } = {
  413. natural: 75, artificial: 65, dramatic: 60, soft: 70,
  414. warm: 60, cool: 70, mixed: 65
  415. };
  416. return (levels[lightingType] || 65) + Math.random() * 15;
  417. }
  418. private getBrightnessDistribution(lightingType: string): 'even' | 'uneven' | 'gradient' | 'spotty' {
  419. const distributions: { [key: string]: 'even' | 'uneven' | 'gradient' | 'spotty' } = {
  420. natural: 'gradient', artificial: 'even', dramatic: 'uneven',
  421. soft: 'even', bright: 'even', dim: 'uneven',
  422. warm: 'gradient', cool: 'even', mixed: 'spotty'
  423. };
  424. return distributions[lightingType] || 'even';
  425. }
  426. private getDynamicRange(lightingType: string): number {
  427. const ranges: { [key: string]: number } = {
  428. natural: 85, artificial: 70, dramatic: 90, soft: 60,
  429. bright: 75, dim: 80, warm: 70, cool: 75, mixed: 85
  430. };
  431. return (ranges[lightingType] || 75) + Math.random() * 10;
  432. }
  433. private getExposureLevel(lightingType: string, isBright: boolean, isDim: boolean): 'underexposed' | 'well-exposed' | 'overexposed' | 'mixed' {
  434. if (isBright) return 'overexposed';
  435. if (isDim) return 'underexposed';
  436. const exposures: { [key: string]: 'underexposed' | 'well-exposed' | 'overexposed' | 'mixed' } = {
  437. natural: 'well-exposed', artificial: 'well-exposed', dramatic: 'mixed',
  438. soft: 'well-exposed', warm: 'well-exposed', cool: 'well-exposed', mixed: 'mixed'
  439. };
  440. return exposures[lightingType] || 'well-exposed';
  441. }
  442. private getContrastLevel(lightingType: string): number {
  443. const contrasts: { [key: string]: number } = {
  444. natural: 70, artificial: 60, dramatic: 90, soft: 40,
  445. bright: 65, dim: 75, warm: 55, cool: 65, mixed: 80
  446. };
  447. return (contrasts[lightingType] || 65) + Math.random() * 15;
  448. }
  449. private getContrastType(lightingType: string): 'low' | 'medium' | 'high' | 'extreme' {
  450. const types: { [key: string]: 'low' | 'medium' | 'high' | 'extreme' } = {
  451. natural: 'medium', artificial: 'medium', dramatic: 'extreme',
  452. soft: 'low', bright: 'medium', dim: 'high',
  453. warm: 'low', cool: 'medium', mixed: 'high'
  454. };
  455. return types[lightingType] || 'medium';
  456. }
  457. private getHighlights(lightingType: string): number {
  458. const highlights: { [key: string]: number } = {
  459. natural: 80, artificial: 70, dramatic: 85, soft: 60,
  460. bright: 90, dim: 40, warm: 65, cool: 75, mixed: 75
  461. };
  462. return (highlights[lightingType] || 70) + Math.random() * 15;
  463. }
  464. private getMidtones(lightingType: string): number {
  465. const midtones: { [key: string]: number } = {
  466. natural: 60, artificial: 65, dramatic: 50, soft: 70,
  467. bright: 55, dim: 45, warm: 65, cool: 60, mixed: 60
  468. };
  469. return (midtones[lightingType] || 60) + Math.random() * 15;
  470. }
  471. private getShadowsLevel(lightingType: string): number {
  472. const shadows: { [key: string]: number } = {
  473. natural: 40, artificial: 45, dramatic: 20, soft: 55,
  474. bright: 35, dim: 65, warm: 50, cool: 40, mixed: 45
  475. };
  476. return (shadows[lightingType] || 45) + Math.random() * 15;
  477. }
  478. private getColorTemperature(lightingType: string, isWarm: boolean, isCool: boolean): number {
  479. if (isWarm) return 2700 + Math.random() * 500;
  480. if (isCool) return 5500 + Math.random() * 1000;
  481. const temperatures: { [key: string]: number } = {
  482. natural: 5500, artificial: 4000, dramatic: 3200,
  483. soft: 4500, bright: 5000, dim: 3000, mixed: 4200
  484. };
  485. return temperatures[lightingType] || 4000;
  486. }
  487. private getWarmthLevel(lightingType: string, isWarm: boolean, isCool: boolean): 'very-warm' | 'warm' | 'neutral' | 'cool' | 'very-cool' {
  488. if (isWarm) return 'warm';
  489. if (isCool) return 'cool';
  490. const warmths: { [key: string]: 'very-warm' | 'warm' | 'neutral' | 'cool' | 'very-cool' } = {
  491. natural: 'neutral', artificial: 'neutral', dramatic: 'warm',
  492. soft: 'warm', bright: 'cool', dim: 'warm', mixed: 'neutral'
  493. };
  494. return warmths[lightingType] || 'neutral';
  495. }
  496. private getTemperatureConsistency(lightingType: string): number {
  497. const consistencies: { [key: string]: number } = {
  498. natural: 90, artificial: 85, dramatic: 70, soft: 80,
  499. bright: 85, dim: 75, warm: 90, cool: 85, mixed: 60
  500. };
  501. return (consistencies[lightingType] || 80) + Math.random() * 10;
  502. }
  503. private getLightSoftness(lightingType: string): number {
  504. const softnesses: { [key: string]: number } = {
  505. natural: 70, artificial: 60, dramatic: 30, soft: 90,
  506. bright: 50, dim: 80, warm: 75, cool: 55, mixed: 65
  507. };
  508. return (softnesses[lightingType] || 65) + Math.random() * 15;
  509. }
  510. private getLightDiffusion(lightingType: string): number {
  511. const diffusions: { [key: string]: number } = {
  512. natural: 75, artificial: 65, dramatic: 40, soft: 85,
  513. bright: 60, dim: 70, warm: 70, cool: 60, mixed: 70
  514. };
  515. return (diffusions[lightingType] || 65) + Math.random() * 15;
  516. }
  517. private getLightDirectionality(lightingType: string): number {
  518. const directionalities: { [key: string]: number } = {
  519. natural: 80, artificial: 70, dramatic: 90, soft: 40,
  520. bright: 75, dim: 50, warm: 60, cool: 70, mixed: 60
  521. };
  522. return (directionalities[lightingType] || 65) + Math.random() * 15;
  523. }
  524. private getLightEvenness(lightingType: string): number {
  525. const evennesses: { [key: string]: number } = {
  526. natural: 60, artificial: 75, dramatic: 30, soft: 85,
  527. bright: 80, dim: 50, warm: 70, cool: 75, mixed: 55
  528. };
  529. return (evennesses[lightingType] || 65) + Math.random() * 15;
  530. }
  531. private getShadowCoverage(lightingType: string, isDramatic: boolean): number {
  532. if (isDramatic) return 60 + Math.random() * 30;
  533. const coverages: { [key: string]: number } = {
  534. natural: 50, artificial: 40, soft: 25, bright: 30,
  535. dim: 70, warm: 45, cool: 35, mixed: 50
  536. };
  537. return (coverages[lightingType] || 45) + Math.random() * 20;
  538. }
  539. private getShadowIntensity(lightingType: string, isDramatic: boolean): number {
  540. if (isDramatic) return 75 + Math.random() * 20;
  541. const intensities: { [key: string]: number } = {
  542. natural: 60, artificial: 50, soft: 30, bright: 45,
  543. dim: 65, warm: 40, cool: 55, mixed: 55
  544. };
  545. return (intensities[lightingType] || 50) + Math.random() * 20;
  546. }
  547. private getShadowSharpness(lightingType: string, isSoft: boolean): 'very-soft' | 'soft' | 'medium' | 'sharp' | 'very-sharp' {
  548. if (isSoft) return 'soft';
  549. const sharpnesses: { [key: string]: 'very-soft' | 'soft' | 'medium' | 'sharp' | 'very-sharp' } = {
  550. natural: 'medium', artificial: 'medium', dramatic: 'sharp',
  551. bright: 'sharp', dim: 'soft', warm: 'soft', cool: 'medium', mixed: 'medium'
  552. };
  553. return sharpnesses[lightingType] || 'medium';
  554. }
  555. private getShadowDefinition(lightingType: string): number {
  556. const definitions: { [key: string]: number } = {
  557. natural: 70, artificial: 65, dramatic: 85, soft: 40,
  558. bright: 75, dim: 55, warm: 50, cool: 70, mixed: 60
  559. };
  560. return (definitions[lightingType] || 60) + Math.random() * 15;
  561. }
  562. private getShadowDirection(lightingType: string): string {
  563. const directions = ['左下', '右下', '正下', '左侧', '右侧', '多方向'];
  564. return directions[Math.floor(Math.random() * directions.length)];
  565. }
  566. private getShadowLength(lightingType: string): 'short' | 'medium' | 'long' | 'varied' {
  567. const lengths: { [key: string]: 'short' | 'medium' | 'long' | 'varied' } = {
  568. natural: 'medium', artificial: 'short', dramatic: 'long',
  569. soft: 'short', bright: 'short', dim: 'medium',
  570. warm: 'medium', cool: 'short', mixed: 'varied'
  571. };
  572. return lengths[lightingType] || 'medium';
  573. }
  574. private getShadowDensity(lightingType: string): number {
  575. const densities: { [key: string]: number } = {
  576. natural: 60, artificial: 55, dramatic: 80, soft: 35,
  577. bright: 45, dim: 70, warm: 50, cool: 60, mixed: 60
  578. };
  579. return (densities[lightingType] || 55) + Math.random() * 20;
  580. }
  581. private getShadowFalloff(lightingType: string, isSoft: boolean): 'gradual' | 'medium' | 'abrupt' {
  582. if (isSoft) return 'gradual';
  583. const falloffs: { [key: string]: 'gradual' | 'medium' | 'abrupt' } = {
  584. natural: 'gradual', artificial: 'medium', dramatic: 'abrupt',
  585. bright: 'medium', dim: 'gradual', warm: 'gradual',
  586. cool: 'medium', mixed: 'medium'
  587. };
  588. return falloffs[lightingType] || 'medium';
  589. }
  590. private getShadowTypes(lightingType: string): Array<{type: 'cast' | 'form' | 'occlusion' | 'contact', prominence: number, contribution: string}> {
  591. const types: Array<{type: 'cast' | 'form' | 'occlusion' | 'contact', prominence: number, contribution: string}> = [
  592. { type: 'cast', prominence: 70 + Math.random() * 25, contribution: '主要阴影效果' },
  593. { type: 'form', prominence: 50 + Math.random() * 30, contribution: '形体塑造' }
  594. ];
  595. if (lightingType === 'dramatic') {
  596. types.push({ type: 'occlusion', prominence: 60 + Math.random() * 30, contribution: '遮挡阴影' });
  597. }
  598. types.push({ type: 'contact', prominence: 40 + Math.random() * 20, contribution: '接触阴影' });
  599. return types;
  600. }
  601. private getDepthEffect(lightingType: string, isDramatic: boolean): number {
  602. if (isDramatic) return 80 + Math.random() * 15;
  603. const depths: { [key: string]: number } = {
  604. natural: 70, artificial: 60, soft: 45, bright: 55,
  605. dim: 75, warm: 60, cool: 65, mixed: 65
  606. };
  607. return (depths[lightingType] || 60) + Math.random() * 20;
  608. }
  609. private getVolumeEffect(lightingType: string): number {
  610. const volumes: { [key: string]: number } = {
  611. natural: 65, artificial: 55, dramatic: 85, soft: 40,
  612. bright: 50, dim: 70, warm: 55, cool: 60, mixed: 60
  613. };
  614. return (volumes[lightingType] || 60) + Math.random() * 20;
  615. }
  616. private get3DEffect(lightingType: string, isDramatic: boolean): number {
  617. if (isDramatic) return 85 + Math.random() * 10;
  618. const effects: { [key: string]: number } = {
  619. natural: 75, artificial: 65, soft: 45, bright: 60,
  620. dim: 70, warm: 60, cool: 70, mixed: 70
  621. };
  622. return (effects[lightingType] || 65) + Math.random() * 20;
  623. }
  624. private getAmbientStrength(lightingType: string): number {
  625. const strengths: { [key: string]: number } = {
  626. natural: 70, artificial: 60, dramatic: 40, soft: 80,
  627. bright: 65, dim: 85, warm: 75, cool: 55, mixed: 65
  628. };
  629. return (strengths[lightingType] || 65) + Math.random() * 15;
  630. }
  631. private getAmbientUniformity(lightingType: string): number {
  632. const uniformities: { [key: string]: number } = {
  633. natural: 60, artificial: 75, dramatic: 30, soft: 85,
  634. bright: 70, dim: 50, warm: 70, cool: 75, mixed: 55
  635. };
  636. return (uniformities[lightingType] || 65) + Math.random() * 15;
  637. }
  638. private getAmbientContribution(lightingType: string): number {
  639. const contributions: { [key: string]: number } = {
  640. natural: 40, artificial: 50, dramatic: 25, soft: 70,
  641. bright: 35, dim: 80, warm: 60, cool: 45, mixed: 55
  642. };
  643. return (contributions[lightingType] || 50) + Math.random() * 20;
  644. }
  645. private getLightingMood(lightingType: string, context: string): 'dramatic' | 'romantic' | 'energetic' | 'calm' | 'mysterious' | 'cheerful' | 'professional' {
  646. if (context.includes('romantic')) return 'romantic';
  647. if (context.includes('energetic')) return 'energetic';
  648. if (context.includes('calm')) return 'calm';
  649. if (context.includes('mysterious')) return 'mysterious';
  650. if (context.includes('cheerful')) return 'cheerful';
  651. if (context.includes('professional')) return 'professional';
  652. const moods: { [key: string]: 'dramatic' | 'romantic' | 'energetic' | 'calm' | 'mysterious' | 'cheerful' | 'professional' } = {
  653. natural: 'cheerful', artificial: 'professional', dramatic: 'dramatic',
  654. soft: 'romantic', bright: 'energetic', dim: 'mysterious',
  655. warm: 'calm', cool: 'professional', mixed: 'energetic'
  656. };
  657. return moods[lightingType] || 'calm';
  658. }
  659. private getMoodIntensity(lightingType: string): number {
  660. const intensities: { [key: string]: number } = {
  661. natural: 70, artificial: 60, dramatic: 90, soft: 75,
  662. bright: 80, dim: 85, warm: 70, cool: 65, mixed: 75
  663. };
  664. return (intensities[lightingType] || 70) + Math.random() * 15;
  665. }
  666. private getEmotionalImpact(lightingType: string, context: string): string[] {
  667. const impacts: { [key: string]: string[] } = {
  668. natural: ['自然', '舒适', '健康'],
  669. artificial: ['现代', '功能性', '可控'],
  670. dramatic: ['戏剧性', '强烈', '艺术感'],
  671. soft: ['温柔', '浪漫', '舒缓'],
  672. bright: ['活力', '清晰', '积极'],
  673. dim: ['神秘', '私密', '放松'],
  674. warm: ['温暖', '舒适', '亲密'],
  675. cool: ['清爽', '专业', '现代'],
  676. mixed: ['丰富', '层次', '复杂']
  677. };
  678. return impacts[lightingType] || ['平衡', '和谐'];
  679. }
  680. private getHazeLevel(lightingType: string, context: string): number {
  681. const base = context.includes('haze') || context.includes('fog') ? 60 : 20;
  682. return base + Math.random() * 30;
  683. }
  684. private getGlareLevel(lightingType: string): number {
  685. const glares: { [key: string]: number } = {
  686. natural: 30, artificial: 25, dramatic: 40, soft: 10,
  687. bright: 60, dim: 5, warm: 15, cool: 35, mixed: 30
  688. };
  689. return (glares[lightingType] || 25) + Math.random() * 20;
  690. }
  691. private getReflectionLevel(lightingType: string, context: string): number {
  692. const base = context.includes('reflection') || context.includes('mirror') ? 70 : 30;
  693. return base + Math.random() * 25;
  694. }
  695. private getTransparencyLevel(lightingType: string): number {
  696. const transparencies: { [key: string]: number } = {
  697. natural: 85, artificial: 75, dramatic: 60, soft: 80,
  698. bright: 90, dim: 50, warm: 70, cool: 80, mixed: 70
  699. };
  700. return (transparencies[lightingType] || 75) + Math.random() * 15;
  701. }
  702. private getDepthEnhancement(lightingType: string): number {
  703. const enhancements: { [key: string]: number } = {
  704. natural: 75, artificial: 65, dramatic: 90, soft: 50,
  705. bright: 60, dim: 80, warm: 60, cool: 70, mixed: 75
  706. };
  707. return (enhancements[lightingType] || 70) + Math.random() * 15;
  708. }
  709. private getSpaceDefinition(lightingType: string): number {
  710. const definitions: { [key: string]: number } = {
  711. natural: 70, artificial: 80, dramatic: 85, soft: 60,
  712. bright: 75, dim: 55, warm: 65, cool: 75, mixed: 70
  713. };
  714. return (definitions[lightingType] || 70) + Math.random() * 15;
  715. }
  716. private getFocalGuidance(lightingType: string): number {
  717. const guidances: { [key: string]: number } = {
  718. natural: 60, artificial: 70, dramatic: 90, soft: 50,
  719. bright: 65, dim: 75, warm: 55, cool: 70, mixed: 75
  720. };
  721. return (guidances[lightingType] || 65) + Math.random() * 15;
  722. }
  723. }