簡體   English   中英

將一個形狀變換為另一個形狀的算法

[英]Algorithm to morph one shape into another.

我正在嘗試將一個“形狀”轉換為另一個“形狀”的算法。 兩種形狀都是任意的,甚至可能具有較小的,不連續的形狀。

我到目前為止的基本思想如下:找到形狀的邊緣,沿着這些邊緣放置點,然后對目標圖像做同樣的事情,然后將點移動到它們的目標。

這是一個例子:

變形

我只是不知道從哪里開始。 上面的圖像是一個簡化,實際用例有更復雜的形狀/輪廓。 我的主要問題是:如何處理不相交的形狀? 我能想到的最好的方法是找出兩個部分之間的最近點,並將它們作為路徑的一部分連接在一起。 但是我該如何實現呢?

我還沒有任何代碼,我還處於規划階段。 我想我要求的是,是否有人可以將我鏈接到任何可能有用的資源,或者給出任何指示。 搜索谷歌已經產生了一些有趣的變形算法,但它們都處理完整的圖像並涉及將圖像分解成碎片以重塑它們,這不是我正在尋找的。

請注意,這將在JavaScript中使用,但如果更容易,可以在PHP中預先計算。

我在JavaScript中找到了一個演示(使用Raphael.js)的輪廓變形和補間動畫,展示了如何使用Raphael.js將一條曲線變形為另一條曲線。

此外, 這個相關的問題 (關於JavaScript中的補間形狀)可能包含一些與此問題相關的答案。

MorpherJS庫也可能適用於此目的。 可以在此處找到使用MorpherJS進行輪廓變形的一些演示。

最好將問題分解為多個可以獨立解決的小問題。 這樣,您在解決此問題后也可以擁有獨立的功能,可以將其添加到某些全局模塊集合中。

首先,我們需要弄清楚from_shape中的哪個像素轉到to_shape中的哪個像素。
我們可以用以下方法解決這個問題:

  1. 將to_shape放在from_shape上。

  2. 對於from_shape中的每個像素,找到其最接近的to_shape像素。
    形狀中的每個像素必須具有唯一的id,該id可以是例如其xy位置。

  3. 現在,您可以記錄from_shape中的每個唯一像素,以及它在to_shape中的唯一像素。

  4. 刪除重疊的形狀並返回原始形狀,
    剛才from_shape中的每個像素都知道to_shape中的目的地。

我們還需要知道每個像素的兄弟姐妹。
兄弟是一個緊挨着另一個像素的像素。
要找到它,轉到一個給定的像素,從中收集半徑為1的所有像素,所有這些像素都是黑色..是像素的兄弟姐妹。 當像素行進到目的地時,該信息對於將形狀保持為單個單元是必要的。 跳過兄弟姐妹會大大加快並簡化變形,但沒有它們,變形過程中形狀可能會變得碎片化。 可能想從一個沒有兄弟的版本開始,看看它是怎么回事。

最后我們實現變形:

  1. 有morph_time_duration。
    對於from_shape中的每個像素,在to_shape中找到它到達目的地的距離。
    該距離除以morph_time_duration,是變形期間像素的速度。
    此外,朝向目的地的角度是行進的角度。
    所以現在你有速度和角度。

  2. 因此,在變形過程的每一幀中,給定的from_pixel現在知道要進入哪個方向,速度,並且它也知道它的兄弟姐妹。 因此,在每個幀中,只需在其方向上以其速度行進之后在其新位置繪制像素。 然后畫一條線給所有像素的兄弟姐妹。

這將顯示你的變形。

這樣做不會很容易,但我可以給你幾個起點。 如果你想要一個簡單的javascript實現,一個很好的起點是: http//raphaeljs.com/animation.html這正是你想做的。 因此,您可以檢查調用的方法,並瀏覽庫源以查看實現的那些方法。

如果你需要在PHP中變換2個圖像,我建議你使用某種擴展而不是在普通的PHP中。 以下是使用ImageMagick執行此操作的示例: http//www.fmwconcepts.com/imagemagick/shapemorph2/index.php

如果你想進一步了解它的內部結構: http//web.mit.edu/manoli/www/ecimorph/ecimorph.html#algo

希望其中一個有所幫助。

簡短的回答,如果你想自己動手,這不是一項簡單的任務。 在這些主題上有大量的數學運算來執行這些非常的變換(最常見的是你會發現最常見的形狀,但很明顯),但這可能會或可能不會被你訪問,並且它不會那么容易找出如何進行非標准轉換。

如果你只是在尋找一種合乎邏輯的方法,那么這就是我開始的地方(多年來沒有完成數學計算,也沒有研究過圖形庫的內部工作原理):

  1. 選擇一個距離,以任何有意義的單位測量,也許是像素。

  2. 確定每個形狀中的每個連續邊緣。 在每個形狀的一個邊緣上選擇一個任意點(例如,在(0,0)表示左上角的平面上,每個形狀上最靠近(0,0)的邊緣點),並在其上對齊單獨的形狀點。 出於轉換的目的,該點將保持靜態,所有其他點將符合它。

  3. 如果您的形狀有兩個或更多不同的邊緣,請按周長排序。 考慮較短的長度從屬於較長的長度。 使用與步驟2中類似的過程來選擇任意點以將這兩個邊連接在一起。

  4. 在您選擇的每個點上,以您在步驟1中選擇的距離間隔計算邊緣周圍的點數。

  5. (作為讀者的練習)將您的不同邊緣上的點整合到目標形狀中,根據需要對齊,縮小或添加邊緣上的點。

或者,您可以選擇任意數量的點而不是任意距離,然后沿着邊緣適當地展開它們適合的距離,然后將這些點一致。

只是拋出一些想法,我真的不知道問題有多深。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM