0
# Daylight Analysis
1
2
Integration with Radiance for advanced daylight and lighting analysis capabilities. The Radiance module provides comprehensive daylight simulation tools including illuminance mapping, glare analysis, and annual daylight metrics, enabling detailed lighting design and energy-efficient daylighting strategies.
3
4
## Capabilities
5
6
### Model Translation
7
8
Conversion of OpenStudio models to Radiance format for daylight simulation.
9
10
```cpp { .api }
11
/**
12
* Converts OpenStudio models to Radiance simulation format
13
*/
14
namespace radiance {
15
16
class ForwardTranslator {
17
public:
18
// Constructor
19
ForwardTranslator();
20
21
// Model translation
22
std::vector<Path> translateModel(const Path& outPath, const Model& model);
23
std::vector<Path> translateModel(const Path& outPath,
24
const Model& model,
25
const std::vector<Space>& spaces);
26
27
// Space-specific translation
28
std::vector<Path> translateSpace(const Path& outPath, const Space& space);
29
std::vector<Path> translateSpaces(const Path& outPath,
30
const std::vector<Space>& spaces);
31
32
// Surface translation
33
std::vector<Path> translateSurface(const Path& outPath, const Surface& surface);
34
std::vector<Path> translateSubSurface(const Path& outPath, const SubSurface& subSurface);
35
36
// Material translation
37
std::vector<Path> translateMaterials(const Path& outPath, const Model& model);
38
Path translateMaterial(const Path& outPath, const Material& material);
39
40
// Translation options
41
RadianceParameters radianceParameters() const;
42
void setRadianceParameters(const RadianceParameters& radianceParameters);
43
44
// Error and warning handling
45
std::vector<LogMessage> errors() const;
46
std::vector<LogMessage> warnings() const;
47
48
// Generated files
49
std::vector<Path> radianceFiles() const;
50
std::vector<Path> octreeFiles() const;
51
};
52
53
/**
54
* Radiance simulation parameters and settings
55
*/
56
class RadianceParameters {
57
public:
58
// Constructor
59
RadianceParameters();
60
61
// Ambient bounces
62
boost::optional<int> ambientBounces() const;
63
bool setAmbientBounces(int ambientBounces);
64
void resetAmbientBounces();
65
66
// Ambient divisions
67
boost::optional<int> ambientDivisions() const;
68
bool setAmbientDivisions(int ambientDivisions);
69
void resetAmbientDivisions();
70
71
// Ambient super-samples
72
boost::optional<int> ambientSupersamples() const;
73
bool setAmbientSupersamples(int ambientSupersamples);
74
void resetAmbientSupersamples();
75
76
// Limit reflection
77
boost::optional<int> limitReflection() const;
78
bool setLimitReflection(int limitReflection);
79
void resetLimitReflection();
80
81
// Limit weight
82
boost::optional<double> limitWeight() const;
83
bool setLimitWeight(double limitWeight);
84
void resetLimitWeight();
85
86
// Grid resolution
87
boost::optional<double> gridResolution() const;
88
bool setGridResolution(double gridResolution);
89
void resetGridResolution();
90
91
// Sensor height
92
boost::optional<double> sensorHeight() const;
93
bool setSensorHeight(double sensorHeight);
94
void resetSensorHeight();
95
};
96
97
}
98
```
99
100
**Usage Examples:**
101
102
```cpp
103
#include <openstudio/radiance/ForwardTranslator.hpp>
104
#include <openstudio/model/Model.hpp>
105
106
using namespace openstudio;
107
using namespace openstudio::model;
108
using namespace openstudio::radiance;
109
110
// Load OpenStudio model
111
boost::optional<Model> model = Model::load(Path("office_building.osm"));
112
113
if (model) {
114
// Set up Radiance translator
115
ForwardTranslator ft;
116
117
// Configure simulation parameters
118
RadianceParameters params;
119
params.setAmbientBounces(3);
120
params.setAmbientDivisions(1000);
121
params.setGridResolution(0.5); // 0.5m grid spacing
122
ft.setRadianceParameters(params);
123
124
// Translate model to Radiance
125
Path radianceDir("radiance_simulation");
126
std::vector<Path> radianceFiles = ft.translateModel(radianceDir, *model);
127
128
// Check translation results
129
std::vector<LogMessage> errors = ft.errors();
130
if (errors.empty()) {
131
std::cout << "Radiance translation successful!" << std::endl;
132
std::cout << "Generated " << radianceFiles.size() << " Radiance files" << std::endl;
133
} else {
134
for (const auto& error : errors) {
135
std::cout << "Translation error: " << error.logMessage() << std::endl;
136
}
137
}
138
}
139
```
140
141
### Illuminance Analysis
142
143
Tools for calculating and analyzing illuminance levels and daylight distribution.
144
145
```cpp { .api }
146
/**
147
* Annual illuminance map generation and analysis
148
*/
149
class AnnualIlluminanceMap {
150
public:
151
// Constructors
152
AnnualIlluminanceMap();
153
AnnualIlluminanceMap(const Path& path);
154
155
// File I/O
156
static boost::optional<AnnualIlluminanceMap> load(const Path& path);
157
bool save(const Path& path) const;
158
159
// Illuminance data access
160
boost::optional<Matrix> illuminanceMap() const;
161
std::vector<double> illuminanceValues() const;
162
std::vector<DateTime> dateTimes() const;
163
164
// Grid properties
165
unsigned xPoints() const;
166
unsigned yPoints() const;
167
double xSpacing() const;
168
double ySpacing() const;
169
170
// Statistical analysis
171
boost::optional<double> minimumIlluminance() const;
172
boost::optional<double> maximumIlluminance() const;
173
boost::optional<double> averageIlluminance() const;
174
boost::optional<double> medianIlluminance() const;
175
176
// Daylight metrics
177
boost::optional<double> spatialDaylightAutonomy(double threshold = 300.0) const;
178
boost::optional<double> continuousDaylightAutonomy(double threshold = 300.0) const;
179
boost::optional<double> annualSunlightExposure(double threshold = 1000.0) const;
180
181
// Time-based analysis
182
std::vector<double> illuminanceAtTime(const DateTime& dateTime) const;
183
std::vector<double> illuminanceAtPoint(unsigned x, unsigned y) const;
184
185
// Zone-based metrics
186
boost::optional<double> zoneAverageIlluminance() const;
187
boost::optional<double> uniformityRatio() const;
188
};
189
190
/**
191
* Point-in-time illuminance calculations
192
*/
193
class IlluminanceMap {
194
public:
195
// Constructor
196
IlluminanceMap();
197
IlluminanceMap(const Space& space);
198
199
// Grid definition
200
void setXSpacing(double xSpacing);
201
void setYSpacing(double ySpacing);
202
void setOriginXCoordinate(double originX);
203
void setOriginYCoordinate(double originY);
204
void setOriginZCoordinate(double originZ);
205
206
double xSpacing() const;
207
double ySpacing() const;
208
double originXCoordinate() const;
209
double originYCoordinate() const;
210
double originZCoordinate() const;
211
212
// Grid points
213
std::vector<Point3d> referencePoints() const;
214
unsigned numberofXGridPoints() const;
215
unsigned numberofYGridPoints() const;
216
217
// Space association
218
boost::optional<Space> space() const;
219
bool setSpace(const Space& space);
220
221
// Illuminance calculation
222
std::vector<double> calculateIlluminance(const std::vector<double>& skyValues) const;
223
Matrix calculateIlluminanceMatrix(const Matrix& skyMatrix) const;
224
};
225
226
/**
227
* Daylighting control and sensor modeling
228
*/
229
class DaylightingControl : public SpaceLoadInstance {
230
public:
231
// Constructor
232
DaylightingControl(const Model& model);
233
234
// Position
235
double positionXCoordinate() const;
236
bool setPositionXCoordinate(double positionXCoordinate);
237
238
double positionYCoordinate() const;
239
bool setPositionYCoordinate(double positionYCoordinate);
240
241
double positionZCoordinate() const;
242
bool setPositionZCoordinate(double positionZCoordinate);
243
244
// Sensor orientation
245
double psiRotationAroundXAxis() const;
246
bool setPsiRotationAroundXAxis(double psiRotation);
247
248
double thetaRotationAroundYAxis() const;
249
bool setThetaRotationAroundYAxis(double thetaRotation);
250
251
double phiRotationAroundZAxis() const;
252
bool setPhiRotationAroundZAxis(double phiRotation);
253
254
// Control parameters
255
double illuminanceSetpoint() const;
256
bool setIlluminanceSetpoint(double illuminanceSetpoint);
257
258
boost::optional<double> lightingControlSteps() const;
259
bool setLightingControlSteps(double lightingControlSteps);
260
void resetLightingControlSteps();
261
262
double lightingControlProbability() const;
263
bool setLightingControlProbability(double lightingControlProbability);
264
265
// Glare control
266
boost::optional<double> glareCalculationAzimuthAngleofViewDirectionClockwisefromZoneyAxis() const;
267
bool setGlareCalculationAzimuthAngleofViewDirectionClockwisefromZoneyAxis(double angle);
268
269
boost::optional<double> maximumAllowableDiscomfortGlareIndex() const;
270
bool setMaximumAllowableDiscomfortGlareIndex(double index);
271
};
272
```
273
274
### Window Groups and Daylighting
275
276
Advanced window modeling and daylight analysis for complex fenestration systems.
277
278
```cpp { .api }
279
/**
280
* Window group for coordinated daylighting analysis
281
*/
282
class WindowGroup {
283
public:
284
// Constructor
285
WindowGroup();
286
WindowGroup(const std::vector<SubSurface>& subSurfaces);
287
288
// Window management
289
std::vector<SubSurface> subSurfaces() const;
290
bool addSubSurface(const SubSurface& subSurface);
291
bool removeSubSurface(const SubSurface& subSurface);
292
void clearSubSurfaces();
293
294
// Group properties
295
boost::optional<std::string> name() const;
296
void setName(const std::string& name);
297
298
boost::optional<double> windowGroupRendering() const;
299
void setWindowGroupRendering(double windowGroupRendering);
300
301
// Window group control
302
boost::optional<Construction> windowGroupConstruction() const;
303
void setWindowGroupConstruction(const Construction& construction);
304
305
boost::optional<ShadingControl> windowGroupShadingControl() const;
306
void setWindowGroupShadingControl(const ShadingControl& shadingControl);
307
308
// Daylight matrix generation
309
std::vector<Path> generateDaylightMatrix(const Path& outputDir,
310
const RadianceParameters& parameters) const;
311
312
// View matrix calculation
313
Matrix calculateViewMatrix(const std::vector<Point3d>& sensorPoints,
314
const RadianceParameters& parameters) const;
315
};
316
317
/**
318
* Three-phase method daylight calculation
319
*/
320
class ThreePhaseMethod {
321
public:
322
// Constructor
323
ThreePhaseMethod();
324
325
// Matrix components
326
void setViewMatrix(const Matrix& viewMatrix);
327
void setDaylightMatrix(const Matrix& daylightMatrix);
328
void setSkyMatrix(const Matrix& skyMatrix);
329
330
Matrix viewMatrix() const;
331
Matrix daylightMatrix() const;
332
Matrix skyMatrix() const;
333
334
// Calculation
335
Matrix calculateIlluminance() const;
336
std::vector<double> calculateAnnualIlluminance(const std::vector<DateTime>& dateTimes) const;
337
338
// Sky conditions
339
void setClearSky();
340
void setOvercastSky();
341
void setIntermediateSky();
342
void setCustomSky(const Matrix& skyRadiance);
343
344
// Window state management
345
void setWindowState(const WindowGroup& windowGroup, const std::string& state);
346
std::map<WindowGroup, std::string> windowStates() const;
347
};
348
```
349
350
### Radiance Utilities and Support
351
352
Helper classes for Radiance file management and simulation control.
353
354
```cpp { .api }
355
/**
356
* Radiance file header information
357
*/
358
class HeaderInfo {
359
public:
360
// Constructor
361
HeaderInfo();
362
363
// Header fields
364
std::string creator() const;
365
void setCreator(const std::string& creator);
366
367
DateTime creationDate() const;
368
void setCreationDate(const DateTime& date);
369
370
std::string description() const;
371
void setDescription(const std::string& description);
372
373
std::string format() const;
374
void setFormat(const std::string& format);
375
376
// View information
377
boost::optional<std::string> view() const;
378
void setView(const std::string& view);
379
void resetView();
380
381
// Resolution
382
boost::optional<int> xResolution() const;
383
boost::optional<int> yResolution() const;
384
void setResolution(int x, int y);
385
386
// File generation
387
std::string generateHeader() const;
388
};
389
390
/**
391
* Radiance utility functions
392
*/
393
namespace Utils {
394
395
// File path utilities
396
Path radianceDirectory();
397
Path radianceBinDirectory();
398
Path radianceLibDirectory();
399
400
// Executable paths
401
Path rpictPath();
402
Path rtracePath();
403
Path rviewPath();
404
Path oconvPath();
405
Path genDayMtxPath();
406
407
// Sky generation
408
Path generateClearSky(const Path& outputDir,
409
const DateTime& dateTime,
410
double latitude,
411
double longitude,
412
double timeZone);
413
414
Path generateOvercastSky(const Path& outputDir);
415
416
Path generateIntermediateSky(const Path& outputDir,
417
const DateTime& dateTime,
418
double latitude,
419
double longitude,
420
double timeZone,
421
double cloudCover);
422
423
// Weather file processing
424
std::vector<Matrix> generateAnnualSkyMatrix(const Path& weatherFile,
425
const Path& outputDir);
426
427
Matrix generateSkyMatrix(const std::vector<DateTime>& dateTimes,
428
const std::vector<double>& directNormalIrradiance,
429
const std::vector<double>& diffuseHorizontalIrradiance);
430
431
// Simulation execution
432
bool runRadianceSimulation(const Path& octreeFile,
433
const Path& viewFile,
434
const Path& outputFile,
435
const RadianceParameters& parameters);
436
437
bool runRtrace(const Path& octreeFile,
438
const std::vector<Point3d>& points,
439
const std::vector<Vector3d>& directions,
440
const Path& outputFile);
441
442
// Result processing
443
std::vector<double> parseIlluminanceResults(const Path& resultsFile);
444
Matrix parseMatrixResults(const Path& matrixFile);
445
446
// File validation
447
bool validateRadianceFile(const Path& radianceFile);
448
bool validateOctreeFile(const Path& octreeFile);
449
}
450
```
451
452
### Annual Daylight Metrics
453
454
Comprehensive daylight performance metrics and analysis tools.
455
456
```cpp { .api }
457
/**
458
* Annual daylight performance metrics calculation
459
*/
460
class AnnualDaylightMetrics {
461
public:
462
// Constructor from illuminance map
463
AnnualDaylightMetrics(const AnnualIlluminanceMap& illuminanceMap);
464
465
// Daylight Autonomy (DA)
466
double daylightAutonomy(double threshold = 300.0) const;
467
Matrix daylightAutonomyMap(double threshold = 300.0) const;
468
469
// Continuous Daylight Autonomy (cDA)
470
double continuousDaylightAutonomy(double threshold = 300.0) const;
471
Matrix continuousDaylightAutonomyMap(double threshold = 300.0) const;
472
473
// Spatial Daylight Autonomy (sDA)
474
double spatialDaylightAutonomy(double threshold = 300.0, double areaThreshold = 0.50) const;
475
476
// Annual Sunlight Exposure (ASE)
477
double annualSunlightExposure(double threshold = 1000.0, double areaThreshold = 0.10) const;
478
Matrix annualSunlightExposureMap(double threshold = 1000.0) const;
479
480
// Useful Daylight Illuminance (UDI)
481
struct UDIBins {
482
double fell_short; // < 100 lux
483
double supplementary; // 100-300 lux
484
double autonomous; // 300-3000 lux
485
double exceeded; // > 3000 lux
486
};
487
488
UDIBins usefulDaylightIlluminance() const;
489
std::map<std::string, Matrix> usefulDaylightIlluminanceMaps() const;
490
491
// Daylight Glare Probability (DGP) - requires view analysis
492
boost::optional<double> daylightGlareProbability() const;
493
void setDaylightGlareProbability(double dgp);
494
495
// Climate-based daylight modeling
496
double climaticAvailability() const;
497
std::vector<double> monthlyDaylightAvailability() const;
498
499
// Summary statistics
500
struct DaylightSummary {
501
double mean_illuminance;
502
double median_illuminance;
503
double min_illuminance;
504
double max_illuminance;
505
double uniformity_ratio;
506
double daylight_autonomy;
507
double spatial_daylight_autonomy;
508
double annual_sunlight_exposure;
509
};
510
511
DaylightSummary generateSummary() const;
512
};
513
```
514
515
## Common Usage Patterns
516
517
### Basic Radiance Translation and Simulation
518
519
```cpp
520
#include <openstudio/radiance/ForwardTranslator.hpp>
521
#include <openstudio/radiance/Utils.hpp>
522
523
using namespace openstudio;
524
using namespace openstudio::model;
525
using namespace openstudio::radiance;
526
527
// Load model and set up translation
528
boost::optional<Model> model = Model::load(Path("daylit_office.osm"));
529
530
if (model) {
531
// Configure Radiance parameters for high accuracy
532
RadianceParameters params;
533
params.setAmbientBounces(5);
534
params.setAmbientDivisions(1500);
535
params.setAmbientSupersamples(100);
536
params.setLimitWeight(0.0002);
537
538
// Set up translator
539
ForwardTranslator ft;
540
ft.setRadianceParameters(params);
541
542
// Translate specific spaces (e.g., only occupied spaces)
543
std::vector<Space> spaces;
544
for (const auto& space : model->getConcreteModelObjects<Space>()) {
545
// Only translate spaces with people
546
if (!space.people().empty()) {
547
spaces.push_back(space);
548
}
549
}
550
551
// Translate to Radiance
552
Path radianceDir("daylight_analysis");
553
std::vector<Path> radianceFiles = ft.translateModel(radianceDir, *model, spaces);
554
555
// Generate octree for simulation
556
Path octreeFile = radianceDir / "scene.oct";
557
// Note: In practice, you would call oconv to generate the octree
558
559
// Set up illuminance mapping
560
for (const auto& space : spaces) {
561
IlluminanceMap illumMap(space);
562
illumMap.setXSpacing(0.5); // 0.5m grid
563
illumMap.setYSpacing(0.5);
564
illumMap.setOriginZCoordinate(0.8); // Desktop height
565
566
// Calculate reference points
567
std::vector<Point3d> points = illumMap.referencePoints();
568
std::cout << "Space '" << space.name().get_value_or("Unnamed")
569
<< "' has " << points.size() << " analysis points" << std::endl;
570
}
571
}
572
```
573
574
### Annual Daylight Analysis
575
576
```cpp
577
#include <openstudio/radiance/AnnualIlluminanceMap.hpp>
578
#include <openstudio/radiance/AnnualDaylightMetrics.hpp>
579
580
using namespace openstudio;
581
using namespace openstudio::radiance;
582
583
// Load annual illuminance results (typically generated by external Radiance tools)
584
boost::optional<AnnualIlluminanceMap> annualMap =
585
AnnualIlluminanceMap::load(Path("annual_illuminance.ill"));
586
587
if (annualMap) {
588
// Calculate comprehensive daylight metrics
589
AnnualDaylightMetrics metrics(*annualMap);
590
591
// Generate summary report
592
AnnualDaylightMetrics::DaylightSummary summary = metrics.generateSummary();
593
594
std::cout << "Daylight Performance Summary:" << std::endl;
595
std::cout << " Mean Illuminance: " << summary.mean_illuminance << " lux" << std::endl;
596
std::cout << " Daylight Autonomy (300 lux): " << summary.daylight_autonomy * 100 << "%" << std::endl;
597
std::cout << " Spatial DA (sDA300/50%): " << summary.spatial_daylight_autonomy * 100 << "%" << std::endl;
598
std::cout << " Annual Sunlight Exposure (ASE1000/10%): " << summary.annual_sunlight_exposure * 100 << "%" << std::endl;
599
600
// Check LEED v4 compliance
601
bool leedCompliant = (summary.spatial_daylight_autonomy >= 0.50) &&
602
(summary.annual_sunlight_exposure <= 0.10);
603
604
if (leedCompliant) {
605
std::cout << "✓ LEED v4 daylight requirements met" << std::endl;
606
} else {
607
std::cout << "✗ LEED v4 daylight requirements not met" << std::endl;
608
}
609
610
// Useful Daylight Illuminance analysis
611
AnnualDaylightMetrics::UDIBins udi = metrics.usefulDaylightIlluminance();
612
613
std::cout << "\nUseful Daylight Illuminance:" << std::endl;
614
std::cout << " Fell Short (<100 lux): " << udi.fell_short * 100 << "%" << std::endl;
615
std::cout << " Supplementary (100-300 lux): " << udi.supplementary * 100 << "%" << std::endl;
616
std::cout << " Autonomous (300-3000 lux): " << udi.autonomous * 100 << "%" << std::endl;
617
std::cout << " Exceeded (>3000 lux): " << udi.exceeded * 100 << "%" << std::endl;
618
}
619
```
620
621
### Three-Phase Daylight Method
622
623
```cpp
624
#include <openstudio/radiance/ThreePhaseMethod.hpp>
625
#include <openstudio/radiance/WindowGroup.hpp>
626
627
using namespace openstudio;
628
using namespace openstudio::radiance;
629
630
// Set up three-phase daylight calculation for dynamic shading analysis
631
Model model;
632
// ... create model with windows and shading systems ...
633
634
// Create window groups for coordinated analysis
635
std::vector<SubSurface> southWindows;
636
for (const auto& surface : model.getConcreteModelObjects<Surface>()) {
637
if (surface.azimuth() && std::abs(*surface.azimuth() - 180.0) < 45.0) { // South-facing
638
for (const auto& subSurface : surface.subSurfaces()) {
639
if (subSurface.subSurfaceType() == "FixedWindow" ||
640
subSurface.subSurfaceType() == "OperableWindow") {
641
southWindows.push_back(subSurface);
642
}
643
}
644
}
645
}
646
647
WindowGroup southWindowGroup(southWindows);
648
southWindowGroup.setName("South Windows");
649
650
// Set up three-phase calculation
651
ThreePhaseMethod threePhase;
652
653
// Generate daylight matrices for different shading states
654
RadianceParameters params;
655
params.setAmbientBounces(3);
656
params.setAmbientDivisions(1000);
657
658
// Calculate for clear glazing state
659
southWindowGroup.setWindowGroupConstruction(/* clear glazing construction */);
660
std::vector<Path> clearMatrixFiles = southWindowGroup.generateDaylightMatrix(
661
Path("matrices/clear"), params);
662
663
// Calculate for shaded state
664
southWindowGroup.setWindowGroupConstruction(/* shaded glazing construction */);
665
std::vector<Path> shadedMatrixFiles = southWindowGroup.generateDaylightMatrix(
666
Path("matrices/shaded"), params);
667
668
// Load matrices (in practice, these would be read from generated files)
669
Matrix viewMatrix; // View matrix from sensors to window
670
Matrix daylightMatrixClear; // Daylight matrix for clear state
671
Matrix daylightMatrixShaded; // Daylight matrix for shaded state
672
Matrix skyMatrix; // Annual sky matrix
673
674
// Calculate annual illuminance for both states
675
threePhase.setViewMatrix(viewMatrix);
676
threePhase.setSkyMatrix(skyMatrix);
677
678
// Clear state analysis
679
threePhase.setDaylightMatrix(daylightMatrixClear);
680
Matrix clearIlluminance = threePhase.calculateIlluminance();
681
682
// Shaded state analysis
683
threePhase.setDaylightMatrix(daylightMatrixShaded);
684
Matrix shadedIlluminance = threePhase.calculateIlluminance();
685
686
// Compare results and optimize shading control
687
std::cout << "Clear state annual illuminance calculated" << std::endl;
688
std::cout << "Shaded state annual illuminance calculated" << std::endl;
689
```
690
691
### Daylighting Controls Integration
692
693
```cpp
694
#include <openstudio/model/DaylightingControl.hpp>
695
#include <openstudio/model/Space.hpp>
696
697
using namespace openstudio;
698
using namespace openstudio::model;
699
700
Model model;
701
// ... create model with spaces ...
702
703
// Add daylighting controls to each space
704
for (auto& space : model.getConcreteModelObjects<Space>()) {
705
706
// Only add controls to spaces with significant window area
707
double windowArea = 0.0;
708
for (const auto& surface : space.surfaces()) {
709
for (const auto& subSurface : surface.subSurfaces()) {
710
windowArea += subSurface.grossArea();
711
}
712
}
713
714
if (windowArea > 5.0) { // More than 5 m² of windows
715
716
// Create daylighting control
717
DaylightingControl daylightingControl(model);
718
daylightingControl.setSpace(space);
719
720
// Position at space centroid
721
boost::optional<Point3d> centroid = space.transformation() * space.floorPrint().centroid();
722
if (centroid) {
723
daylightingControl.setPositionXCoordinate(centroid->x());
724
daylightingControl.setPositionYCoordinate(centroid->y());
725
daylightingControl.setPositionZCoordinate(centroid->z() + 0.8); // Desktop height
726
}
727
728
// Configure control parameters
729
daylightingControl.setIlluminanceSetpoint(500.0); // 500 lux target
730
daylightingControl.setLightingControlSteps(3.0); // 3-step dimming
731
daylightingControl.setLightingControlProbability(1.0); // Always respond
732
733
// Set up glare control if space has view to exterior
734
bool hasExteriorView = false;
735
for (const auto& surface : space.surfaces()) {
736
if (surface.outsideBoundaryCondition() == "Outdoors") {
737
for (const auto& subSurface : surface.subSurfaces()) {
738
hasExteriorView = true;
739
break;
740
}
741
}
742
}
743
744
if (hasExteriorView) {
745
daylightingControl.setMaximumAllowableDiscomfortGlareIndex(0.4); // Imperceptible glare
746
daylightingControl.setGlareCalculationAzimuthAngleofViewDirectionClockwisefromZoneyAxis(0.0);
747
}
748
749
std::cout << "Added daylighting control to space: "
750
<< space.name().get_value_or("Unnamed") << std::endl;
751
}
752
}
753
754
// Verify all daylighting controls
755
std::vector<DaylightingControl> controls = model.getConcreteModelObjects<DaylightingControl>();
756
std::cout << "Total daylighting controls: " << controls.size() << std::endl;
757
```