aboutsummaryrefslogtreecommitdiff
path: root/js/tools/PenTool.js
diff options
context:
space:
mode:
authorPushkar Joshi2012-04-17 17:38:36 -0700
committerPushkar Joshi2012-04-17 17:38:36 -0700
commit5bac19550ae74bb5561d1e1fbb55bdac8c5e3dd1 (patch)
treef35c79ef130968360f00c8d015f70141d44fa57d /js/tools/PenTool.js
parent2165b91022d3585720db881cf97bc971eb7fcce8 (diff)
downloadninja-5bac19550ae74bb5561d1e1fbb55bdac8c5e3dd1.tar.gz
Fairly stable version of polyline drawing code that works for paths on XY, YZ, XZ planes.
Current bugs: if the new point increases the bbox of the canvas, the entire canvas is shifted (due to inconsistency with center of rotation) AND the first two points added to planes other than XY have incorrect local coordinates (due to missing local coordinates)
Diffstat (limited to 'js/tools/PenTool.js')
-rwxr-xr-xjs/tools/PenTool.js97
1 files changed, 32 insertions, 65 deletions
diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js
index 7bc0364e..8abb41ef 100755
--- a/js/tools/PenTool.js
+++ b/js/tools/PenTool.js
@@ -735,87 +735,54 @@ exports.PenTool = Montage.create(ShapeTool, {
735 var currAnchor = null; 735 var currAnchor = null;
736 var xAdjustment = snapManager.getStageWidth()*0.5; 736 var xAdjustment = snapManager.getStageWidth()*0.5;
737 var yAdjustment = snapManager.getStageHeight()*0.5; 737 var yAdjustment = snapManager.getStageHeight()*0.5;
738 var localPos = [[0,0,0,0],[0,0,0,0],[0,0,0,0]]; 738
739 //if there already is a subpath canvas, it means the anchor points are in local space
740 // so convert them to stage world space
741 var numAnchors = this._selectedSubpath.getNumAnchors(); 739 var numAnchors = this._selectedSubpath.getNumAnchors();
740 var bboxMin=null, bboxMax=null;
742 if (this._selectedSubpathCanvas) { 741 if (this._selectedSubpathCanvas) {
743 //this transformation will take the path points from local space to stage world space 742 //if there already is a subpath canvas, it means the anchor points are in local space
744 // *without* taking into account the transformation applied to this canvas 743 // so convert them to stage world space
745 // (this is because we use the center of the bbox to find a place for the canvas) 744 //compute the bbox in local space
746 var localToStageWorldMat = ViewUtils.getObjToStageWorldMatrix(this._selectedSubpathCanvas, false);//ViewUtils.getLocalToStageWorldMatrix(this._selectedSubpathCanvas, true, false); 745 this._selectedSubpath.createSamples(false);
747 for (i=0;i<numAnchors;i++){ 746 bboxMin = this._selectedSubpath.getBBoxMin();
748 //convert this anchor from local to stage world 747 bboxMax = this._selectedSubpath.getBBoxMax();
749 var currAnchor = this._selectedSubpath.getAnchor(i); 748
750 localPos[0] = [currAnchor.getPrevX(), currAnchor.getPrevY(), currAnchor.getPrevZ(),1]; 749 // *********** Test for Too Large Canvas *************
751 localPos[1] = [currAnchor.getPosX(), currAnchor.getPosY(), currAnchor.getPosZ(),1]; 750 //check if the last point added made this canvas is now bigger than the max canvas size
752 localPos[2] = [currAnchor.getNextX(), currAnchor.getNextY(), currAnchor.getNextZ(),1]; 751 var canvasTooLarge = false;
753 for (d=0;d<3;d++) { 752 for (d=0;d<3;d++){
754 localPos[d] = MathUtils.transformAndDivideHomogeneousPoint(localPos[d], localToStageWorldMat); 753 if (bboxMax[d]-bboxMin[d]>this._MAX_CANVAS_DIMENSION){
755 //add half the stage width and height to the X and Y coord. 754 canvasTooLarge = true;
756 localPos[d][0]+= xAdjustment;
757 localPos[d][1]+= yAdjustment;
758 } 755 }
759 currAnchor.setPrevPos(localPos[0][0],localPos[0][1],localPos[0][2]);
760 currAnchor.setPos(localPos[1][0],localPos[1][1],localPos[1][2]);
761 currAnchor.setNextPos(localPos[2][0],localPos[2][1],localPos[2][2]);
762 } 756 }
763 this._selectedSubpath.makeDirty(); 757 if (canvasTooLarge){
764 }
765
766 //compute the bbox in stage-world space
767 this._selectedSubpath.createSamples(true); //we need to compute samples to get the bounding box center in stage world space
768 var bboxMin = this._selectedSubpath.getBBoxMin();
769 var bboxMax = this._selectedSubpath.getBBoxMax();
770
771 //check if the last point added made this canvas is now bigger than the max canvas size
772 for (d=0;d<3;d++){
773 if (bboxMax[d]-bboxMin[d]>this._MAX_CANVAS_DIMENSION){
774 console.log("PEN: Warning! Ignoring last added point because canvas size too large"); 758 console.log("PEN: Warning! Ignoring last added point because canvas size too large");
775 this._selectedSubpath.removeAnchor(numAnchors-1); 759 this._selectedSubpath.removeAnchor(numAnchors-1);
776 numAnchors--; 760 numAnchors--;
761
777 //recompute the bbox of this subpath 762 //recompute the bbox of this subpath
778 this._selectedSubpath.createSamples(true); 763 this._selectedSubpath.createSamples(false);
779 bboxMin = this._selectedSubpath.getBBoxMin(); 764 bboxMin = this._selectedSubpath.getBBoxMin();
780 bboxMax = this._selectedSubpath.getBBoxMax(); 765 bboxMax = this._selectedSubpath.getBBoxMax();
781 break;
782 } 766 }
783 }
784 767
768 //convert the midpoint of this bbox to stage world space
769 var bboxMid = VecUtils.vecInterpolate(3, bboxMin, bboxMax, 0.5);
770 //this._selectedSubpathCanvasCenter = ViewUtils.localToStageWorld(bboxMid, this._selectedSubpathCanvas);
771 var localToStageWorldMat = ViewUtils.getLocalToStageWorldMatrix(this._selectedSubpathCanvas, false, false);
772 this._selectedSubpathCanvasCenter = MathUtils.transformAndDivideHomogeneousPoint(bboxMid, localToStageWorldMat);
773 this._selectedSubpathCanvasCenter[0]+= xAdjustment;
774 this._selectedSubpathCanvasCenter[1]+= yAdjustment;
775 } else {
776 //compute the bbox in stage-world space (the points are already in stage world space)
777 this._selectedSubpath.createSamples(true);
778 bboxMin = this._selectedSubpath.getBBoxMin();
779 bboxMax = this._selectedSubpath.getBBoxMax();
780 this._selectedSubpathCanvasCenter = VecUtils.vecInterpolate(3, bboxMin, bboxMax, 0.5);
785 781
786 this._selectedSubpathCanvasCenter = VecUtils.vecInterpolate(3, bboxMin, bboxMax, 0.5); 782 //todo convert the path points into local coordinates
787 783
788 //update the plane matrix of this subpath by querying the element mediator
789 if (this._selectedSubpathCanvas) {
790 this._selectedSubpathPlaneMat = ElementMediator.getMatrix(this._selectedSubpathCanvas);
791 } 784 }
792 var planeMatInv = glmat4.inverse(this._selectedSubpathPlaneMat, []);
793
794 // ***** compute local coordinates of the anchor points *****
795 for (i=0;i<numAnchors;i++){
796 var currAnchor = this._selectedSubpath.getAnchor(i);
797
798 localPos[0] = [currAnchor.getPrevX(), currAnchor.getPrevY(), currAnchor.getPrevZ(),1];
799 localPos[1] = [currAnchor.getPosX(), currAnchor.getPosY(), currAnchor.getPosZ(),1];
800 localPos[2] = [currAnchor.getNextX(), currAnchor.getNextY(), currAnchor.getNextZ(),1];
801 for (d=0;d<3;d++) {
802 localPos[d][0]-= this._selectedSubpathCanvasCenter[0];
803 localPos[d][1]-= this._selectedSubpathCanvasCenter[1];
804 localPos[d][2]-= this._selectedSubpathCanvasCenter[2];
805
806 // ***** unproject all the centered points and convert them to 2D (plane space)*****
807 // (undo the projection step performed by the browser)
808 localPos[d] = this._unprojectPt(localPos[d], 1400); //todo get the perspective distance from the canvas
809 localPos[d] = MathUtils.transformPoint(localPos[d], planeMatInv);
810
811 //explicitly remove the third (Z) component since it should always be zero
812 localPos[d][2]=0;
813 }
814 785
815 currAnchor.setPrevPos(localPos[0][0],localPos[0][1],localPos[0][2]);
816 currAnchor.setPos(localPos[1][0],localPos[1][1],localPos[1][2]);
817 currAnchor.setNextPos(localPos[2][0],localPos[2][1],localPos[2][2]);
818 }
819 this._selectedSubpath.makeDirty(); 786 this._selectedSubpath.makeDirty();
820 this._selectedSubpath.createSamples(false); 787 this._selectedSubpath.createSamples(false);
821 this._selectedSubpath.offsetPerBBoxMin(); 788 this._selectedSubpath.offsetPerBBoxMin();