Skip to content

Add a broadcasting rotation method - #50

Open
bcbnz wants to merge 1 commit into
moble:mainfrom
bcbnz:rotate_broadcast
Open

Add a broadcasting rotation method#50
bcbnz wants to merge 1 commit into
moble:mainfrom
bcbnz:rotate_broadcast

Conversation

@bcbnz

Copy link
Copy Markdown
Contributor

This pull request adds a quat.rotate_broadcast(vecs) method. Standard NumPy broadcasting rules are used to determine the shape of its output. This means that for an Nx4 quaternionic array and an Nx3 vector array, an Nx3 rotated vector array will be output. This is in contrast to the existing .rotate() method which operates as an outer product and would return an NxNx3 rotated vector array.

My initial use case for this is using this for coordinate transforms. If we have a series of poses stored as Nx3 positions and Nx4 quaternions, the result of rotating vectors as part of changing coordinate systems should be Nx3.

Note that I have implemented this with the standard q * v * q.inverse method as some benchmarking indicated this was faster than the Euler-Rodrigues formula given in the docstring of .rotate except for small numbers of rotations. I have uploaded the benchmark script I wrote to https://gist.github.com/bcbnz/72ccebe4cc3d6e5ad3666953bfe3c6d5 and a subset of the generated images are below. The benchmark also asserts the results are allclose with each other and with the existing .rotate() (either fully if the output shapes are the same, or on the first quaternion & vector if not). The benchmarked functions did not include the error checking included in the pull request.

Nx4, 1x3
Nx4, Nx3
Nx10x4, Nx10x3

The unit tests compare results against the .rotate method. In simple cases, these will have the same shape. In the other cases, we can compare with the diagonal vector components.

I have not mentioned the new method in the docstring of .rotate as I wasn't sure what to do with its comments about the alternative method. I am happy to add a commit or do a force push modifying it with some guidance on the appropriate changes, or you are of course welcome to do so yourself (I have set the 'allow edits by maintainers' option in this pull request).

This uses standard NumPy broadcasting rules. This means that for an Nx4
quaternionic array and an Nx3 vector array, an Nx3 rotated vector array
will be output. This is in contrast to the existing rotate() method
which operates as an outer product and would return an NxNx3 rotated
vector array.
@codecov

codecovBot commented Feb 14, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.92%. Comparing base (cd82c6c) to head (c1c0a01).
⚠️ Report is 10 commits behind head on main.

Additional details and impacted files
@@ Coverage Diff @@## main #50 +/- ##
==========================================
+ Coverage 97.90% 97.92% +0.01% 
==========================================
Files 10 10 Lines 1098 1107 +9 Branches 118 120 +2 ==========================================
+ Hits 1075 1084 +9 
Misses 21 21 Partials 2 2 

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for freeto 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

@bcbnz@bcb-hsu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Add a broadcasting rotation method by bcbnz · Pull Request #50 · moble/quaternionic · GitHub
Skip to content

Add a broadcasting rotation method - #50

Open
bcbnz wants to merge 1 commit into
moble:mainfrom
bcbnz:rotate_broadcast
Open

Add a broadcasting rotation method#50
bcbnz wants to merge 1 commit into
moble:mainfrom
bcbnz:rotate_broadcast

Conversation

@bcbnz

Copy link
Copy Markdown
Contributor

This pull request adds a quat.rotate_broadcast(vecs) method. Standard NumPy broadcasting rules are used to determine the shape of its output. This means that for an Nx4 quaternionic array and an Nx3 vector array, an Nx3 rotated vector array will be output. This is in contrast to the existing .rotate() method which operates as an outer product and would return an NxNx3 rotated vector array.

My initial use case for this is using this for coordinate transforms. If we have a series of poses stored as Nx3 positions and Nx4 quaternions, the result of rotating vectors as part of changing coordinate systems should be Nx3.

