elkrb 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +11 -0
- data/Gemfile +13 -0
- data/README.adoc +1028 -0
- data/Rakefile +64 -0
- data/benchmarks/README.md +172 -0
- data/benchmarks/elkjs_benchmark.js +140 -0
- data/benchmarks/elkrb_benchmark.rb +145 -0
- data/benchmarks/fixtures/graphs.json +10777 -0
- data/benchmarks/generate_report.rb +241 -0
- data/benchmarks/generate_test_graphs.rb +154 -0
- data/benchmarks/results/elkrb_results.json +280 -0
- data/benchmarks/results/elkrb_summary.json +285 -0
- data/elkrb.gemspec +39 -0
- data/examples/dot_export_demo.rb +133 -0
- data/examples/hierarchical_graph.rb +19 -0
- data/examples/layout_constraints_demo.rb +272 -0
- data/examples/port_constraints_demo.rb +291 -0
- data/examples/self_loop_demo.rb +391 -0
- data/examples/simple_graph.rb +50 -0
- data/examples/spline_routing_demo.rb +235 -0
- data/exe/elkrb +8 -0
- data/lib/elkrb/cli.rb +224 -0
- data/lib/elkrb/commands/batch_command.rb +66 -0
- data/lib/elkrb/commands/convert_command.rb +130 -0
- data/lib/elkrb/commands/diagram_command.rb +208 -0
- data/lib/elkrb/commands/render_command.rb +52 -0
- data/lib/elkrb/commands/validate_command.rb +241 -0
- data/lib/elkrb/errors.rb +30 -0
- data/lib/elkrb/geometry/bezier.rb +163 -0
- data/lib/elkrb/geometry/dimension.rb +32 -0
- data/lib/elkrb/geometry/point.rb +68 -0
- data/lib/elkrb/geometry/rectangle.rb +86 -0
- data/lib/elkrb/geometry/vector.rb +67 -0
- data/lib/elkrb/graph/edge.rb +95 -0
- data/lib/elkrb/graph/graph.rb +90 -0
- data/lib/elkrb/graph/label.rb +45 -0
- data/lib/elkrb/graph/layout_options.rb +247 -0
- data/lib/elkrb/graph/node.rb +79 -0
- data/lib/elkrb/graph/node_constraints.rb +107 -0
- data/lib/elkrb/graph/port.rb +104 -0
- data/lib/elkrb/graphviz_wrapper.rb +133 -0
- data/lib/elkrb/layout/algorithm_registry.rb +57 -0
- data/lib/elkrb/layout/algorithms/base_algorithm.rb +208 -0
- data/lib/elkrb/layout/algorithms/box.rb +47 -0
- data/lib/elkrb/layout/algorithms/disco.rb +206 -0
- data/lib/elkrb/layout/algorithms/fixed.rb +32 -0
- data/lib/elkrb/layout/algorithms/force.rb +165 -0
- data/lib/elkrb/layout/algorithms/layered/cycle_breaker.rb +86 -0
- data/lib/elkrb/layout/algorithms/layered/layer_assigner.rb +96 -0
- data/lib/elkrb/layout/algorithms/layered/node_placer.rb +77 -0
- data/lib/elkrb/layout/algorithms/layered.rb +49 -0
- data/lib/elkrb/layout/algorithms/libavoid.rb +389 -0
- data/lib/elkrb/layout/algorithms/mrtree.rb +144 -0
- data/lib/elkrb/layout/algorithms/radial.rb +64 -0
- data/lib/elkrb/layout/algorithms/random.rb +43 -0
- data/lib/elkrb/layout/algorithms/rectpacking.rb +93 -0
- data/lib/elkrb/layout/algorithms/spore_compaction.rb +139 -0
- data/lib/elkrb/layout/algorithms/spore_overlap.rb +117 -0
- data/lib/elkrb/layout/algorithms/stress.rb +176 -0
- data/lib/elkrb/layout/algorithms/topdown_packing.rb +183 -0
- data/lib/elkrb/layout/algorithms/vertiflex.rb +174 -0
- data/lib/elkrb/layout/constraints/alignment_constraint.rb +150 -0
- data/lib/elkrb/layout/constraints/base_constraint.rb +72 -0
- data/lib/elkrb/layout/constraints/constraint_processor.rb +134 -0
- data/lib/elkrb/layout/constraints/fixed_position_constraint.rb +87 -0
- data/lib/elkrb/layout/constraints/layer_constraint.rb +71 -0
- data/lib/elkrb/layout/constraints/relative_position_constraint.rb +110 -0
- data/lib/elkrb/layout/edge_router.rb +935 -0
- data/lib/elkrb/layout/hierarchical_processor.rb +299 -0
- data/lib/elkrb/layout/label_placer.rb +338 -0
- data/lib/elkrb/layout/layout_engine.rb +170 -0
- data/lib/elkrb/layout/port_constraint_processor.rb +173 -0
- data/lib/elkrb/options/elk_padding.rb +94 -0
- data/lib/elkrb/options/k_vector.rb +100 -0
- data/lib/elkrb/options/k_vector_chain.rb +135 -0
- data/lib/elkrb/parsers/elkt_parser.rb +248 -0
- data/lib/elkrb/serializers/dot_serializer.rb +339 -0
- data/lib/elkrb/serializers/elkt_serializer.rb +236 -0
- data/lib/elkrb/version.rb +5 -0
- data/lib/elkrb.rb +509 -0
- data/sig/elkrb/constraints.rbs +114 -0
- data/sig/elkrb/geometry.rbs +61 -0
- data/sig/elkrb/graph.rbs +112 -0
- data/sig/elkrb/layout.rbs +107 -0
- data/sig/elkrb/options.rbs +81 -0
- data/sig/elkrb.rbs +32 -0
- metadata +179 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base_constraint"
|
|
4
|
+
|
|
5
|
+
module Elkrb
|
|
6
|
+
module Layout
|
|
7
|
+
module Constraints
|
|
8
|
+
# Relative position constraint
|
|
9
|
+
#
|
|
10
|
+
# Positions a node relative to another node with a specified offset.
|
|
11
|
+
# The constrained node will be positioned at:
|
|
12
|
+
# x = reference_node.x + offset.x
|
|
13
|
+
# y = reference_node.y + offset.y
|
|
14
|
+
#
|
|
15
|
+
# @example
|
|
16
|
+
# api_node.constraints = NodeConstraints.new(
|
|
17
|
+
# relative_to: "backend_service",
|
|
18
|
+
# relative_offset: RelativeOffset.new(x: 150, y: 0)
|
|
19
|
+
# )
|
|
20
|
+
# # api_node will be 150px to the right of backend_service
|
|
21
|
+
class RelativePositionConstraint < BaseConstraint
|
|
22
|
+
# Apply relative position constraint
|
|
23
|
+
#
|
|
24
|
+
# Positions nodes relative to their reference nodes.
|
|
25
|
+
# Processes in order of position_priority to handle chains.
|
|
26
|
+
#
|
|
27
|
+
# @param graph [Graph::Graph] The graph
|
|
28
|
+
# @return [Graph::Graph] The modified graph
|
|
29
|
+
def apply(graph)
|
|
30
|
+
nodes_with_relative = all_nodes(graph).select do |node|
|
|
31
|
+
node.constraints&.relative_to &&
|
|
32
|
+
node.constraints.relative_offset
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Sort by priority (higher priority processed first)
|
|
36
|
+
nodes_with_relative.sort_by! do |node|
|
|
37
|
+
-(node.constraints.position_priority || 0)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Apply relative positioning
|
|
41
|
+
nodes_with_relative.each do |node|
|
|
42
|
+
apply_relative_position(node, graph)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
graph
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Validate relative position constraints
|
|
49
|
+
#
|
|
50
|
+
# Checks that reference nodes exist and positions are correct.
|
|
51
|
+
#
|
|
52
|
+
# @param graph [Graph::Graph] The graph to validate
|
|
53
|
+
# @return [Array<String>] List of validation errors
|
|
54
|
+
def validate(graph)
|
|
55
|
+
errors = []
|
|
56
|
+
|
|
57
|
+
all_nodes(graph).each do |node|
|
|
58
|
+
next unless node.constraints&.relative_to
|
|
59
|
+
|
|
60
|
+
ref_id = node.constraints.relative_to
|
|
61
|
+
ref_node = find_node(graph, ref_id)
|
|
62
|
+
|
|
63
|
+
if ref_node.nil?
|
|
64
|
+
errors << "Node '#{node.id}' has relative_to constraint " \
|
|
65
|
+
"referencing '#{ref_id}' which doesn't exist"
|
|
66
|
+
next
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Validate position if offset is specified
|
|
70
|
+
if node.constraints.relative_offset
|
|
71
|
+
expected_x = ref_node.x + node.constraints.relative_offset.x
|
|
72
|
+
expected_y = ref_node.y + node.constraints.relative_offset.y
|
|
73
|
+
|
|
74
|
+
tolerance = 0.01
|
|
75
|
+
if (node.x - expected_x).abs > tolerance ||
|
|
76
|
+
(node.y - expected_y).abs > tolerance
|
|
77
|
+
errors << "Node '#{node.id}' relative position incorrect. " \
|
|
78
|
+
"Expected (#{expected_x}, #{expected_y}), " \
|
|
79
|
+
"got (#{node.x}, #{node.y})"
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
errors
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
private
|
|
88
|
+
|
|
89
|
+
# Apply relative position to a single node
|
|
90
|
+
def apply_relative_position(node, graph)
|
|
91
|
+
ref_id = node.constraints.relative_to
|
|
92
|
+
ref_node = find_node(graph, ref_id)
|
|
93
|
+
|
|
94
|
+
unless ref_node
|
|
95
|
+
warn "Warning: Node '#{node.id}' references non-existent " \
|
|
96
|
+
"node '#{ref_id}' for relative positioning"
|
|
97
|
+
return
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
offset = node.constraints.relative_offset
|
|
101
|
+
return unless offset
|
|
102
|
+
|
|
103
|
+
# Calculate and set new position
|
|
104
|
+
node.x = ref_node.x + offset.x
|
|
105
|
+
node.y = ref_node.y + offset.y
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|