php-tui / cassowary
Cassowary 约束求解算法实现
0.1.0
2023-10-23 16:11 UTC
Requires
- php: ^8.1
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.34
- phpbench/phpbench: ^1.2
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.4
- symfony/var-dumper: ^6.3
README
Cassowary 约束求解算法的实现。在大量借鉴 cassowary-rs 的基础上,而 cassowary-rs 又是基于 kiwi 开发的。
此库可用于指定和解决用户界面的约束。
状态
我只将足够的代码移植以支持求解约束。我没有移植对编辑变量或更改约束的支持。欢迎PR。
安装
$ composer require phptui/cassowary
它做什么?
假设我们想在定义大小的屏幕上渲染布局。布局有两个部分
+-------+-------------------+
| A | B |
+-------+-------------------+
我们需要为部分 a
和 b
中的每个点引入变量
0 30
ax1 ax2,bx1 bx2
0 y1 +-------+-------------------+
| | |
2 y2 +-------+-------------------+
然后指定必须保持的约束
ax1 = 0 // the left-most point is CONSTANT at 0
ax2 >= ax1 // ax2 is REQUIRED to be greater than equal to ax1
ax2 >= ax1 + 10 // ax2 must have a WEAK requirement to be greater than equal to ax1 plus 10
bx1 = ax2 // bx1 and bx2 are REQUIRED to be contiguous
bx2 = 30 // bx2 is REQUIRED be at the right-most point - 30
// etc
有两件有趣的事情
- 约束可以相互关联
- 约束有 强度,这决定了在存在冲突时考虑哪个约束。
约束求解器能够将这些约束解决为最优解。
用法
使用上述示例
<?php require __DIR__ . '/vendor/autoload.php'; use PhpTui\Cassowary\AddConstraintaintError; use PhpTui\Cassowary\Constraint; use PhpTui\Cassowary\RelationalOperator; use PhpTui\Cassowary\Solver; use PhpTui\Cassowary\Strength; use PhpTui\Cassowary\Variable; $ax1 = Variable::new(); $ax2 = Variable::new(); $bx1 = Variable::new(); $bx2 = Variable::new(); $y1 = Variable::new(); $y2 = Variable::new(); $s = Solver::new(); $s->addConstraints([ Constraint::equalTo($ax1, 0.0, Strength::REQUIRED), Constraint::greaterThanOrEqualTo($ax2, $ax1, Strength::REQUIRED), Constraint::greaterThanOrEqualTo($ax2, $ax1->add(10.0), Strength::WEAK), Constraint::equalTo($bx1, $ax2, Strength::REQUIRED), Constraint::equalTo($bx2, 30.0, Strength::REQUIRED), Constraint::equalTo($y1, 0.0, Strength::REQUIRED), Constraint::equalTo($y2, 3.0, Strength::REQUIRED), ]); $changes = $s->fetchChanges(); var_dump($changes->getValue($ax2)); // 10 var_dump($changes->getValue($bx1); // 10 var_dump($changes->getValue($bx2)); // 30 var_dump($changes->getValue($y2)); // 3
注意
$changes
只包含已更改的值,并且默认情况下变量从 0.0 开始。此API更适用于变量可以更新时。
它是如何工作的?
我不知道,但它确实做到了!我只是带着极大的决心将代码移植并调试,直到它工作。
您可以在这里阅读论文。