Skip to content

Feat: Optimize collision resolution using depth-based partitioning#264

Open
itvi-1234 wants to merge 7 commits into
ioflux-org:mainfrom
itvi-1234:fix-complexity
Open

Feat: Optimize collision resolution using depth-based partitioning#264
itvi-1234 wants to merge 7 commits into
ioflux-org:mainfrom
itvi-1234:fix-complexity

Conversation

@itvi-1234

@itvi-1234 itvi-1234 commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

Description: This PR optimizes the resolveCollisions algorithm by reducing its time complexity from $O(n^2)$ to $O(k \cdot (n/k)^2)$, where $k$ is the number of columns (depths).

closes issue #240

Changes:
Implemented Depth-Based Partitioning: Instead of comparing every node pair globally, nodes are now grouped into "buckets" based on their depth.
Localized Resolution: Collision checks are only performed between nodes within the same bucket/column.

Summary by CodeRabbit

  • Chores

    • Added release documentation for a patch release.
  • Refactor

    • Optimized collision resolution by grouping elements by depth to reduce pair checks and sort-per-group processing.
    • Preserved iteration limits and early-exit behavior while refining vertical displacement handling for more predictable adjustments.

Signed-off-by: itvi-1234 <rjsumit71@gmail.com>
@coderabbitai

coderabbitai Bot commented Apr 2, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@itvi-1234 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 8 minutes and 47 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 8 minutes and 47 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4be1b00e-a14c-41f8-a938-b85e3060ff8b

📥 Commits

Reviewing files that changed from the base of the PR and between 4014e49 and 574bf38.

📒 Files selected for processing (1)
  • src/utils/resolveCollisions.ts
📝 Walkthrough

Walkthrough

Boxes are bucketed by box.node.depth; collision checks run within same-depth and adjacent-depth buckets via a new resolveBoxPairs helper, and vertical displacement branching was updated. A changeset marks json-schema-studio for a patch release.

Changes

