aboutsummaryrefslogtreecommitdiff
path: root/js/lib/geom/sub-path.js
diff options
context:
space:
mode:
authorPushkar Joshi2012-04-11 10:07:42 -0700
committerPushkar Joshi2012-04-11 10:07:42 -0700
commit25e406c9924438697564bc2341bd5b045a1dd85c (patch)
treef4c904662708a6d5db8c463a23256ac661c972a1 /js/lib/geom/sub-path.js
parent7fed1940bb4f3a333cef92fd51787a29e6dd787b (diff)
downloadninja-25e406c9924438697564bc2341bd5b045a1dd85c.tar.gz
Use local coordinates to pick a point within the path (works correctly even with canvas and/or stage transformation). Dragging does not yet work in case of canvas transformation
Diffstat (limited to 'js/lib/geom/sub-path.js')
-rwxr-xr-xjs/lib/geom/sub-path.js87
1 files changed, 62 insertions, 25 deletions
diff --git a/js/lib/geom/sub-path.js b/js/lib/geom/sub-path.js
index 64f27bd3..87840bdc 100755
--- a/js/lib/geom/sub-path.js
+++ b/js/lib/geom/sub-path.js
@@ -752,9 +752,9 @@ GLSubpath.prototype.pathSamplesLocalHitTest = function(pickX, pickY, pickZ, radi
752 currAnchor = nextAnchor; 752 currAnchor = nextAnchor;
753 }//for every anchor i 753 }//for every anchor i
754 return [selAnchorIndex,retParam]; 754 return [selAnchorIndex,retParam];
755
756}; 755};
757 756
757
758//pick the path point closest to the specified location, return null if some anchor point (or its handles) is within radius, else return the parameter distance 758//pick the path point closest to the specified location, return null if some anchor point (or its handles) is within radius, else return the parameter distance
759GLSubpath.prototype.pathHitTest = function (pickX, pickY, pickZ, radius) { 759GLSubpath.prototype.pathHitTest = function (pickX, pickY, pickZ, radius) {
760 var numAnchors = this._Anchors.length; 760 var numAnchors = this._Anchors.length;
@@ -828,16 +828,27 @@ GLSubpath.prototype.pathHitTest = function (pickX, pickY, pickZ, radius) {
828 return [selAnchorIndex,retParam]; 828 return [selAnchorIndex,retParam];
829} //GLSubpath.pathHitTest function 829} //GLSubpath.pathHitTest function
830 830
831
831//pick the path point closest to the specified location, return null if some anchor point (or its handles) is within radius, else return the parameter distance 832//pick the path point closest to the specified location, return null if some anchor point (or its handles) is within radius, else return the parameter distance
832GLSubpath.prototype.pickPath = function (pickX, pickY, pickZ, radius) { 833GLSubpath.prototype.pickPath = function (pickX, pickY, pickZ, radius, useLocal) {
833 var numAnchors = this._Anchors.length; 834 var numAnchors = this._Anchors.length;
834 var selAnchorIndex = -1; 835 var selAnchorIndex = -1;
835 var retCode = this.SEL_NONE; 836 var retCode = this.SEL_NONE;
836 var radSq = radius * radius; 837 var radSq = radius * radius;
837 var minDistance = Infinity; 838 var minDistance = Infinity;
839
840 //ignore the useLocal flag if the anchor points are not in-sync. with the local coordinates
841 if (numAnchors != this._AnchorLocalCoords.length){
842 useLocal = false;
843 }
844
838 //check if the clicked location is close to the currently selected anchor position 845 //check if the clicked location is close to the currently selected anchor position
839 if (this._selectedAnchorIndex>=0 && this._selectedAnchorIndex<this._Anchors.length){ 846 if (this._selectedAnchorIndex>=0 && this._selectedAnchorIndex<this._Anchors.length){
840 var distSq = this._Anchors[this._selectedAnchorIndex].getDistanceSq(pickX, pickY, pickZ); 847 var distSq;
848 if (!useLocal)
849 distSq = this._Anchors[this._selectedAnchorIndex].getDistanceSq(pickX, pickY, pickZ);
850 else
851 distSq = VecUtils.vecDistSq(3, this._AnchorLocalCoords[this._selectedAnchorIndex][1], [pickX, pickY, pickZ]);
841 //check the anchor point 852 //check the anchor point
842 if (distSq < minDistance && distSq < radSq) { 853 if (distSq < minDistance && distSq < radSq) {
843 selAnchorIndex = this._selectedAnchorIndex; 854 selAnchorIndex = this._selectedAnchorIndex;
@@ -845,10 +856,16 @@ GLSubpath.prototype.pickPath = function (pickX, pickY, pickZ, radius) {
845 retCode = retCode | this.SEL_ANCHOR; 856 retCode = retCode | this.SEL_ANCHOR;
846 } 857 }
847 } 858 }
859
848 //now check if the click location is close to any anchor position 860 //now check if the click location is close to any anchor position
849 if (selAnchorIndex===-1) { 861 if (selAnchorIndex===-1) {
850 for (var i = 0; i < numAnchors; i++) { 862 for (var i = 0; i < numAnchors; i++) {
851 var distSq = this._Anchors[i].getDistanceSq(pickX, pickY, pickZ); 863 var distSq;
864 if (!useLocal)
865 distSq = this._Anchors[i].getDistanceSq(pickX, pickY, pickZ);
866 else
867 distSq = VecUtils.vecDistSq(3, this._AnchorLocalCoords[i][1], [pickX, pickY, pickZ]);
868
852 //check the anchor point 869 //check the anchor point
853 if (distSq < minDistance && distSq < radSq) { 870 if (distSq < minDistance && distSq < radSq) {
854 selAnchorIndex = i; 871 selAnchorIndex = i;
@@ -860,14 +877,23 @@ GLSubpath.prototype.pickPath = function (pickX, pickY, pickZ, radius) {
860 877
861 //check the prev and next of the selected anchor if the above did not register a hit 878 //check the prev and next of the selected anchor if the above did not register a hit
862 if (this._selectedAnchorIndex>=0 && selAnchorIndex === -1) { 879 if (this._selectedAnchorIndex>=0 && selAnchorIndex === -1) {
863 var distSq = this._Anchors[this._selectedAnchorIndex].getPrevDistanceSq(pickX, pickY, pickZ); 880 var distSq;
881 if (!useLocal)
882 distSq = this._Anchors[this._selectedAnchorIndex].getPrevDistanceSq(pickX, pickY, pickZ);
883 else
884 distSq = VecUtils.vecDistSq(3, this._AnchorLocalCoords[this._selectedAnchorIndex][0], [pickX, pickY, pickZ]);
885
864 if (distSq < minDistance && distSq < radSq){ 886 if (distSq < minDistance && distSq < radSq){
865 selAnchorIndex = this._selectedAnchorIndex; 887 selAnchorIndex = this._selectedAnchorIndex;
866 minDistance = distSq; 888 minDistance = distSq;
867 retCode = retCode | this.SEL_PREV; 889 retCode = retCode | this.SEL_PREV;
868 } else { 890 } else {
869 //check the next for this anchor point 891 //check the next for this anchor point
870 distSq = this._Anchors[this._selectedAnchorIndex].getNextDistanceSq(pickX, pickY, pickZ); 892 if (!useLocal)
893 distSq = this._Anchors[this._selectedAnchorIndex].getNextDistanceSq(pickX, pickY, pickZ);
894 else
895 distSq = VecUtils.vecDistSq(3, this._AnchorLocalCoords[this._selectedAnchorIndex][2], [pickX, pickY, pickZ]);
896
871 if (distSq<minDistance && distSq<radSq){ 897 if (distSq<minDistance && distSq<radSq){
872 selAnchorIndex = this._selectedAnchorIndex; 898 selAnchorIndex = this._selectedAnchorIndex;
873 minDistance = distSq; 899 minDistance = distSq;
@@ -881,27 +907,38 @@ GLSubpath.prototype.pickPath = function (pickX, pickY, pickZ, radius) {
881 this._selectedAnchorIndex = selAnchorIndex; 907 this._selectedAnchorIndex = selAnchorIndex;
882 } else { 908 } else {
883 this._selectedAnchorIndex = -1; 909 this._selectedAnchorIndex = -1;
884 var numSegments = this._isClosed ? numAnchors : numAnchors-1; 910 if (!useLocal){
885 for (var i = 0; i < numSegments; i++) { 911 var numSegments = this._isClosed ? numAnchors : numAnchors-1;
886 var nextIndex = (i+1)%numAnchors; 912 var currAnchor = this._AnchorLocalCoords[0];
887 //check if the point is close to the bezier segment between anchor i and anchor nextIndex 913 var nextAnchor = null;
888 var controlPoints = [[this._Anchors[i].getPosX(),this._Anchors[i].getPosY(),this._Anchors[i].getPosZ()], 914 for (var i = 0; i < numSegments; i++) {
889 [this._Anchors[i].getNextX(),this._Anchors[i].getNextY(),this._Anchors[i].getNextZ()], 915 var nextIndex = (i+1)%numAnchors;
890 [this._Anchors[nextIndex].getPrevX(),this._Anchors[nextIndex].getPrevY(),this._Anchors[nextIndex].getPrevZ()], 916 //check if the point is close to the bezier segment between anchor i and anchor nextIndex
891 [this._Anchors[nextIndex].getPosX(),this._Anchors[nextIndex].getPosY(),this._Anchors[nextIndex].getPosZ()]]; 917 var controlPoints = [[this._Anchors[i].getPosX(),this._Anchors[i].getPosY(),this._Anchors[i].getPosZ()],
892 var point = [pickX, pickY, pickZ]; 918 [this._Anchors[i].getNextX(),this._Anchors[i].getNextY(),this._Anchors[i].getNextZ()],
893 if (this._isWithinBoundingBox(point, controlPoints, radius)) { 919 [this._Anchors[nextIndex].getPrevX(),this._Anchors[nextIndex].getPrevY(),this._Anchors[nextIndex].getPrevZ()],
894 //var intersectParam = this._checkIntersection(controlPoints, 0.0, 1.0, point, radius); 920 [this._Anchors[nextIndex].getPosX(),this._Anchors[nextIndex].getPosY(),this._Anchors[nextIndex].getPosZ()]];
895 var intersectParam = this._checkIntersectionWithSamples(this._anchorSampleIndex[i], this._anchorSampleIndex[nextIndex], point, radius); 921 var point = [pickX, pickY, pickZ];
896 console.log("intersectParam:"+intersectParam); 922 if (this._isWithinBoundingBox(point, controlPoints, radius)) {
897 if (intersectParam){ 923 //var intersectParam = this._checkIntersection(controlPoints, 0.0, 1.0, point, radius);
898 retCode = retCode | this.SEL_PATH; 924 var intersectParam = this._checkIntersectionWithSamples(this._anchorSampleIndex[i], this._anchorSampleIndex[nextIndex], point, radius);
899 retParam = intersectParam-i; //make the retParam go from 0 to 1 925 console.log("intersectParam:"+intersectParam);
900 this._selectedAnchorIndex = i; 926 if (intersectParam){
901 break; 927 retCode = retCode | this.SEL_PATH;
928 retParam = intersectParam-i; //make the retParam go from 0 to 1
929 this._selectedAnchorIndex = i;
930 break;
931 }
902 } 932 }
933 }//for every anchor i
934 } else {
935 var selAnchorParam = this.pathSamplesLocalHitTest(pickX, pickY, pickZ, radius);
936 if (selAnchorParam[0]!== -1){
937 this._selectedAnchorIndex = selAnchorParam[0];
938 retParam = selAnchorParam[1];
939 retCode = retCode | this.SEL_PATH;
903 } 940 }
904 }//for every anchor i 941 }
905 } 942 }
906 this._selectMode = retCode; 943 this._selectMode = retCode;
907 return retParam; 944 return retParam;