Note that I have implemented this with the standard q * v * q.inverse method as some benchmarking indicated this was faster than the Euler-Rodrigues formula given in the docstring of .rotate except for small numbers of rotations. I have uploaded the benchmark script I wrote to https://gist.github.com/bcbnz/72ccebe4cc3d6e5ad3666953bfe3c6d5 and a subset of the generated images are below. The benchmark also asserts the results are allclose with each other and with the existing .rotate() (either fully if the output shapes are the same, or on the first quaternion & vector if not). The benchmarked functions did not include the error checking included in the pull request.

Nx4, 1x3
Nx4, Nx3
Nx10x4, Nx10x3

The unit tests compare results against the .rotate method. In simple cases, these will have the same shape. In the other cases, we can compare with the diagonal vector components.

I have not mentioned the new method in the docstring of .rotate as I wasn't sure what to do with its comments about the alternative method. I am happy to add a commit or do a force push modifying it with some guidance on the appropriate changes, or you are of course welcome to do so yourself (I have set the 'allow edits by maintainers' option in this pull request).

This uses standard NumPy broadcasting rules. This means that for an Nx4
quaternionic array and an Nx3 vector array, an Nx3 rotated vector array
will be output. This is in contrast to the existing rotate() method
which operates as an outer product and would return an NxNx3 rotated
vector array.
@codecov

codecovBot commented Feb 14, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.92%. Comparing base (cd82c6c) to head (c1c0a01).
⚠️ Report is 10 commits behind head on main.

Additional details and impacted files
@@ Coverage Diff @@## main #50 +/- ##
==========================================
+ Coverage 97.90% 97.92% +0.01% 
==========================================
Files 10 10 Lines 1098 1107 +9 Branches 118 120 +2 ==========================================
+ Hits 1075 1084 +9 
Misses 21 21 Partials 2 2 

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for freeto 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

@bcbnz@bcb-hsu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Add a broadcasting rotation method by bcbnz · Pull Request #50 · moble/quaternionic · GitHub
Skip to content

Add a broadcasting rotation method - #50

Open
bcbnz wants to merge 1 commit into
moble:mainfrom
bcbnz:rotate_broadcast
Open

Add a broadcasting rotation method#50
bcbnz wants to merge 1 commit into
moble:mainfrom
bcbnz:rotate_broadcast

Conversation

@bcbnz

Copy link
Copy Markdown
Contributor

This pull request adds a quat.rotate_broadcast(vecs) method. Standard NumPy broadcasting rules are used to determine the shape of its output. This means that for an Nx4 quaternionic array and an Nx3 vector array, an Nx3 rotated vector array will be output. This is in contrast to the existing .rotate() method which operates as an outer product and would return an NxNx3 rotated vector array.

My initial use case for this is using this for coordinate transforms. If we have a series of poses stored as Nx3 positions and Nx4 quaternions, the result of rotating vectors as part of changing coordinate systems should be Nx3.

Note that I have implemented this with the standard q * v * q.inverse method as some benchmarking indicated this was faster than the Euler-Rodrigues formula given in the docstring of .rotate except for small numbers of rotations. I have uploaded the benchmark script I wrote to https://gist.github.com/bcbnz/72ccebe4cc3d6e5ad3666953bfe3c6d5 and a subset of the generated images are below. The benchmark also asserts the results are allclose with each other and with the existing .rotate() (either fully if the output shapes are the same, or on the first quaternion & vector if not). The benchmarked functions did not include the error checking included in the pull request.

Nx4, 1x3
Nx4, Nx3
Nx10x4, Nx10x3

The unit tests compare results against the .rotate method. In simple cases, these will have the same shape. In the other cases, we can compare with the diagonal vector components.

I have not mentioned the new method in the docstring of .rotate as I wasn't sure what to do with its comments about the alternative method. I am happy to add a commit or do a force push modifying it with some guidance on the appropriate changes, or you are of course welcome to do so yourself (I have set the 'allow edits by maintainers' option in this pull request).