Cohort / File(s) Summary
Release Documentation
\.changeset/little-bushes-pick.md
Adds a patch changeset noting collision-resolution optimization using depth-based partitioning.
Collision Resolution Optimization
src/utils/resolveCollisions.ts
Replaces full all-pairs collision loop with depth-bucketed processing (depthBuckets); limits checks to same and adjacent depths; extracts pair handling into resolveBoxPairs(listA, listB, sameColumn); sorts buckets by y; changes vertical displacement branching and aggregates moved per-bucket while retaining max-iteration/early-exit behavior.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I hop through buckets, depth by depth I peer,
I nudge the tumbled boxes gently, not too near.
A clockwise tweak, a vertical swap of place,
Patch in my paw — collisions find their space.
Thump-thump, I twitch my whiskers: tidy, neat, and clear.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: optimizing collision resolution using depth-based partitioning, which is the primary focus of the changeset.
Description check ✅ Passed The description covers most template sections: includes a clear summary, explains the type of change (optimization), references the issue number (#240), and provides details about the implementation. However, it's missing explicit answers to the template questions about breaking changes and documentation updates.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@itvi-1234

Copy link
Copy Markdown
Contributor Author

@AgniveshChaubey , could you please review it , Lemme know if any changes needed 🚀

@github-actions

github-actions Bot commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

Preview Deployed!

Item Status
Latest Deploy Visit Preview
Environment Preview (PR-264)
Action View Logs

Last updated at 2026-04-03T09:03:04Z

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/utils/resolveCollisions.ts (1)

57-87: Please codify the “depth == collision column” assumption.

This loop now ignores collisions between different depths entirely. That’s safe only if every resolveCollisions caller guarantees distinct depths never share x-space; otherwise adjacent-depth wide nodes can now overlap without ever being separated. A small regression test or inline invariant note here would make that contract explicit.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/resolveCollisions.ts` around lines 57 - 87, The loop assumes boxes
in each depth bucket represent a single collision column; make that contract
explicit and enforced: in resolveCollisions ensure depthBuckets is keyed by node
depth and assert or guard that A.depth === B.depth before computing/handling
overlaps (or throw/log a descriptive error if not), add a small regression test
that creates two wide nodes at adjacent depths with overlapping x-ranges to
verify the assertion triggers (or that callers pre-bucket by depth), and include
an inline comment at the start of the nested loops referencing depthBuckets and
the overlapThreshold to document the invariant; reference symbols:
resolveCollisions, depthBuckets, overlapThreshold, A, B, moved.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/utils/resolveCollisions.ts`:
- Around line 57-87: The loop assumes boxes in each depth bucket represent a
single collision column; make that contract explicit and enforced: in
resolveCollisions ensure depthBuckets is keyed by node depth and assert or guard
that A.depth === B.depth before computing/handling overlaps (or throw/log a
descriptive error if not), add a small regression test that creates two wide
nodes at adjacent depths with overlapping x-ranges to verify the assertion
triggers (or that callers pre-bucket by depth), and include an inline comment at
the start of the nested loops referencing depthBuckets and the overlapThreshold
to document the invariant; reference symbols: resolveCollisions, depthBuckets,
overlapThreshold, A, B, moved.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 64564782-48d7-45ce-9bcc-7ad761f18e0c

📥 Commits

Reviewing files that changed from the base of the PR and between bfb4f1e and 88c1052.

📒 Files selected for processing (2)
  • .changeset/little-bushes-pick.md
  • src/utils/resolveCollisions.ts

@itvi-1234 itvi-1234 marked this pull request as draft April 2, 2026 18:47
@itvi-1234 itvi-1234 marked this pull request as draft April 2, 2026 18:47
Signed-off-by: itvi-1234 <rjsumit71@gmail.com>
@itvi-1234 itvi-1234 marked this pull request as ready for review April 2, 2026 20:10
@itvi-1234 itvi-1234 marked this pull request as draft April 2, 2026 21:20
@itvi-1234 itvi-1234 marked this pull request as draft April 2, 2026 21:20
Signed-off-by: itvi-1234 <rjsumit71@gmail.com>
@itvi-1234 itvi-1234 marked this pull request as ready for review April 3, 2026 08:40
Signed-off-by: itvi-1234 <rjsumit71@gmail.com>
Signed-off-by: itvi-1234 <rjsumit71@gmail.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/utils/resolveCollisions.ts (1)

99-103: Add a comment documenting the depth-based horizontal separation assumption.

The collision resolution algorithm only checks collisions within the same depth bucket and between adjacent depths (lines 103 and 108). This optimization relies on the depth-based X-offset in GraphView.tsx—specifically the formula (NODE_WIDTH + HORIZONTAL_GAP) * node.depth with NODE_WIDTH=172 and HORIZONTAL_GAP=150—which ensures non-adjacent depths are sufficiently separated horizontally (322 pixels apart) to prevent collisions. While this assumption is mathematically sound, documenting it in the code will help future maintainers understand the implicit coupling between this collision resolution strategy and the layout pipeline.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/resolveCollisions.ts` around lines 99 - 103, Add a clarifying
comment near the depth-based collision logic around depthBuckets and
resolveBoxPairs explaining the optimization: mention that collisions are only
checked within the same depth bucket and between adjacent depths because
GraphView.tsx uses an X-offset of (NODE_WIDTH + HORIZONTAL_GAP) * node.depth
(with NODE_WIDTH=172 and HORIZONTAL_GAP=150), which guarantees non-adjacent
depths are at least 322px apart and cannot collide; reference depthBuckets,
resolveBoxPairs, GraphView.tsx, NODE_WIDTH and HORIZONTAL_GAP in the comment so
future maintainers know this function relies on that layout assumption.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/utils/resolveCollisions.ts`:
- Line 91: The for-loop in resolveCollisions.ts inside the resolveCollisions
function uses "for (let iter = 0; iter <= maxIterations; iter++)" causing one
extra iteration; change the loop condition to stop after maxIterations
iterations (e.g., use "iter < maxIterations") or rename the parameter to reflect
the inclusive behavior, and update any callers/tests if needed so the function
performs exactly maxIterations iterations; ensure the unique symbol "iter" and
the loop in resolveCollisions are adjusted consistently.

---

Nitpick comments:
In `@src/utils/resolveCollisions.ts`:
- Around line 99-103: Add a clarifying comment near the depth-based collision
logic around depthBuckets and resolveBoxPairs explaining the optimization:
mention that collisions are only checked within the same depth bucket and
between adjacent depths because GraphView.tsx uses an X-offset of (NODE_WIDTH +
HORIZONTAL_GAP) * node.depth (with NODE_WIDTH=172 and HORIZONTAL_GAP=150), which
guarantees non-adjacent depths are at least 322px apart and cannot collide;
reference depthBuckets, resolveBoxPairs, GraphView.tsx, NODE_WIDTH and
HORIZONTAL_GAP in the comment so future maintainers know this function relies on
that layout assumption.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d1aa6157-a1ff-48f2-9a45-43b18c7d9ca0

📥 Commits

Reviewing files that changed from the base of the PR and between 0a838f1 and 0a6f311.

📒 Files selected for processing (1)
  • src/utils/resolveCollisions.ts

Comment thread src/utils/resolveCollisions.ts Outdated
Signed-off-by: itvi-1234 <rjsumit71@gmail.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/utils/resolveCollisions.ts (1)

96-96: ⚠️ Potential issue | 🟡 Minor

Loop still runs maxIterations + 1 passes.

Line 96 uses iter <= maxIterations, so maxIterations: 0 still performs one relaxation pass and every other value gets one extra iteration.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/resolveCollisions.ts` at line 96, The for-loop in resolveCollisions
uses "for (let iter = 0; iter <= maxIterations; iter++)" which makes it run one
extra pass (maxIterations + 1); change the loop condition to "iter <
maxIterations" (or adjust the initialization if you want 1-based counts) so that
when maxIterations is 0 no relaxation pass runs. Update the loop condition
referencing iter and maxIterations inside the resolveCollisions function
accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/utils/resolveCollisions.ts`:
- Around line 47-52: The current depth-bucketing in resolveCollisions groups
boxes by box.node.depth and only compares a bucket with depth+1, which misses
geometric overlaps when a wide box spans further depths; update the collision
resolution in resolveCollisions (the depthBuckets Map logic and the loop that
compares buckets around lines where depthBuckets is used) to first compute each
box's x-range from its x/width and only compare buckets whose overall x-ranges
intersect (i.e., gate comparisons by actual x-range overlap rather than assuming
only depth+1 can collide), expanding the neighbor-depth checks when ranges
overlap; also apply the same fix to the similar logic around the other
occurrence (the code noted at 99-109) and add a regression test that constructs
a wide node spanning depth+2 to assert it gets collision-resolved.

---

Duplicate comments:
In `@src/utils/resolveCollisions.ts`:
- Line 96: The for-loop in resolveCollisions uses "for (let iter = 0; iter <=
maxIterations; iter++)" which makes it run one extra pass (maxIterations + 1);
change the loop condition to "iter < maxIterations" (or adjust the
initialization if you want 1-based counts) so that when maxIterations is 0 no
relaxation pass runs. Update the loop condition referencing iter and
maxIterations inside the resolveCollisions function accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2d2b7be4-41c7-48cd-bb4f-ba6fa5abbd8f

