diff options
author | Pushkar Joshi | 2012-04-11 10:07:42 -0700 |
---|---|---|
committer | Pushkar Joshi | 2012-04-11 10:07:42 -0700 |
commit | 25e406c9924438697564bc2341bd5b045a1dd85c (patch) | |
tree | f4c904662708a6d5db8c463a23256ac661c972a1 /js/lib/geom | |
parent | 7fed1940bb4f3a333cef92fd51787a29e6dd787b (diff) | |
download | ninja-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')
-rwxr-xr-x | js/lib/geom/sub-path.js | 87 |
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 |
759 | GLSubpath.prototype.pathHitTest = function (pickX, pickY, pickZ, radius) { | 759 | GLSubpath.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 |
832 | GLSubpath.prototype.pickPath = function (pickX, pickY, pickZ, radius) { | 833 | GLSubpath.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; |