or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

energyplus.mdindex.mdmeasure.mdmodel.mdradiance.mdutilities.mdworkflow.md

radiance.mddocs/

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

```