This uses standard NumPy broadcasting rules. This means that for an Nx4
quaternionic array and an Nx3 vector array, an Nx3 rotated vector array
will be output. This is in contrast to the existing rotate() method
which operates as an outer product and would return an NxNx3 rotated
vector array.
@codecov

codecovBot commented Feb 14, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.92%. Comparing base (cd82c6c) to head (c1c0a01).
⚠️ Report is 10 commits behind head on main.

Additional details and impacted files
@@ Coverage Diff @@## main #50 +/- ##
==========================================
+ Coverage 97.90% 97.92% +0.01% 
==========================================
Files 10 10 Lines 1098 1107 +9 Branches 118 120 +2 ==========================================
+ Hits 1075 1084 +9 
Misses 21 21 Partials 2 2 

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for freeto 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

@bcbnz@bcb-hsu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Add a broadcasting rotation method by bcbnz · Pull Request #50 · moble/quaternionic · GitHub
Skip to content

Add a broadcasting rotation method - #50

Open
bcbnz wants to merge 1 commit into
moble:mainfrom
bcbnz:rotate_broadcast
Open

Add a broadcasting rotation method#50
bcbnz wants to merge 1 commit into
moble:mainfrom
bcbnz:rotate_broadcast

Conversation

@bcbnz

Copy link
Copy Markdown
Contributor

This pull request adds a quat.rotate_broadcast(vecs) method. Standard NumPy broadcasting rules are used to determine the shape of its output. This means that for an Nx4 quaternionic array and an Nx3 vector array, an Nx3 rotated vector array will be output. This is in contrast to the existing .rotate() method which operates as an outer product and would return an NxNx3 rotated vector array.

My initial use case for this is using this for coordinate transforms. If we have a series of poses stored as Nx3 positions and Nx4 quaternions, the result of rotating vectors as part of changing coordinate systems should be Nx3.

Note that I have implemented this with the standard q * v * q.inverse method as some benchmarking indicated this was faster than the Euler-Rodrigues formula given in the docstring of .rotate except for small numbers of rotations. I have uploaded the benchmark script I wrote to https://gist.github.com/bcbnz/72ccebe4cc3d6e5ad3666953bfe3c6d5 and a subset of the generated images are below. The benchmark also asserts the results are allclose with each other and with the existing .rotate() (either fully if the output shapes are the same, or on the first quaternion & vector if not). The benchmarked functions did not include the error checking included in the pull request.

Nx4, 1x3
Nx4, Nx3
Nx10x4, Nx10x3

The unit tests compare results against the .rotate method. In simple cases, these will have the same shape. In the other cases, we can compare with the diagonal vector components.

I have not mentioned the new method in the docstring of .rotate as I wasn't sure what to do with its comments about the alternative method. I am happy to add a commit or do a force push modifying it with some guidance on the appropriate changes, or you are of course welcome to do so yourself (I have set the 'allow edits by maintainers' option in this pull request).

This uses standard NumPy broadcasting rules. This means that for an Nx4
quaternionic array and an Nx3 vector array, an Nx3 rotated vector array
will be output. This is in contrast to the existing rotate() method
which operates as an outer product and would return an NxNx3 rotated
vector array.
@codecov

codecovBot commented Feb 14, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.92%. Comparing base (cd82c6c) to head (c1c0a01).
⚠️ Report is 10 commits behind head on main.

Additional details and impacted files
@@ Coverage Diff @@## main #50 +/- ##
==========================================
+ Coverage 97.90% 97.92% +0.01% 
==========================================
Files 10 10 Lines 1098 1107 +9 Branches 118 120 +2 ==========================================
+ Hits 1075 1084 +9 
Misses 21 21 Partials 2 2 

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for freeto 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

@bcbnz@bcb-hsu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Add a broadcasting rotation method by bcbnz · Pull Request #50 · moble/quaternionic · GitHub
Skip to content

