Pārlūkot izejas kodu

SVGLoader: Improved arc command parsing and clean up. See #13919

Mr.doob 7 gadi atpakaļ
vecāks
revīzija
01b263d336
1 mainītis faili ar 29 papildinājumiem un 23 dzēšanām
  1. 29 23
      examples/js/loaders/SVGLoader.js

+ 29 - 23
examples/js/loaders/SVGLoader.js

@@ -221,17 +221,17 @@ THREE.SVGLoader.prototype = {
 						break;
 						break;
 
 
 					case 'A':
 					case 'A':
+						console.warn( command );
 						var numbers = parseFloats( data );
 						var numbers = parseFloats( data );
 						for ( var j = 0, jl = numbers.length; j < jl; j += 7 ) {
 						for ( var j = 0, jl = numbers.length; j < jl; j += 7 ) {
-
+							var start = point.clone();
 							point.x = numbers[ j + 5 ];
 							point.x = numbers[ j + 5 ];
 							point.y = numbers[ j + 6 ];
 							point.y = numbers[ j + 6 ];
-							var radius = { x: numbers[ j ], y: numbers[ j + 1 ] };
-							var x_axis_rotation = numbers[ j + 2 ] * Math.PI / 180;
-							svgEllipsisToThreeEllipsis( path, control, radius, x_axis_rotation, numbers[ j + 3 ], numbers[ j + 4 ], point );
 							control.x = point.x;
 							control.x = point.x;
 							control.y = point.y;
 							control.y = point.y;
-
+							parseArcCommand(
+								path, numbers[ j ], numbers[ j + 1 ], numbers[ j + 2 ], numbers[ j + 3 ], numbers[ j + 4 ], start, point
+							);
 						}
 						}
 						break;
 						break;
 
 
@@ -347,11 +347,14 @@ THREE.SVGLoader.prototype = {
 						console.warn( command );
 						console.warn( command );
 						var numbers = parseFloats( data );
 						var numbers = parseFloats( data );
 						for ( var j = 0, jl = numbers.length; j < jl; j += 7 ) {
 						for ( var j = 0, jl = numbers.length; j < jl; j += 7 ) {
-							// TODO
+							var start = point.clone();
 							point.x += numbers[ j + 5 ];
 							point.x += numbers[ j + 5 ];
 							point.y += numbers[ j + 6 ];
 							point.y += numbers[ j + 6 ];
 							control.x = point.x;
 							control.x = point.x;
 							control.y = point.y;
 							control.y = point.y;
+							parseArcCommand(
+								path, numbers[ j ], numbers[ j + 1 ], numbers[ j + 2 ], numbers[ j + 3 ], numbers[ j + 4 ], start, point
+							);
 						}
 						}
 						break;
 						break;
 
 
@@ -375,7 +378,6 @@ THREE.SVGLoader.prototype = {
 
 
 		}
 		}
 
 
-
 		/**
 		/**
 		 * https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
 		 * https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
 		 * https://mortoray.com/2017/02/16/rendering-an-svg-elliptical-arc-as-bezier-curves/ Appendix: Endpoint to center arc conversion
 		 * https://mortoray.com/2017/02/16/rendering-an-svg-elliptical-arc-as-bezier-curves/ Appendix: Endpoint to center arc conversion
@@ -384,35 +386,39 @@ THREE.SVGLoader.prototype = {
 		 * To
 		 * To
 		 * aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation
 		 * aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation
 		 */
 		 */
-		function svgEllipsisToThreeEllipsis( path, start, radius, x_axis_rotation, large_arc_flag, sweep_flag, end ) {
 
 
-			//F.6.6 Correction of out-of-range radii
-			//Step 2: Ensure radii are positive
-			var rX = Math.abs( radius.x );
-			var rY = Math.abs( radius.y );
+		var vector = new THREE.Vector2();
 
 
-			// Step 1: Compute (x1′, y1′)
-			var midDist = new THREE.Vector2().subVectors( start, end ).multiplyScalar( 0.5 );
+		function parseArcCommand( path, rx, ry, x_axis_rotation, large_arc_flag, sweep_flag, start, end ) {
+
+			x_axis_rotation = x_axis_rotation * Math.PI / 180;
+
+			// Ensure radii are positive
+			var rX = Math.abs( rx );
+			var rY = Math.abs( ry );
+
+			// Compute (x1′, y1′)
+			var midDist = vector.subVectors( start, end ).multiplyScalar( 0.5 );
 			var x1p = Math.cos( x_axis_rotation ) * midDist.x + Math.sin( x_axis_rotation ) * midDist.y;
 			var x1p = Math.cos( x_axis_rotation ) * midDist.x + Math.sin( x_axis_rotation ) * midDist.y;
 			var y1p = - Math.sin( x_axis_rotation ) * midDist.x + Math.cos( x_axis_rotation ) * midDist.y;
 			var y1p = - Math.sin( x_axis_rotation ) * midDist.x + Math.cos( x_axis_rotation ) * midDist.y;
 
 
-			// Step 2: Compute (cx′, cy′)
+			// Compute (cx′, cy′)
 			var rxs = rX * rX;
 			var rxs = rX * rX;
 			var rys = rY * rY;
 			var rys = rY * rY;
 			var x1ps = x1p * x1p;
 			var x1ps = x1p * x1p;
 			var y1ps = y1p * y1p;
 			var y1ps = y1p * y1p;
 
 
-			//Step 3: Ensure radii are large enough
+			// Ensure radii are large enough
 			var cr = x1ps / rxs + y1ps / rys;
 			var cr = x1ps / rxs + y1ps / rys;
-			if (cr > 1) {
-				//scale up rX,rY equally so cr == 1
-				var s = Math.sqrt(cr);
+			if ( cr > 1 ) {
+				// scale up rX,rY equally so cr == 1
+				var s = Math.sqrt( cr );
 				rX = s * rX;
 				rX = s * rX;
 				rY = s * rY;
 				rY = s * rY;
 				rxs = rX * rX;
 				rxs = rX * rX;
 				rys = rY * rY;
 				rys = rY * rY;
 			}
 			}
-			
+
 			var dq = ( rxs * y1ps + rys * x1ps );
 			var dq = ( rxs * y1ps + rys * x1ps );
 			var pq = ( rxs * rys - dq ) / dq;
 			var pq = ( rxs * rys - dq ) / dq;
 			var q = Math.sqrt( pq );
 			var q = Math.sqrt( pq );
@@ -425,8 +431,8 @@ THREE.SVGLoader.prototype = {
 			var cy = Math.sin( x_axis_rotation ) * cxp + Math.cos( x_axis_rotation ) * cyp + ( start.y + end.y ) / 2;
 			var cy = Math.sin( x_axis_rotation ) * cxp + Math.cos( x_axis_rotation ) * cyp + ( start.y + end.y ) / 2;
 
 
 			// Step 4: Compute θ1 and Δθ
 			// Step 4: Compute θ1 and Δθ
-			var startAngle = new THREE.Vector2( ( x1p - cxp ) / rX, ( y1p - cyp ) / rY ).angle();
-			var endAngle = new THREE.Vector2( ( - x1p - cxp ) / rX, ( - y1p - cyp ) / rY ).angle();
+			var startAngle = vector.set( ( x1p - cxp ) / rX, ( y1p - cyp ) / rY ).angle();
+			var endAngle = vector.set( ( - x1p - cxp ) / rX, ( - y1p - cyp ) / rY ).angle();
 			if ( ! sweep_flag ) endAngle -= 2 * Math.PI;
 			if ( ! sweep_flag ) endAngle -= 2 * Math.PI;
 
 
 			path.currentPath.absellipse( cx, cy, rX, rY, startAngle, endAngle, endAngle > startAngle, x_axis_rotation );
 			path.currentPath.absellipse( cx, cy, rX, rY, startAngle, endAngle, endAngle > startAngle, x_axis_rotation );
@@ -647,4 +653,4 @@ THREE.SVGLoader.prototype = {
 
 
 	}
 	}
 
 
-};
+};