📥 Commits

Reviewing files that changed from the base of the PR and between 0a6f311 and 4014e49.

📒 Files selected for processing (1)
  • src/utils/resolveCollisions.ts

Comment thread src/utils/resolveCollisions.ts
Signed-off-by: itvi-1234 <rjsumit71@gmail.com>
@itvi-1234

Copy link
Copy Markdown
Contributor Author

Hey agnivesh , Also In simple words let's Imagine a classroom with 60 students. Previously, we were comparing every student against all other 59 students to check for space, even if they were sitting in the first row and the other was in the last. This led to thousands of unnecessary calculations (O(n²) complexity), causing the UI to lag significantly on large schemas.
Now, we have partitioned nodes into vertical columns (Buckets) based on their depth. we first resolve collisions between nodes in the same column. ans only compare column 1 with column 2 (or beyond) if their X-coordinate boundaries actually touch or overlap.

Why it’s better: Instead of blindly checking every pair, the algorithm now skips calculations for nodes that are horizontally far apart. It only does the heavy lifting when nodes are geometrically close enough to actually collide.
which makes it 5x - 10x faster.

@itvi-1234

Copy link
Copy Markdown
Contributor Author

Hey agnivesh , any direction or views regarding this PR

@AgniveshChaubey

AgniveshChaubey commented Apr 5, 2026

Copy link
Copy Markdown
Member

Hi, reviewing this would be a bit time consuming as I myself have to thoroughly go through it first... since I just copy pasted it previously. I'm calling it a day for now, so, I'll check this by next weekend.

@itvi-1234

itvi-1234 commented Apr 5, 2026

Copy link
Copy Markdown
Contributor Author

let’s connect next weekend. 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants