Beautifl - Flash Gallery

Thumbnail : Sierpinski Valentine
Sierpinski Valentine
makc3d 2010-02-15 see code comments

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

package  {
	import flash.display.Sprite;
	import flash.geom.Point;
	import flash.text.TextField;
	import flash.text.TextFormat;
	
	/**
	 * Inspired by xkcd №543.
	 * @author makc
	 */
	[SWF(width=800,height=800)]
	public class Heart3 extends Sprite {

		// Change this to your message
		public const text:String = "MAKA+OKA=";

		public function Heart3 () {
			mouseEnabled = false; mouseChildren = false;

			// triangle
			var r:Number = 0.5 * 800;
			var x1:Number = r * (1 + Math.cos ( - Math.PI / 6)), y1:Number = r * (1 - Math.sin ( - Math.PI / 6));
			var x2:Number = r * (1 + Math.cos ( + Math.PI / 2)), y2:Number = r * (1 -  Math.sin ( + Math.PI / 2));
			var x3:Number = r * (1 + Math.cos ( 7*Math.PI / 6)), y3:Number = r * (1 - Math.sin ( 7*Math.PI / 6));

			graphics.lineStyle (4, 0xFF7F7F); graphics.moveTo (x1, y1);
			graphics.lineTo (x2, y2); graphics.lineTo (x3, y3); graphics.lineTo (x1, y1);

			scaleY = 0.8; y = 150;

			// generate basic heart, y = sqrt(|x|)/2 +/- sqrt((1-x^2)/2)
			// http://www.mathematische-basteleien.de/heart.htm
			heart = new Vector.<Point> ();
			var a:Number, b:Number;
			for (x1 = -1; x1 < +1; x1 += 0.01) {
				a = Math.sqrt (Math.abs (x1)) / 2; b = Math.sqrt ((1 - x1 * x1) / 2);
				heart.push (new Point (x1, -a -b));
			}
			for (x1 = +1; x1 > -1; x1 -= 0.01) {
				a = Math.sqrt (Math.abs (x1)) / 2; b = Math.sqrt ((1 - x1 * x1) / 2);
				heart.push (new Point (x1, -a +b));
			}

			// hearts
			var i:int, j:int = 0;
			for (i = 0; i < data.length; i++) {
				drawHeartShape (data [i].x, data [i].y, data [i].s);

				// draw message
				var p:Number = 0;
				while (int (p) < heart.length) {
					// get letter
					var t:TextField = new TextField; t.text = text.charAt (j);
					t.autoSize = "left"; t.selectable = false; t.textColor = 0xFF7F7F;
					var f:TextFormat = t.getTextFormat (); f.size = int (Math.sqrt (data [i].s)); t.setTextFormat (f);
					var w:Number = t.getRect (t).width;

					var found:Boolean = false;
					var p0:Point = heart [(int(p) -1 + heart.length) % heart.length];
					var p1:Point = heart [(int(p) +0 + heart.length) % heart.length];
					var p2:Point = heart [(int(p) +1 + heart.length) % heart.length];
					var p3:Point = heart [(int(p) +2 + heart.length) % heart.length];
					var pA:Point = spline (p0, p1, p2, p3, p - int (p));
					var pB:Point = pA.clone ();
					while (Point.distance (pA, pB) * data [i].s < w * 0.8) {
						p += 0.1;
						found = true; if (p > heart.length + 1) { found = false; break; }

						p0 = heart [(int(p) -1 + heart.length) % heart.length];
						p1 = heart [(int(p) +0 + heart.length) % heart.length];
						p2 = heart [(int(p) +1 + heart.length) % heart.length];
						p3 = heart [(int(p) +2 + heart.length) % heart.length];
						pB = spline (p0, p1, p2, p3, p - int (p));

						// hack against the bug near heart's bottom
						if (Math.abs (p - heart.length * 0.75) < 5) found = false;
					}

					if (found) {
						var sp:Sprite = new Sprite; sp.addChild (t); t.x = - 0.1 * Number (f.size); t.y = -0.3 * Number (f.size);
						sp.rotationZ = 180 * Math.atan2 (pA.y - pB.y, pA.x - pB.x) / Math.PI - 180;
						sp.x = pA.x * data [i].s + data [i].x;
						sp.y = pA.y * data [i].s + data [i].y;
						addChild (sp);

						j++; j %= text.length;
					}
				}
			}
		}

		private var heart:Vector.<Point>;

		private function drawHeartShape (x:Number, y:Number, s:Number):void {
			graphics.lineStyle (2, 0xFF7F7F);
			for (var i:int = 0; i < heart.length + 1; i++) {
				graphics [(i == 0) ? "moveTo" : "lineTo"] (x + heart [i % heart.length].x * s, y + heart [i % heart.length].y * s);
			}
		}

		// semi-automatically generated data for 800x800 resolution
		private var data:Array = [
			{x:400,y:463.4002728527412,s:196.5284803188406},
			{x:400,y:244.7215357059613,s:103.64195191022009},
			{x:605.8919056169689,y:546.0052201719955,s:79.80397377233021},
			{x:194.10809438303113,y:546.0052201719955,s:79.80397377233021},
			{x:400,y:129.3481242991984,s:54.85592107055709},
			{x:299.0547058954835,y:573.0302273114212,s:41.70455467724241},
			{x:500.9452941045165,y:573.0302273114212,s:41.70455467724241},
			{x:188.00251285545528,y:454.9444936104119,s:36.4774521056097},
			{x:611.9974871445447,y:454.9444936104119,s:36.4774521056097},
			{x:690.0101580703631,y:579.2084480030462,s:32.250521225621924},
			{x:109.9898419296369,y:579.2084480030462,s:32.250521225621924},
			{x:400,y:68.10115392599255,s:29.08300296915695},
			{x:512.0834618457593,y:257.7894526273012,s:26.893927168101072},
			{x:287.9165381542407,y:257.7894526273012,s:26.893927168101072},
			{x:443.9248610106297,y:585.7494149059057,s:22.668620551237836},
			{x:356.0751389893703,y:585.7494149059057,s:22.668620551237836},
			{x:246.52865941962227,y:587.4881193875335,s:20.434888303512707},
			{x:553.4713405803777,y:587.4881193875335,s:20.434888303512707},
			{x:610.579614258837,y:412.69078743690625,s:20.237200914882123},
			{x:189.42038574116305,y:412.69078743690625,s:20.237200914882123},
			{x:647.4705647085793,y:589.8631541808136,s:16.737865320639685},
			{x:152.52943529142067,y:589.8631541808136,s:16.737865320639685},
			{x:400,y:36.1539272358641,s:15.123563141096383},
			{x:692.1109628505073,y:542.9469659165479,s:15.090049159014598},
			{x:107.88903714949265,y:542.9469659165479,s:15.090049159014598},
			{x:340.93071625428274,y:136.76000382611528,s:14.548912978731096},
			{x:459.06928374571726,y:136.76000382611528,s:14.548912978731096},
			{x:287.43549493234605,y:525.2518965760246,s:14.411672779591754},
			{x:512.564505067654,y:525.2518965760246,s:14.411672779591754},
			{x:511.88300151145086,y:227.80882933549583,s:14.235807507531717},
			{x:288.11699848854914,y:227.80882933549583,s:14.235807507531717},
			{x:539.1352838408202,y:274.89364725118503,s:14.006836630636826},
			{x:260.8647161591798,y:274.89364725118503,s:14.006836630636826},
			{x:76.19026520801708,y:592.1868846346624,s:13.037382744252682},
			{x:723.8097347919829,y:592.1868846346624,s:13.037382744252682},
			{x:479.9866674495861,y:266.8434352390468,s:12.039542768383399},
			{x:320.0133325504139,y:266.8434352390468,s:12.039542768383399},
			{x:193.2125827386044,y:387.1166734388098,s:11.943412765860558},
			{x:606.7874172613956,y:387.1166734388098,s:11.943412765860558},
			{x:148.29466720111668,y:463.2085094396025,s:11.256643181433901},
			{x:651.7053327988833,y:463.2085094396025,s:11.256643181433901},
			{x:571.942359468434,y:462.44292084127665,s:11.247406342765316},
			{x:228.057640531566,y:462.44292084127665,s:11.247406342765316},
			{x:581.985083987005,y:593.6488022985868,s:11.087568677496165},
			{x:218.01491601299495,y:593.6488022985868,s:11.087568677496165},
			{x:415.4868962643668,y:593.7308800932951,s:11.050529938191175},
			{x:384.5131037356332,y:593.7308800932951,s:11.050529938191175},
			{x:471.9467283333652,y:593.6420050947927,s:10.914339462295175},
			{x:328.0532716666348,y:593.6420050947927,s:10.914339462295175},
			{x:527.4853790090419,y:594.3130289418623,s:10.053288353141397},
			{x:272.51462099095806,y:594.3130289418623,s:10.053288353141397},
			{x:175.5389362159185,y:594.8177863382734,s:9.09120064880699},
			{x:624.4610637840815,y:594.8177863382734,s:9.09120064880699},
			{x:289.7346494849771,y:210.47087746672332,s:8.272347889607772},
			{x:510.2653505150229,y:210.47087746672332,s:8.272347889607772},
			{x:691.8393486668356,y:525.4590577846393,s:8.24225621833466},
			{x:108.16065133316442,y:525.4590577846393,s:8.24225621833466},
			{x:493.60489980783314,y:530.6024617180228,s:8.206850306130946},
			{x:306.39510019216686,y:530.6024617180228,s:8.206850306130946},
			{x:450.9999335743487,y:559.8982726340182,s:8.17839759006165},
			{x:349.0000664256513,y:559.8982726340182,s:8.17839759006165},
			{x:246.87875676900148,y:284.9836071222089,s:8.176436646841466},
			{x:553.1212432309985,y:284.9836071222089,s:8.176436646841466},
			{x:131.47086535254493,y:595.6526658679359,s:8.171630583936349},
			{x:668.5291346474551,y:595.6526658679359,s:8.171630583936349},
			{x:431.0348047623411,y:72.49033630965278,s:7.971291854977608},
			{x:368.9651952376589,y:72.49033630965278,s:7.971291854977608},
			{x:400,y:19.1413890151307,s:7.831158068496734},
			{x:603.7587662511505,y:371.42685872036964,s:7.659528844058514},
			{x:196.24123374884948,y:371.42685872036964,s:7.659528844058514},
			{x:250.9503755737096,y:564.4028059779666,s:7.629010838922113},
			{x:549.0496244262904,y:564.4028059779666,s:7.629010838922113},
			{x:459.13323673186824,y:120.67753744265065,s:7.609971035271883},
			{x:340.86676326813176,y:120.67753744265065,s:7.609971035271883},
			{x:325.9426351240836,y:145.5991565180011,s:7.386607280932367},
			{x:474.0573648759164,y:145.5991565180011,s:7.386607280932367},
			{x:335.5574317574501,y:272.31094188429415,s:6.85730082471855},
			{x:464.4425682425499,y:272.31094188429415,s:6.85730082471855},
			{x:519.6740419026464,y:507.80593424569815,s:6.800806283717975},
			{x:280.3259580973536,y:507.80593424569815,s:6.800806283717975},
			{x:707.0290097421966,y:596.4251947375014,s:6.751892362022772},
			{x:92.97099025780335,y:596.4251947375014,s:6.751892362022772},
			{x:213.52264421526343,y:468.02623479021713,s:6.521336960140616},
			{x:586.4773557847366,y:468.02623479021713,s:6.521336960140616},
			{x:357.84703332558274,y:141.4283179435879,s:6.380118315340951},
			{x:442.15296667441726,y:141.4283179435879,s:6.380118315340951},
			{x:148.0749855930917,y:571.119971845299,s:6.1529121631756425},
			{x:651.9250144069083,y:571.119971845299,s:6.1529121631756425},
			{x:75.3259663307108,y:577.8210690966807,s:6.082289765588939},
			{x:724.6740336692892,y:577.8210690966807,s:6.082289765588939},
			{x:651.6508578541689,y:450.7900155200623,s:5.9971901152748615},
			{x:148.34914214583114,y:450.7900155200623,s:5.9971901152748615},
			{x:540.3807234456763,y:259.5883739120327,s:5.947651949943975},
			{x:259.61927655432373,y:259.5883739120327,s:5.947651949943975},
			{x:136.98474612785503,y:469.9063107240945,s:5.868062464753166},
			{x:663.015253872145,y:469.9063107240945,s:5.868062464753166},
			{x:632.4494809522294,y:416.5730267558247,s:5.83220389066264},
			{x:167.55051904777065,y:416.5730267558247,s:5.83220389066264},
			{x:572.3336290139705,y:450.02710691280663,s:5.556828874628991},
			{x:227.6663709860295,y:450.02710691280663,s:5.556828874628991},
			{x:495.1340189771727,y:270.1031073848717,s:5.455987439258024},
			{x:304.8659810228273,y:270.1031073848717,s:5.455987439258024},
			{x:209.59454875485972,y:417.48648076551035,s:5.364822947187349},
			{x:590.4054512451403,y:417.48648076551035,s:5.364822947187349},
			{x:318.92537330091,y:253.6837179386057,s:5.349796864204109},
			{x:481.07462669909,y:253.6837179386057,s:5.349796864204109},
			{x:238.74538954673335,y:291.73224990163,s:5.316515657119453},
			{x:561.2546104532667,y:291.73224990163,s:5.316515657119453},
			{x:240.97270313091576,y:467.302248142194,s:5.297187236137688},
			{x:559.0272968690842,y:467.302248142194,s:5.297187236137688},
			{x:689.9128249110654,y:514.8251562588848,s:5.1880090304184705},
			{x:110.0871750889346,y:514.8251562588848,s:5.1880090304184705},
			{x:291.66641797591,y:199.9527272921987,s:5.1124423884321},
			{x:508.33358202409,y:199.9527272921987,s:5.1124423884321},
			{x:737.6631903205998,y:597.3636012850329,s:5.087250181706622},
			{x:62.336809679400176,y:597.3636012850329,s:5.087250181706622},
			{x:637.0240586451255,y:466.3542338539846,s:5.070570279378444},
			{x:162.97594135487452,y:466.3542338539846,s:5.070570279378444},
			{x:526.5715072788298,y:530.8228532783687,s:4.890537571627647},
			{x:273.4284927211702,y:530.8228532783687,s:4.890537571627647},
			{x:278.52624631486833,y:274.3984374701977,s:4.852794086793438},
			{x:521.4737536851317,y:274.3984374701977,s:4.852794086793438},
			{x:454.4010606086813,y:276.2944767740555,s:4.829513406846672},
			{x:345.5989393913187,y:276.2944767740555,s:4.829513406846672},
			{x:124.4923780541867,y:545.8717821743339,s:4.72908342583105},
			{x:675.5076219458133,y:545.8717821743339,s:4.72908342583105},
			{x:708.2845904016867,y:545.5772367543541,s:4.685356764122844},
			{x:91.71540959831327,y:545.5772367543541,s:4.685356764122844},
			{x:400,y:10.5916220927611,s:4.540829328820109},
			{x:319.12117216037586,y:150.955240489915,s:4.425077967112884},
			{x:480.87882783962414,y:150.955240489915,s:4.425077967112884},
			{x:458.22571359667927,y:111.6516571356915,s:4.3682266168762},
			{x:341.77428640332073,y:111.6516571356915,s:4.3682266168762},
			{x:416.2808527969755,y:37.769800229463726,s:4.093661399791017},
			{x:383.7191472030245,y:37.769800229463726,s:4.093661399791017},
			{x:527.1546252537519,y:230.1003229743801,s:4.033989728894085},
			{x:272.8453747462481,y:230.1003229743801,s:4.033989728894085},
			{x:368.76861893897876,y:63.65822831215337,s:4.010418681195006},
			{x:431.23138106102124,y:63.65822831215337,s:4.010418681195006},
			{x:360.75489358371124,y:77.07122791279107,s:3.8923177260439843},
			{x:439.24510641628876,y:77.07122791279107,s:3.8923177260439843},
			{x:366.27585839806125,y:143.98982488689944,s:3.776627002283931},
			{x:433.72414160193875,y:143.98982488689944,s:3.776627002283931},
			{x:302.94788975967094,y:230.37297371262684,s:3.6981578022241592},
			{x:497.05211024032906,y:230.37297371262684,s:3.6981578022241592},
			{x:422.13006993429735,y:74.68356413021684,s:3.379919509869069},
			{x:377.86993006570265,y:74.68356413021684,s:3.379919509869069}
		];

        /* 
        * Calculates 2D cubic Catmull-Rom spline.
        * @see http://www.mvps.org/directx/articles/catmull/ 
        */ 
        private function spline (p0:Point, p1:Point, p2:Point, p3:Point, t:Number):Point {
            return new Point (
				0.5 * ((          2*p1.x) +
					t * (( -p0.x           +p2.x) +
					t * ((2*p0.x -5*p1.x +4*p2.x -p3.x) +
					t * (  -p0.x +3*p1.x -3*p2.x +p3.x)))),
				0.5 * ((          2*p1.y) +
					t * (( -p0.y           +p2.y) +
					t * ((2*p0.y -5*p1.y +4*p2.y -p3.y) +
					t * (  -p0.y +3*p1.y -3*p2.y +p3.y))))
			);
        }

		private function splineGradient (p0:Point, p1:Point, p2:Point, p3:Point, t:Number):Point {
			return new Point (
				0.5 * (
					-p0.x + p2.x +
					2 * (2 * p0.x - 5 * p1.x + 4 * p2.x - p3.x) * t +
					3 * (-p0.x + 3 * p1.x - 3 * p2.x + p3.x) * t * t
				),
				0.5 * (
					-p0.y + p2.y +
					2 * (2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t +
					3 * (-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * t * t
				)
			);
		}
	}
}