Add a broadcasting rotation method - #50

Open
bcbnz wants to merge 1 commit into
moble:mainfrom
bcbnz:rotate_broadcast
Open

Add a broadcasting rotation method#50
bcbnz wants to merge 1 commit into
moble:mainfrom
bcbnz:rotate_broadcast

Conversation

@bcbnz

Copy link
Copy Markdown
Contributor

This pull request adds a quat.rotate_broadcast(vecs) method. Standard NumPy broadcasting rules are used to determine the shape of its output. This means that for an Nx4 quaternionic array and an Nx3 vector array, an Nx3 rotated vector array will be output. This is in contrast to the existing .rotate() method which operates as an outer product and would return an NxNx3 rotated vector array.

My initial use case for this is using this for coordinate transforms. If we have a series of poses stored as Nx3 positions and Nx4 quaternions, the result of rotating vectors as part of changing coordinate systems should be Nx3.

Note that I have implemented this with the standard q * v * q.inverse method as some benchmarking indicated this was faster than the Euler-Rodrigues formula given in the docstring of .rotate except for small numbers of rotations. I have uploaded the benchmark script I wrote to https://gist.github.com/bcbnz/72ccebe4cc3d6e5ad3666953bfe3c6d5 and a subset of the generated images are below. The benchmark also asserts the results are allclose with each other and with the existing .rotate() (either fully if the output shapes are the same, or on the first quaternion & vector if not). The benchmarked functions did not include the error checking included in the pull request.

Nx4, 1x3
Nx4, Nx3
Nx10x4, Nx10x3

The unit tests compare results against the .rotate method. In simple cases, these will have the same shape. In the other cases, we can compare with the diagonal vector components.

I have not mentioned the new method in the docstring of .rotate as I wasn't sure what to do with its comments about the alternative method. I am happy to add a commit or do a force push modifying it with some guidance on the appropriate changes, or you are of course welcome to do so yourself (I have set the 'allow edits by maintainers' option in this pull request).

This uses standard NumPy broadcasting rules. This means that for an Nx4
quaternionic array and an Nx3 vector array, an Nx3 rotated vector array
will be output. This is in contrast to the existing rotate() method
which operates as an outer product and would return an NxNx3 rotated
vector array.
@codecov

codecovBot commented Feb 14, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.92%. Comparing base (cd82c6c) to head (c1c0a01).
⚠️ Report is 10 commits behind head on main.

Additional details and impacted files
@@ Coverage Diff @@## main #50 +/- ##
==========================================
+ Coverage 97.90% 97.92% +0.01% 
==========================================
Files 10 10 Lines 1098 1107 +9 Branches 118 120 +2 ==========================================
+ Hits 1075 1084 +9 
Misses 21 21 Partials 2 2 

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for freeto 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

@bcbnz@bcb-hsu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Add a broadcasting rotation method by bcbnz · Pull Request #50 · moble/quaternionic · GitHub
Skip to content

Add a broadcasting rotation method - #50

Open
bcbnz wants to merge 1 commit into
moble:mainfrom
bcbnz:rotate_broadcast
Open

Add a broadcasting rotation method#50
bcbnz wants to merge 1 commit into
moble:mainfrom
bcbnz:rotate_broadcast

Conversation

@bcbnz

Copy link
Copy Markdown
Contributor

This pull request adds a quat.rotate_broadcast(vecs) method. Standard NumPy broadcasting rules are used to determine the shape of its output. This means that for an Nx4 quaternionic array and an Nx3 vector array, an Nx3 rotated vector array will be output. This is in contrast to the existing .rotate() method which operates as an outer product and would return an NxNx3 rotated vector array.

My initial use case for this is using this for coordinate transforms. If we have a series of poses stored as Nx3 positions and Nx4 quaternions, the result of rotating vectors as part of changing coordinate systems should be Nx3.

