我怀疑(尽管被证明是错误的)如果没有关于形状的几何数据,基于像素的操作可能是唯一的方法。
如果有几何数据,那么可以只对形状中的点与其他点之间的距离进行线性检查(想到的第一个简单的解决方案——更好的解决方案)。
即使形状是用户生成的(如绘图),也可以在绘图期间对点进行采样以获取点数据,依此类推。我把它放在一边,因为我认为其中任何一个都会比我下面的解决方案更快/更有效(仅假设像素)。
话虽如此,这个解决方案的工作原理是使用 BitmapData 的 hitTest() 检查两个形状是否发生碰撞。它几乎没有效率,不可否认,我不久前刚醒来,并决定这是一个很好的晨练。我没有测试任何错误情况(也就是,如果点在形状内)。
它的工作原理是从点末端开始并在其周围绘制越来越大的圆圈,在每一步将其转换为位图并使用 BitmapData 的 hitTest()。当它认为位图相交/接触时,围绕该点的圆的半径将是与形状最近的距离。
但是,可以通过调整“探针/步长”来提高效率(类似于二分搜索比线性搜索更有效)。但是,我将把它留给读者(代码 cmets 中的示例)。
import flash.display.Shape;
import flash.geom.Point;
import flash.display.BitmapData;
import flash.display.Bitmap;
// assumptions: the movie clip is currenly the only thing on the stage
// first generate the first BitmapData by taking all the pixels on the stage (which should just contain the movieclip)
var stagePixels:BitmapData = new BitmapData(this.stage.stageWidth, this.stage.stageHeight, true, 0xffffff);
stagePixels.draw(this);
function getDistance(inputPoint:Point):int {
var currentSearchDistance:int = 1;
var result:Boolean = false;
var zeroPoint:Point = new Point(0, 0); // just a common reference point for the hitTest() call
var pointShape:Shape;
while(result == false){
// create the shape and draw the circle around the point
pointShape = new Shape();
pointShape.graphics.lineStyle(1);
pointShape.graphics.drawCircle(inputPoint.x, inputPoint.y, currentSearchDistance);
// convert to BitmapData
var pointPixels:BitmapData = new BitmapData(this.stage.stageWidth, this.stage.stageHeight, true, 0xffffff);
pointPixels.draw(pointShape);
// left this here to show the steps and what it is doing
// will slow down stage rendering though since there are potentially a lot of bitmaps being added to the stage
this.addChild(new Bitmap(pointPixels));
result = stagePixels.hitTest(zeroPoint, 0xff, pointPixels, zeroPoint);
// for now, increase the search distance by 1 only, so can return true when it hits the shape for the first time.
// This can be optimized to take larger steps (and smaller) steps as well with multiple probes.
// ex:
// take a big step (+50)... didn't hit shape
// so take another big step (+50)... hit shape so we know the point is between the first 50 to 100
// take maybe half a step back (-25)... hit shape, so we know the point is between the first 50 and 75
// take another half step back (-12)... didn't hit shape so we know the point is between 62 abd 75...etc
// thus can slowly close in on the result instead of taking every small step (would have tkaen 62+ checks to get to this point vs 5)
// (and can also decide to quite early for a "good enough" result)
currentSearchDistance++;
}
return currentSearchDistance;
}
var dot:Point = new Point(100, 100); // input point here
trace(getDistance(dot));
edit:决定添加一张图片来展示它在做什么。