Skip to content

Commit ae952f1

Browse files
committed
feat: add tests for clampToCircle functionality in Poline class
1 parent 8da9c2c commit ae952f1

File tree

1 file changed

+170
-0
lines changed

1 file changed

+170
-0
lines changed

tests/index.test.ts

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
hslToPoint,
88
randomHSLPair,
99
randomHSLTriple,
10+
clampToCircle,
1011
} from '../src/index';
1112

1213
describe('ColorPoint', () => {
@@ -719,3 +720,172 @@ describe('Position Functions', () => {
719720
expect(p75).toBeGreaterThan(0.5);
720721
});
721722
});
723+
724+
describe('clampToCircle', () => {
725+
it('should not modify points inside the circle', () => {
726+
const [x, y] = clampToCircle(0.5, 0.5); // center
727+
expect(x).toBe(0.5);
728+
expect(y).toBe(0.5);
729+
730+
const [x2, y2] = clampToCircle(0.6, 0.6); // inside
731+
expect(x2).toBe(0.6);
732+
expect(y2).toBe(0.6);
733+
});
734+
735+
it('should clamp points outside the circle to the boundary', () => {
736+
// Point at (1, 0.5) is 0.5 units to the right of center, on the edge
737+
const [x1, y1] = clampToCircle(1, 0.5);
738+
expect(x1).toBeCloseTo(1);
739+
expect(y1).toBeCloseTo(0.5);
740+
741+
// Point at (1.5, 0.5) is outside, should be clamped to edge
742+
const [x2, y2] = clampToCircle(1.5, 0.5);
743+
expect(x2).toBeCloseTo(1);
744+
expect(y2).toBeCloseTo(0.5);
745+
746+
// Point at (0.9, 0.9) is outside the circle
747+
const [x3, y3] = clampToCircle(0.9, 0.9);
748+
const dist = Math.sqrt((x3 - 0.5) ** 2 + (y3 - 0.5) ** 2);
749+
expect(dist).toBeCloseTo(0.5);
750+
});
751+
752+
it('should preserve direction when clamping', () => {
753+
// Point far to the upper right
754+
const [x, y] = clampToCircle(1.5, 1.5);
755+
// Should be on the edge in the same direction
756+
expect(x - 0.5).toBeCloseTo(y - 0.5); // diagonal
757+
expect(x).toBeGreaterThan(0.5);
758+
expect(y).toBeGreaterThan(0.5);
759+
});
760+
});
761+
762+
describe('Poline clampToCircle option', () => {
763+
it('should initialize with clampToCircle default false', () => {
764+
const poline = new Poline();
765+
expect(poline.clampToCircle).toBe(false);
766+
});
767+
768+
it('should initialize with clampToCircle option', () => {
769+
const poline = new Poline({
770+
anchorColors: [
771+
[0, 1, 0.5],
772+
[180, 1, 0.5],
773+
],
774+
clampToCircle: true,
775+
});
776+
expect(poline.clampToCircle).toBe(true);
777+
});
778+
779+
it('should allow setting clampToCircle after initialization', () => {
780+
const poline = new Poline();
781+
expect(poline.clampToCircle).toBe(false);
782+
poline.clampToCircle = true;
783+
expect(poline.clampToCircle).toBe(true);
784+
});
785+
786+
it('should clamp addAnchorPoint when clamp option is true', () => {
787+
const poline = new Poline({
788+
anchorColors: [
789+
[0, 1, 0.5],
790+
[180, 1, 0.5],
791+
],
792+
});
793+
794+
// Add point outside circle with clamp: true
795+
const point = poline.addAnchorPoint({ xyz: [0.9, 0.9, 0.5], clamp: true });
796+
const dist = Math.sqrt((point.x - 0.5) ** 2 + (point.y - 0.5) ** 2);
797+
expect(dist).toBeCloseTo(0.5);
798+
});
799+
800+
it('should not clamp addAnchorPoint when clamp option is false', () => {
801+
const poline = new Poline({
802+
anchorColors: [
803+
[0, 1, 0.5],
804+
[180, 1, 0.5],
805+
],
806+
});
807+
808+
// Add point outside circle without clamping
809+
const point = poline.addAnchorPoint({ xyz: [0.9, 0.9, 0.5], clamp: false });
810+
expect(point.x).toBe(0.9);
811+
expect(point.y).toBe(0.9);
812+
});
813+
814+
it('should use class default clampToCircle when clamp option not specified', () => {
815+
const poline = new Poline({
816+
anchorColors: [
817+
[0, 1, 0.5],
818+
[180, 1, 0.5],
819+
],
820+
clampToCircle: true,
821+
});
822+
823+
// Add point outside circle, should use class default (true)
824+
const point = poline.addAnchorPoint({ xyz: [0.9, 0.9, 0.5] });
825+
const dist = Math.sqrt((point.x - 0.5) ** 2 + (point.y - 0.5) ** 2);
826+
expect(dist).toBeCloseTo(0.5);
827+
});
828+
829+
it('should override class default with explicit clamp: false', () => {
830+
const poline = new Poline({
831+
anchorColors: [
832+
[0, 1, 0.5],
833+
[180, 1, 0.5],
834+
],
835+
clampToCircle: true,
836+
});
837+
838+
// Add point outside circle with explicit clamp: false
839+
const point = poline.addAnchorPoint({ xyz: [0.9, 0.9, 0.5], clamp: false });
840+
expect(point.x).toBe(0.9);
841+
expect(point.y).toBe(0.9);
842+
});
843+
844+
it('should clamp updateAnchorPoint when clamp option is true', () => {
845+
const poline = new Poline({
846+
anchorColors: [
847+
[0, 1, 0.5],
848+
[180, 1, 0.5],
849+
],
850+
});
851+
852+
// Update point to outside circle with clamp: true
853+
const point = poline.updateAnchorPoint({
854+
pointIndex: 0,
855+
xyz: [0.9, 0.9, 0.5],
856+
clamp: true,
857+
});
858+
const dist = Math.sqrt((point.x - 0.5) ** 2 + (point.y - 0.5) ** 2);
859+
expect(dist).toBeCloseTo(0.5);
860+
});
861+
862+
it('should use class default for updateAnchorPoint when clamp not specified', () => {
863+
const poline = new Poline({
864+
anchorColors: [
865+
[0, 1, 0.5],
866+
[180, 1, 0.5],
867+
],
868+
clampToCircle: true,
869+
});
870+
871+
// Update point to outside circle, should use class default (true)
872+
const point = poline.updateAnchorPoint({
873+
pointIndex: 0,
874+
xyz: [0.9, 0.9, 0.5],
875+
});
876+
const dist = Math.sqrt((point.x - 0.5) ** 2 + (point.y - 0.5) ** 2);
877+
expect(dist).toBeCloseTo(0.5);
878+
});
879+
880+
it('should preserve z coordinate when clamping', () => {
881+
const poline = new Poline({
882+
anchorColors: [
883+
[0, 1, 0.5],
884+
[180, 1, 0.5],
885+
],
886+
});
887+
888+
const point = poline.addAnchorPoint({ xyz: [0.9, 0.9, 0.8], clamp: true });
889+
expect(point.z).toBe(0.8);
890+
});
891+
});

0 commit comments

Comments
 (0)