aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--images/cursors/penAdd.pngbin0 -> 3043 bytes
-rwxr-xr-xjs/helper-classes/backup-delete/GLSubpath.js147
-rwxr-xr-xjs/lib/geom/sub-path.js84
-rwxr-xr-xjs/tools/PenTool.js12
4 files changed, 219 insertions, 24 deletions
diff --git a/images/cursors/penAdd.png b/images/cursors/penAdd.png
new file mode 100644
index 00000000..c306cc85
--- /dev/null
+++ b/images/cursors/penAdd.png
Binary files differ
diff --git a/js/helper-classes/backup-delete/GLSubpath.js b/js/helper-classes/backup-delete/GLSubpath.js
index f3d8ad36..2fb91d33 100755
--- a/js/helper-classes/backup-delete/GLSubpath.js
+++ b/js/helper-classes/backup-delete/GLSubpath.js
@@ -505,7 +505,6 @@ GLSubpath.prototype._isWithinBoundingBox = function(point, ctrlPts, radius) {
505GLSubpath.prototype.pickAnchor = function (pickX, pickY, pickZ, radius) { 505GLSubpath.prototype.pickAnchor = function (pickX, pickY, pickZ, radius) {
506 var numAnchors = this._Anchors.length; 506 var numAnchors = this._Anchors.length;
507 var selAnchorIndex = -1; 507 var selAnchorIndex = -1;
508 var retCode = this.SEL_NONE;
509 var radSq = radius * radius; 508 var radSq = radius * radius;
510 var minDistance = Infinity; 509 var minDistance = Infinity;
511 //check if the clicked location is close to the currently selected anchor position 510 //check if the clicked location is close to the currently selected anchor position
@@ -515,9 +514,23 @@ GLSubpath.prototype.pickAnchor = function (pickX, pickY, pickZ, radius) {
515 if (distSq < minDistance && distSq < radSq) { 514 if (distSq < minDistance && distSq < radSq) {
516 selAnchorIndex = this._selectedAnchorIndex; 515 selAnchorIndex = this._selectedAnchorIndex;
517 minDistance = distSq; 516 minDistance = distSq;
518 retCode = retCode | this.SEL_ANCHOR; 517 } else {
518 //check the prev and next of the selected anchor if the above did not register a hit
519 distSq = this._Anchors[this._selectedAnchorIndex].getPrevDistanceSq(pickX, pickY, pickZ);
520 if (distSq < minDistance && distSq < radSq){
521 selAnchorIndex = this._selectedAnchorIndex;
522 minDistance = distSq;
523 } else {
524 //check the next for this anchor point
525 distSq = this._Anchors[this._selectedAnchorIndex].getNextDistanceSq(pickX, pickY, pickZ);
526 if (distSq<minDistance && distSq<radSq){
527 selAnchorIndex = this._selectedAnchorIndex;
528 minDistance = distSq;
529 }
530 }
519 } 531 }
520 } 532 }
533
521 //now check if the click location is close to any anchor position 534 //now check if the click location is close to any anchor position
522 if (selAnchorIndex===-1) { 535 if (selAnchorIndex===-1) {
523 for (var i = 0; i < numAnchors; i++) { 536 for (var i = 0; i < numAnchors; i++) {
@@ -532,12 +545,97 @@ GLSubpath.prototype.pickAnchor = function (pickX, pickY, pickZ, radius) {
532 return selAnchorIndex; 545 return selAnchorIndex;
533} 546}
534 547
548GLSubpath.prototype.isWithinBBox =function(x,y,z){
549 if (this._BBoxMin[0]>x || this._BBoxMin[1]>y || this._BBoxMin[2]>z){
550 return false;
551 }
552 if (this._BBoxMax[0]<x || this._BBoxMax[1]<y || this._BBoxMax[2]<z){
553 return false;
554 }
555 return true;
556}
557
558//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
559GLSubpath.prototype.pathHitTest = function (pickX, pickY, pickZ, radius) {
560 var numAnchors = this._Anchors.length;
561 var selAnchorIndex = -1;
562 var retParam = null;
563 var radSq = radius * radius;
564 var minDistance = Infinity;
565
566 //check if the location is close to the currently selected anchor position
567 if (this._selectedAnchorIndex>=0 && this._selectedAnchorIndex<this._Anchors.length){
568 var distSq = this._Anchors[this._selectedAnchorIndex].getDistanceSq(pickX, pickY, pickZ);
569 //check the anchor point
570 if (distSq < minDistance && distSq < radSq) {
571 selAnchorIndex = this._selectedAnchorIndex;
572 minDistance = distSq;
573 }
574 }
575 //check the prev and next of the selected anchor if the above did not register a hit
576 if (this._selectedAnchorIndex>=0 && selAnchorIndex === -1) {
577 var distSq = this._Anchors[this._selectedAnchorIndex].getPrevDistanceSq(pickX, pickY, pickZ);
578 if (distSq < minDistance && distSq < radSq){
579 selAnchorIndex = this._selectedAnchorIndex;
580 minDistance = distSq;
581 } else {
582 //check the next for this anchor point
583 distSq = this._Anchors[this._selectedAnchorIndex].getNextDistanceSq(pickX, pickY, pickZ);
584 if (distSq<minDistance && distSq<radSq){
585 selAnchorIndex = this._selectedAnchorIndex;
586 minDistance = distSq;
587 }
588 }
589 }
590
591 //now check if the location is close to any anchor position
592 if (selAnchorIndex===-1) {
593 for (var i = 0; i < numAnchors; i++) {
594 var distSq = this._Anchors[i].getDistanceSq(pickX, pickY, pickZ);
595 //check the anchor point
596 if (distSq < minDistance && distSq < radSq) {
597 selAnchorIndex = i;
598 minDistance = distSq;
599 }
600 }//for every anchor i
601 }
602
603 //finally check if the location is close to the curve itself
604 if (selAnchorIndex===-1) {
605 //first check if the input location is within the bounding box
606 if (this.isWithinBBox(pickX,pickY,pickZ)){
607 var numSegments = this._isClosed ? numAnchors : numAnchors-1;
608 for (var i = 0; i < numSegments; i++) {
609 var nextIndex = (i+1)%numAnchors;
610 //check if the point is close to the bezier segment between anchor i and anchor nextIndex
611 var controlPoints = Vector.create([Vector.create([this._Anchors[i].getPosX(),this._Anchors[i].getPosY(),this._Anchors[i].getPosZ()]),
612 Vector.create([this._Anchors[i].getNextX(),this._Anchors[i].getNextY(),this._Anchors[i].getNextZ()]),
613 Vector.create([this._Anchors[nextIndex].getPrevX(),this._Anchors[nextIndex].getPrevY(),this._Anchors[nextIndex].getPrevZ()]),
614 Vector.create([this._Anchors[nextIndex].getPosX(),this._Anchors[nextIndex].getPosY(),this._Anchors[nextIndex].getPosZ()])]);
615 var point = Vector.create([pickX, pickY, pickZ]);
616 if (this._isWithinBoundingBox(point, controlPoints, radius)) {
617 //var intersectParam = this._checkIntersection(controlPoints, 0.0, 1.0, point, radius);
618 var intersectParam = this._checkIntersectionWithSamples(this._anchorSampleIndex[i], this._anchorSampleIndex[nextIndex], point, radius);
619 console.log("intersectParam:"+intersectParam);
620 if (intersectParam){
621 selAnchorIndex=i;
622 retParam = intersectParam-i; //make the retParam go from 0 to 1
623 break;
624 }
625 }
626 }//for every anchor i
627 }//if is within bbox
628 }
629 return [selAnchorIndex,retParam];
630} //GLSubpath.pathHitTest function
631
535 632
536//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 633//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
537GLSubpath.prototype.pickPath = function (pickX, pickY, pickZ, radius) { 634GLSubpath.prototype.pickPath = function (pickX, pickY, pickZ, radius) {
538 var numAnchors = this._Anchors.length; 635 var numAnchors = this._Anchors.length;
539 var selAnchorIndex = -1; 636 var selAnchorIndex = -1;
540 var retCode = this.SEL_NONE; 637 var retCode = this.SEL_NONE;
638 var retParam = null;
541 var radSq = radius * radius; 639 var radSq = radius * radius;
542 var minDistance = Infinity; 640 var minDistance = Infinity;
543 //check if the clicked location is close to the currently selected anchor position 641 //check if the clicked location is close to the currently selected anchor position
@@ -580,33 +678,36 @@ GLSubpath.prototype.pickPath = function (pickX, pickY, pickZ, radius) {
580 } 678 }
581 } 679 }
582 } 680 }
583 var retParam = null; 681
584 if (retCode !== this.SEL_NONE) { 682 if (retCode !== this.SEL_NONE) {
585 retCode = retCode | this.SEL_PATH; //ensure that path is also selected if anything else is selected 683 retCode = retCode | this.SEL_PATH; //ensure that path is also selected if anything else is selected
586 this._selectedAnchorIndex = selAnchorIndex; 684 this._selectedAnchorIndex = selAnchorIndex;
587 } else { 685 } else {
588 this._selectedAnchorIndex = -1; 686 this._selectedAnchorIndex = -1;
589 var numSegments = this._isClosed ? numAnchors : numAnchors-1; 687 //first check if the input location is within the bounding box
590 for (var i = 0; i < numSegments; i++) { 688 if (this.isWithinBBox(pickX,pickY,pickZ)){
591 var nextIndex = (i+1)%numAnchors; 689 var numSegments = this._isClosed ? numAnchors : numAnchors-1;
592 //check if the point is close to the bezier segment between anchor i and anchor nextIndex 690 for (var i = 0; i < numSegments; i++) {
593 var controlPoints = Vector.create([Vector.create([this._Anchors[i].getPosX(),this._Anchors[i].getPosY(),this._Anchors[i].getPosZ()]), 691 var nextIndex = (i+1)%numAnchors;
594 Vector.create([this._Anchors[i].getNextX(),this._Anchors[i].getNextY(),this._Anchors[i].getNextZ()]), 692 //check if the point is close to the bezier segment between anchor i and anchor nextIndex
595 Vector.create([this._Anchors[nextIndex].getPrevX(),this._Anchors[nextIndex].getPrevY(),this._Anchors[nextIndex].getPrevZ()]), 693 var controlPoints = Vector.create([Vector.create([this._Anchors[i].getPosX(),this._Anchors[i].getPosY(),this._Anchors[i].getPosZ()]),
596 Vector.create([this._Anchors[nextIndex].getPosX(),this._Anchors[nextIndex].getPosY(),this._Anchors[nextIndex].getPosZ()])]); 694 Vector.create([this._Anchors[i].getNextX(),this._Anchors[i].getNextY(),this._Anchors[i].getNextZ()]),
597 var point = Vector.create([pickX, pickY, pickZ]); 695 Vector.create([this._Anchors[nextIndex].getPrevX(),this._Anchors[nextIndex].getPrevY(),this._Anchors[nextIndex].getPrevZ()]),
598 if (this._isWithinBoundingBox(point, controlPoints, radius)) { 696 Vector.create([this._Anchors[nextIndex].getPosX(),this._Anchors[nextIndex].getPosY(),this._Anchors[nextIndex].getPosZ()])]);
599 //var intersectParam = this._checkIntersection(controlPoints, 0.0, 1.0, point, radius); 697 var point = Vector.create([pickX, pickY, pickZ]);
600 var intersectParam = this._checkIntersectionWithSamples(this._anchorSampleIndex[i], this._anchorSampleIndex[nextIndex], point, radius); 698 if (this._isWithinBoundingBox(point, controlPoints, radius)) {
601 console.log("intersectParam:"+intersectParam); 699 //var intersectParam = this._checkIntersection(controlPoints, 0.0, 1.0, point, radius);
602 if (intersectParam){ 700 var intersectParam = this._checkIntersectionWithSamples(this._anchorSampleIndex[i], this._anchorSampleIndex[nextIndex], point, radius);
603 retCode = retCode | this.SEL_PATH; 701 console.log("intersectParam:"+intersectParam);
604 retParam = intersectParam-i; //make the retParam go from 0 to 1 702 if (intersectParam){
605 this._selectedAnchorIndex = i; 703 retCode = retCode | this.SEL_PATH;
606 break; 704 retParam = intersectParam-i; //make the retParam go from 0 to 1
705 this._selectedAnchorIndex = i;
706 break;
707 }
607 } 708 }
608 } 709 }//for every anchor i
609 }//for every anchor i 710 }//is within bounding box
610 } 711 }
611 this._selectMode = retCode; 712 this._selectMode = retCode;
612 return retParam; 713 return retParam;
diff --git a/js/lib/geom/sub-path.js b/js/lib/geom/sub-path.js
index ab54d1e9..0a65511b 100755
--- a/js/lib/geom/sub-path.js
+++ b/js/lib/geom/sub-path.js
@@ -584,6 +584,90 @@ GLSubpath.prototype.pickAnchor = function (pickX, pickY, pickZ, radius) {
584 return selAnchorIndex; 584 return selAnchorIndex;
585}; 585};
586 586
587GLSubpath.prototype.isWithinBBox =function(x,y,z){