@@ -268,3 +268,152 @@ TEST_F(GeometryTests, copyBuffers_mixedCellsAndParticles)
268268 EXPECT_EQ (2u , numObjects.cells );
269269 EXPECT_EQ (3u , numObjects.energyParticles );
270270}
271+
272+ // Signal restriction tests for cudaExtractSelectedObjectData
273+
274+ TEST_F (GeometryTests, selectedObjectData_noRestriction_inactive)
275+ {
276+ auto cell = CellDescription ().id (1 ).pos ({100 .0f , 100 .0f });
277+ cell._signalRestriction ._mode = SignalRestrictionMode_Inactive;
278+ cell._signalRestriction ._baseAngle = 45 .0f ;
279+ cell._signalRestriction ._openingAngle = 90 .0f ;
280+
281+ auto data = Description ().cells ({
282+ cell,
283+ CellDescription ().id (2 ).pos ({101 .0f , 100 .0f }),
284+ });
285+ data.addConnection (1 , 2 );
286+ _simulationFacade->setSimulationData (data);
287+
288+ // Select cell 1 using position-based selection
289+ _simulationFacade->setSelection ({99 .0f , 99 .0f }, {100 .5f , 101 .0f });
290+
291+ auto selectedData = _simulationFacade->testOnly_getSelectedObjectData ();
292+ ASSERT_EQ (1u , selectedData.size ());
293+ EXPECT_EQ (0 , selectedData[0 ].hasSignalRestriction ); // Inactive mode = no restriction
294+ }
295+
296+ TEST_F (GeometryTests, selectedObjectData_hasRestriction_active)
297+ {
298+ auto cell = CellDescription ().id (1 ).pos ({100 .0f , 100 .0f });
299+ cell._signalRestriction ._mode = SignalRestrictionMode_Active;
300+ cell._signalRestriction ._baseAngle = 45 .0f ;
301+ cell._signalRestriction ._openingAngle = 90 .0f ;
302+
303+ auto data = Description ().cells ({
304+ cell,
305+ CellDescription ().id (2 ).pos ({101 .0f , 100 .0f }),
306+ });
307+ data.addConnection (1 , 2 );
308+ _simulationFacade->setSimulationData (data);
309+
310+ // Select cell 1 using position-based selection
311+ _simulationFacade->setSelection ({99 .0f , 99 .0f }, {100 .5f , 101 .0f });
312+
313+ auto selectedData = _simulationFacade->testOnly_getSelectedObjectData ();
314+ ASSERT_EQ (1u , selectedData.size ());
315+ EXPECT_EQ (1 , selectedData[0 ].hasSignalRestriction ); // Active mode = has restriction
316+ }
317+
318+ TEST_F (GeometryTests, selectedObjectData_hasRestriction_conditional)
319+ {
320+ auto cell = CellDescription ().id (1 ).pos ({100 .0f , 100 .0f });
321+ cell._signalRestriction ._mode = SignalRestrictionMode_Conditional;
322+ cell._signalRestriction ._baseAngle = 45 .0f ;
323+ cell._signalRestriction ._openingAngle = 90 .0f ;
324+
325+ auto data = Description ().cells ({
326+ cell,
327+ CellDescription ().id (2 ).pos ({101 .0f , 100 .0f }),
328+ });
329+ data.addConnection (1 , 2 );
330+ _simulationFacade->setSimulationData (data);
331+
332+ // Select cell 1 using position-based selection
333+ _simulationFacade->setSelection ({99 .0f , 99 .0f }, {100 .5f , 101 .0f });
334+
335+ auto selectedData = _simulationFacade->testOnly_getSelectedObjectData ();
336+ ASSERT_EQ (1u , selectedData.size ());
337+ EXPECT_EQ (1 , selectedData[0 ].hasSignalRestriction ); // Conditional mode = has restriction
338+ }
339+
340+ // Signal restriction tests for cudaExtractSelectedConnectionData
341+
342+ TEST_F (GeometryTests, connectionData_noRestriction_inactive_bothDirections)
343+ {
344+ auto cell1 = CellDescription ().id (1 ).pos ({100 .0f , 100 .0f });
345+ cell1._signalRestriction ._mode = SignalRestrictionMode_Inactive;
346+
347+ auto cell2 = CellDescription ().id (2 ).pos ({101 .0f , 100 .0f });
348+ cell2._signalRestriction ._mode = SignalRestrictionMode_Inactive;
349+
350+ auto data = Description ().cells ({cell1, cell2});
351+ data.addConnection (1 , 2 );
352+ _simulationFacade->setSimulationData (data);
353+
354+ // Select both cells using position-based selection
355+ _simulationFacade->setSelection ({99 .0f , 99 .0f }, {102 .0f , 101 .0f });
356+
357+ auto connectionData = _simulationFacade->testOnly_getConnectionArrowData ();
358+ ASSERT_EQ (2u , connectionData.size ()); // 2 vertices per connection line
359+ // arrowFlags: bit 0 = arrow to cell1, bit 1 = arrow to cell2
360+ // Both cells have no restriction, so signals can flow both ways (flags = 3)
361+ EXPECT_EQ (3 , connectionData[0 ].arrowFlags );
362+ EXPECT_EQ (3 , connectionData[1 ].arrowFlags );
363+ }
364+
365+ TEST_F (GeometryTests, connectionData_withRestriction_active_restrictedDirection)
366+ {
367+ auto cell1 = CellDescription ().id (1 ).pos ({100 .0f , 100 .0f });
368+ cell1._signalRestriction ._mode = SignalRestrictionMode_Active;
369+ // Use baseAngle = 90 and openingAngle = 90 to point away from connection
370+ // Connection angle is 0 (first connection), so range [45+180, 135+180] = [225, 315] doesn't include 0
371+ cell1._signalRestriction ._baseAngle = 90 .0f ;
372+ cell1._signalRestriction ._openingAngle = 90 .0f ;
373+
374+ auto cell2 = CellDescription ().id (2 ).pos ({101 .0f , 100 .0f });
375+ cell2._signalRestriction ._mode = SignalRestrictionMode_Inactive;
376+
377+ auto data = Description ().cells ({cell1, cell2});
378+ data.addConnection (1 , 2 );
379+ _simulationFacade->setSimulationData (data);
380+
381+ // Select both cells using position-based selection
382+ _simulationFacade->setSelection ({99 .0f , 99 .0f }, {102 .0f , 101 .0f });
383+
384+ auto connectionData = _simulationFacade->testOnly_getConnectionArrowData ();
385+ ASSERT_EQ (2u , connectionData.size ());
386+ // Cell1 has restriction that blocks signal to cell2 (connection angle 0 is outside range [225,315])
387+ // Cell2 has no restriction, so signal can flow to cell1
388+ // Expected: arrow to cell1 (bit 0 = 1), no arrow to cell2 (bit 1 = 0) => flags = 1
389+ EXPECT_EQ (1 , connectionData[0 ].arrowFlags );
390+ EXPECT_EQ (1 , connectionData[1 ].arrowFlags );
391+ }
392+
393+ TEST_F (GeometryTests, connectionData_withRestriction_conditional_restrictedDirection)
394+ {
395+ auto cell1 = CellDescription ().id (1 ).pos ({100 .0f , 100 .0f });
396+ cell1._signalRestriction ._mode = SignalRestrictionMode_Conditional;
397+ // Use baseAngle = 90 and openingAngle = 90 to point away from connection
398+ cell1._signalRestriction ._baseAngle = 90 .0f ;
399+ cell1._signalRestriction ._openingAngle = 90 .0f ;
400+
401+ auto cell2 = CellDescription ().id (2 ).pos ({101 .0f , 100 .0f });
402+ cell2._signalRestriction ._mode = SignalRestrictionMode_Inactive;
403+
404+ auto data = Description ().cells ({cell1, cell2});
405+ data.addConnection (1 , 2 );
406+ _simulationFacade->setSimulationData (data);
407+
408+ // Select both cells using position-based selection
409+ _simulationFacade->setSelection ({99 .0f , 99 .0f }, {102 .0f , 101 .0f });
410+
411+ auto connectionData = _simulationFacade->testOnly_getConnectionArrowData ();
412+ ASSERT_EQ (2u , connectionData.size ());
413+ // Conditional mode should render the same as Active mode for arrow directions
414+ // Cell1 has restriction that blocks signal to cell2
415+ // Cell2 has no restriction, so signal can flow to cell1
416+ // Expected: arrow to cell1 (bit 0 = 1), no arrow to cell2 (bit 1 = 0) => flags = 1
417+ EXPECT_EQ (1 , connectionData[0 ].arrowFlags );
418+ EXPECT_EQ (1 , connectionData[1 ].arrowFlags );
419+ }
0 commit comments