Note that I have implemented this with the standard q * v * q.inverse method as some benchmarking indicated this was faster than the Euler-Rodrigues formula given in the docstring of .rotate except for small numbers of rotations. I have uploaded the benchmark script I wrote to https://gist.github.com/bcbnz/72ccebe4cc3d6e5ad3666953bfe3c6d5 and a subset of the generated images are below. The benchmark also asserts the results are allclose with each other and with the existing .rotate() (either fully if the output shapes are the same, or on the first quaternion & vector if not). The benchmarked functions did not include the error checking included in the pull request.

Nx4, 1x3
Nx4, Nx3
Nx10x4, Nx10x3

The unit tests compare results against the .rotate method. In simple cases, these will have the same shape. In the other cases, we can compare with the diagonal vector components.

I have not mentioned the new method in the docstring of .rotate as I wasn't sure what to do with its comments about the alternative method. I am happy to add a commit or do a force push modifying it with some guidance on the appropriate changes, or you are of course welcome to do so yourself (I have set the 'allow edits by maintainers' option in this pull request).

This uses standard NumPy broadcasting rules. This means that for an Nx4
quaternionic array and an Nx3 vector array, an Nx3 rotated vector array
will be output. This is in contrast to the existing rotate() method
which operates as an outer product and would return an NxNx3 rotated
vector array.
@codecov

codecovBot commented Feb 14, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.92%. Comparing base (cd82c6c) to head (c1c0a01).
⚠️ Report is 10 commits behind head on main.

Additional details and impacted files
@@ Coverage Diff @@## main #50 +/- ##
==========================================
+ Coverage 97.90% 97.92% +0.01% 
==========================================
Files 10 10 Lines 1098 1107 +9 Branches 118 120 +2 ==========================================
+ Hits 1075 1084 +9 
Misses 21 21 Partials 2 2 

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for freeto 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

@bcbnz@bcb-hsu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Add a broadcasting rotation method by bcbnz · Pull Request #50 · moble/quaternionic · GitHub
Skip to content

Add a broadcasting rotation method - #50

Open
bcbnz wants to merge 1 commit into
moble:mainfrom
bcbnz:rotate_broadcast
Open

Add a broadcasting rotation method#50
bcbnz wants to merge 1 commit into
moble:mainfrom
bcbnz:rotate_broadcast

Conversation

@bcbnz

Copy link
Copy Markdown
Contributor

This pull request adds a quat.rotate_broadcast(vecs) method. Standard NumPy broadcasting rules are used to determine the shape of its output. This means that for an Nx4 quaternionic array and an Nx3 vector array, an Nx3 rotated vector array will be output. This is in contrast to the existing .rotate() method which operates as an outer product and would return an NxNx3 rotated vector array.

My initial use case for this is using this for coordinate transforms. If we have a series of poses stored as Nx3 positions and Nx4 quaternions, the result of rotating vectors as part of changing coordinate systems should be Nx3.

Note that I have implemented this with the standard q * v * q.inverse method as some benchmarking indicated this was faster than the Euler-Rodrigues formula given in the docstring of .rotate except for small numbers of rotations. I have uploaded the benchmark script I wrote to https://gist.github.com/bcbnz/72ccebe4cc3d6e5ad3666953bfe3c6d5 and a subset of the generated images are below. The benchmark also asserts the results are allclose with each other and with the existing .rotate() (either fully if the output shapes are the same, or on the first quaternion & vector if not). The benchmarked functions did not include the error checking included in the pull request.

Nx4, 1x3
Nx4, Nx3
Nx10x4, Nx10x3

The unit tests compare results against the .rotate method. In simple cases, these will have the same shape. In the other cases, we can compare with the diagonal vector components.

I have not mentioned the new method in the docstring of .rotate as I wasn't sure what to do with its comments about the alternative method. I am happy to add a commit or do a force push modifying it with some guidance on the appropriate changes, or you are of course welcome to do so yourself (I have set the 'allow edits by maintainers' option in this pull request).

