flash on 2012-9-2
♥0 |
Line 135 |
Modified 2012-09-02 16:19:17 |
MIT License
archived:2017-03-20 14:55:01
ActionScript3 source code
/**
* Copyright yasnis ( http://wonderfl.net/user/yasnis )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/d8sL
*/
package {
import flash.display.Sprite;
public class FlashTest extends Sprite {
public function FlashTest() {
// write as3 code here..
}
}
}
import flash.printing.PrintJobOrientation;
import flash.geom.Point;
class ConvexPolygon {
private var vertices:Vector.<Point>; // 頂点
private var edges:Vector.<LineSegment>; // 辺
public function ConvexPolygon(v:Vector.<Point>){
var n:uint = v.length;
if(n<3) throw new Error('');
vertices = v;
edges = new Vector.<LineSegment>();
//基準となるCCW値を計算
var ccw0:Number = GeomUtils.ccw(vertices[0],vertices[1],vertices[2]);
if (ccw0 == 0) { // ゼロの場合はエラー
throw new Error("Polygon is not convex.");
}
for (var i:int = 1; i < n; i++) {
var v1:Point = vertices[i]; // i番目の頂点
var v2:Point = vertices[(i+1)%n]; // v1の次の頂点
var v3:Point = vertices[(i+2)%n]; // v2の次の頂点
var ccw:Number = GeomUtils.ccw(v1, v2, v3); // CCW値を計算
if (ccw0 * ccw <= 0) { // 基準値と符号が異なる,またはゼロの場合はエラー
throw new Error("Polygon is not convex.");
}
}
//線分を登録
for (var j:int = 0; j < n; j++) {
var p1:Point = vertices[j];
var p2:Point = vertices[(j+1)%n];
// 2つの頂点から辺の線分を作成して登録
edges.push(new LineSegment(p1,p2));
}
}
public function getArea():Number {
var crossSum:Number = 0; // 外積の合計
var n:int = vertices.length;
// 頂点を巡回
for (var i:int = 0; i < n; i++) {
var v1:Point = vertices[i];
var v2:Point = vertices[(i+1)%n];
// 外積を計算
var cross:Number = GeomUtils.cross(v1, v2);
crossSum += cross; // 外積を加算
}
return Math.abs(crossSum / 2.0);
}
// 指定位置の頂点を取得
public function getVertex(index:int):Point {
return vertices[index];
}
// 指定位置の辺を取得
public function getEdge(index:int):LineSegment {
return edges[index];
}
// 辺の数(=角数)を取得
public function getEdgeCound():int {
return edges.length;
}
}
class GeomUtils {
public static function cross(v1:Point, v2:Point):Number {
return v1.x * v2.y - v2.x * v1.y;
}
public static function ccw(v1:Point, v2:Point, v3:Point):Number {
return cross(new Point(v2.x-v1.x,v2.y-v1.y),new Point(v3.x-v2.x,v3.y-v2.y));
}
public static function dot(v1:Point, v2:Point):Number {
return v1.x * v2.x + v1.y * v2.y;
}
}
class LineSegment {
private var v1:Point;
private var v2:Point;
public function LineSegment(v1:Point,v2:Point){
this.v1 = v1;
this.v2 = v2;
}
public function toLine():Line {
return Line.fromPoints(v1,v2);
}
//直線との交差チェック
public function intersectsToLine(line:Line):Boolean {
var t1:Number = line.a * v1.x + line.b * v1.y + line.c; // 端点1の座標を直線の式に代入
var t2:Number = line.a * v2.x + line.b * v2.y + line.c; // 端点2の座標を直線の式に代入
return t1 * t2 <= 0; // 不等式の判定
}
//セグメントとの交差チェック
public function intersectsToSegment(seg:LineSegment):Boolean {
return intersectsToLine(seg.toLine()) && seg.intersectsToLine(toLine());
}
//
public function getIntersectionPointByLine(line:Line):Point {
if (!intersectsToLine(line)) {
return null; // 交差しない場合はnullを返す
}
return line.getIntersectionPoint(toLine());
}
//
public function getIntersectionPointBySeg(seg:LineSegment):Point {
if (!intersectsToSegment(seg)) {
return null; // 交差しない場合はnullを返す
}
return seg.toLine().getIntersectionPoint(toLine());
}
// sが自線分の「両側」にあるかどうかを調べる
private function bothSides(seg:LineSegment):Boolean {
var ccw1:Number = GeomUtils.ccw(v1, seg.v1, v2);
var ccw2:Number = GeomUtils.ccw(v1, seg.v2, v2);
if (ccw1 == 0 && ccw2 == 0) { // sと自線分が一直線上にある場合
// sのいずれか1つの端点が自線分を内分していれば,sは自線分と共有部分を持つので
// trueを返す
return isInternal(seg.v1.x, seg.v1.y) || isInternal(seg.v2.x, seg.v2.y);
} else { // それ以外の場合
// CCW値の符号が異なる場合にtrueを返す
return ccw1 * ccw2 <= 0;
}
}
// (x, y)が自線分を内分しているかどうかを調べる
private function isInternal(x:Number,y:Number):Boolean {
// (x, y)から端点に向かうベクトルの内積がゼロ以下であれば内分と見なす
return GeomUtils.dot(new Point(v1.x - x, v1.y - y), new Point(v2.x - x, v2.y - y)) <= 0;
}
}
class Line {
public var a:Number;
public var b:Number;
public var c:Number;
static public function fromPoints(v1:Point,v2:Point):Line{
var dx:Number = v2.x - v1.x;
var dy:Number = v2.y - v1.y;
return new Line(dy, -dx, dx * v1.y - dy * v1.x);
}
public function Line(a:Number, b:Number, c:Number) {
this.a = a;
this.b = b;
this.c = c;
}
public function getIntersectionPoint(line:Line):Point {
var d:Number = a * line.b - line.a * b;
if (d == 0) {
return null; // 直線が平行の場合はnullを返す
}
var x:Number = (b * line.c - line.b * c) / d;
var y:Number = (line.a * c - a * line.c) / d;
return new Point(x, y);
}
}