This uses standard NumPy broadcasting rules. This means that for an Nx4
quaternionic array and an Nx3 vector array, an Nx3 rotated vector array
will be output. This is in contrast to the existing rotate() method
which operates as an outer product and would return an NxNx3 rotated
vector array.
@codecov

codecovBot commented Feb 14, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.92%. Comparing base (cd82c6c) to head (c1c0a01).
⚠️ Report is 10 commits behind head on main.

Additional details and impacted files
@@ Coverage Diff @@## main #50 +/- ##
==========================================
+ Coverage 97.90% 97.92% +0.01% 
==========================================
Files 10 10 Lines 1098 1107 +9 Branches 118 120 +2 ==========================================
+ Hits 1075 1084 +9 
Misses 21 21 Partials 2 2 

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for freeto 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

@bcbnz@bcb-hsu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Add a broadcasting rotation method by bcbnz · Pull Request #50 · moble/quaternionic · GitHub
Skip to content

Add a broadcasting rotation method - #50

Open
bcbnz wants to merge 1 commit into
moble:mainfrom
bcbnz:rotate_broadcast
Open

Add a broadcasting rotation method#50
bcbnz wants to merge 1 commit into
moble:mainfrom
bcbnz:rotate_broadcast

Conversation

@bcbnz

Copy link
Copy Markdown
Contributor

This pull request adds a quat.rotate_broadcast(vecs) method. Standard NumPy broadcasting rules are used to determine the shape of its output. This means that for an Nx4 quaternionic array and an Nx3 vector array, an Nx3 rotated vector array will be output. This is in contrast to the existing .rotate() method which operates as an outer product and would return an NxNx3 rotated vector array.

My initial use case for this is using this for coordinate transforms. If we have a series of poses stored as Nx3 positions and Nx4 quaternions, the result of rotating vectors as part of changing coordinate systems should be Nx3.

Note that I have implemented this with the standard q * v * q.inverse method as some benchmarking indicated this was faster than the Euler-Rodrigues formula given in the docstring of .rotate except for small numbers of rotations. I have uploaded the benchmark script I wrote to https://gist.github.com/bcbnz/72ccebe4cc3d6e5ad3666953bfe3c6d5 and a subset of the generated images are below. The benchmark also asserts the results are allclose with each other and with the existing .rotate() (either fully if the output shapes are the same, or on the first quaternion & vector if not). The benchmarked functions did not include the error checking included in the pull request.

Nx4, 1x3
Nx4, Nx3
Nx10x4, Nx10x3

The unit tests compare results against the .rotate method. In simple cases, these will have the same shape. In the other cases, we can compare with the diagonal vector components.

I have not mentioned the new method in the docstring of .rotate as I wasn't sure what to do with its comments about the alternative method. I am happy to add a commit or do a force push modifying it with some guidance on the appropriate changes, or you are of course welcome to do so yourself (I have set the 'allow edits by maintainers' option in this pull request).

This uses standard NumPy broadcasting rules. This means that for an Nx4
quaternionic array and an Nx3 vector array, an Nx3 rotated vector array
will be output. This is in contrast to the existing rotate() method
which operates as an outer product and would return an NxNx3 rotated
vector array.
@codecov

codecovBot commented Feb 14, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.92%. Comparing base (cd82c6c) to head (c1c0a01).
⚠️ Report is 10 commits behind head on main.

Additional details and impacted files
@@ Coverage Diff @@## main #50 +/- ##
==========================================
+ Coverage 97.90% 97.92% +0.01% 
==========================================
Files 10 10 Lines 1098 1107 +9 Branches 118 120 +2 ==========================================
+ Hits 1075 1084 +9 
Misses 21 21 Partials 2 2 

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for freeto 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

@bcbnz@bcb-hsu