2013-10-02 4 views
4

볼록 선체 알고리즘 작업을 시작했으며 폴리곤 가장자리를 매끄럽게 만드는 데 사용할 수있는 방법이 무엇인지 궁금합니다. 선체의 윤곽이 매끄럽지 않습니다. 내가하고 싶은 것은 꼭지점을 통과하는 선들을 더 부드럽게 만들어서 그들이 기울어 진 것처럼 보이지 않게하는 것입니다.부드러운 볼록 선체

enter image description here

나는 베지을 구현하기 위해 노력했다 (단지 모양이 선체의 모양처럼 아무것도 실현하기 위해) 모양이 같은 아무것도 다시 B 스플라인 (나는 B를 만들 수 없습니다 사실 - 닫힌 모양을 줄이십시오).

나는 실패하고 누군가가지도 할 수 있기를 희망한다.

+0

catmull rom 스플라인은 보통 그래픽 스무딩에 사용됩니다. 그들은 1 차 주문까지 지속됩니다. – Bathsheba

+0

@ Bathsheba 답장을 보내 주셔서 감사합니다 ...이 방법은 또한 두 점이 적절히 가까운 경우에 볼록 선체 외곽에 매우 많은 선이 생길 수 있음을 압니다. 이것은 다른 방법 중 일부에 대한 문제입니다. 본. 나의 접근 방식이 최선입니까? 나는 그래픽 배경이 아니기 때문에 아무런 참고 점이 없다. 다각형의 바깥 가장자리를 어떻게 다듬을 수 있을까? – beliskna

+0

나는 그래픽 전문가도 아니야. 겸손한 수학자. 하지만 아마도 처음부터 솔루션을 만드는 것을 고려해 볼 수 있습니다. 타원의 세그먼트에서 접합하여 모서리를 둥글게 만듭니다 (일치하는 값과 기울기 및 점을 통과). 타원의 크기는 수축 양의 함수입니다. 수학을 이해하는 데 시간이 좀 걸리지 만 부드럽고 모든 점들을 통과하며 절대로 선체 밖에있을 수 없습니다. – Bathsheba

답변

1

내가 극좌표 Lagrange polynomial으로 정확한 해결책을 찾을 수 있지만, 발견하려고 노력

(주의! 그게 해결책이 아니다), 그 somtimes "부드럽게 곡선은"볼록 다각형 내부에 자리 잡고 있습니다. 첫 번째 파생 조건 일치 조건 (시작 지점)은 theta in [0:2 * pi] 간격 외부에 추가로 움직일 수있는 보이지 않는 점을 추가하여 근본적으로 해결할 수 있습니다. 그러나 위의 문제는 어쨌든 내 마음에 풀리지 않습니다. 여기

내 attemptions와 루아 스크립트 ( qhull, rbox 사용은 ( qhull 툴 체인)과 의 gnuplot 유틸리티에서)

function using() 
    return error('using: ' .. arg[0] .. ' <number of points>') 
end 

function points_from_file(infile) 
    local points = {} 
    local infile = io.open(infile, 'r') 
    local d = infile:read('*number') 
    if d ~= 2 then 
     error('dimensions is not two') 
    end 
    local n = infile:read('*number') 
    while true do 
     local x, y = infile:read('*number', '*number') 
     if not x and not y then 
      break 
     end 
     if not x or not y then 
      error('wrong format of input file: line does not contain two coordinates') 
     end 
     table.insert(points, {x, y}) 
    end 
    infile:close() 
    if n ~= #points then 
     error('second line not contain real count of points') 
    end 
    return points 
end 

if not arg then 
    error("script should use as standalone") 
end 
if #arg ~= 1 then 
    using() 
end 
local n = tonumber(arg[1]) 
if not n then 
    using() 
end 
local bounding_box = math.sqrt(math.pi)/2.0 
local fnp = os.tmpname() 
local fnchp = os.tmpname() 
os.execute('rbox ' .. n .. ' B' .. bounding_box .. ' D2 n t | tee ' .. fnp .. ' | qhull p | tee ' .. fnchp .. ' > nul') -- Windows specific part is "> nul" 
local sp = points_from_file(fnp) -- source points 
os.remove(fnp) 
local chp = points_from_file(fnchp) -- convex hull points 
os.remove(fnchp) 
local m = #chp 
if m < 3 then 
    io.stderr:write('convex hull consist of less than three points') 
    return 
end 
local pole = {0.0, 0.0} -- offset of polar origin relative to cartesian origin 
for _, point in ipairs(chp) do 
    pole[1] = pole[1] + point[1] 
    pole[2] = pole[2] + point[2] 
end 
pole[1] = pole[1]/m 
pole[2] = pole[2]/m 
print("pole = ", pole[1], pole[2]) 
local chcc = {} 
for _, point in ipairs(chp) do 
    table.insert(chcc, {point[1] - pole[1], point[2] - pole[2]}) 
end 
local theta_min = 2.0 * math.pi -- angle between abscissa ort of cartesian and ort of polar coordinates 
local rho_mean = 0.0 
local rho_max = 0.0 
local chpc = {} -- {theta, rho} pairs 
for _, point in ipairs(chcc) do 
    local rho = math.sqrt(point[1] * point[1] + point[2] * point[2]) 
    local theta = math.atan2(point[2], point[1]) 
    if theta < 0.0 then -- [-pi:pi] -> [0:2 * pi] 
     theta = theta + 2.0 * math.pi 
    end 
    table.insert(chpc, {theta, rho}) 
    if theta_min > theta then 
     theta_min = theta 
    end 
    rho_mean = rho_mean + rho 
    if rho_max < rho then 
     rho_max = rho 
    end 
end 
theta_min = -theta_min 
rho_mean = rho_mean/m 
rho_max = rho_max/rho_mean 
for pos, point in ipairs(chpc) do 
    local theta = (point[1] + theta_min)/math.pi -- [0:2 * pi] -> [0:2] 
    local rho = point[2]/rho_mean 
    table.remove(chpc, pos) 
    table.insert(chpc, pos, {theta, rho}) 
end 
table.sort(chpc, function (lhs, rhs) return lhs[1] < rhs[1] end) 
-- table.insert(chpc, {chpc[#chpc][1] - 2.0 * math.pi, chpc[#chpc][2]}) 
table.insert(chpc, {2.0, chpc[1][2]}) 
-- table.sort(chpc, function (lhs, rhs) return lhs[1] < rhs[1] end) 

local solution = {} 
solution.x = {} 
solution.y = {} 
for _, point in ipairs(chpc) do 
    table.insert(solution.x, point[1]) 
    table.insert(solution.y, point[2]) 
end 
solution.c = {} 
for i, xi in ipairs(solution.x) do 
    local c = solution.y[i] 
    for j, xj in ipairs(solution.x) do 
     if i ~= j then 
      c = c/(xi - xj) 
     end 
    end 
    solution.c[i] = c 
end 
function solution:monomial(i, x) 
    local y = self.c[i] 
    for j, xj in ipairs(solution.x) do 
     if xj == x then 
      if i == j then 
       return self.y[i] 
      else 
       return 0.0 
      end 
     end 
     if i ~= j then 
      y = y * (x - xj) 
     end 
    end 
    return y 
end 
function solution:polynomial(x) 
    local y = self:monomial(1, x) 
    for i = 2, #solution.y do 
     y = y + self:monomial(i, x) 
    end 
    return y 
end 

local gnuplot = io.popen('gnuplot', 'w') 

gnuplot:write('reset;\n') 
gnuplot:write('set terminal wxt 1;\n') 
gnuplot:write(string.format('set xrange [%f:%f];\n', -bounding_box, bounding_box)) 
gnuplot:write(string.format('set yrange [%f:%f];\n', -bounding_box, bounding_box)) 
gnuplot:write('set size square;\n') 
gnuplot:write(string.format('set xtics %f;\n', 0.1)) 
gnuplot:write(string.format('set ytics %f;\n', 0.1)) 
gnuplot:write('set grid xtics ytics;\n') 
gnuplot:write('plot "-" using 1:2 notitle with points, "-" using 1:2:3:4 notitle with vectors;\n') 
for _, point in ipairs(sp) do 
    gnuplot:write(string.format('%f %f\n', point[1], point[2])) 
end 
gnuplot:write('e\n') 
for _, point in ipairs(chcc) do 
    gnuplot:write(string.format('%f %f %f %f\n', pole[1], pole[2], point[1], point[2])) 
end 
gnuplot:write('e\n') 
gnuplot:flush(); 

gnuplot:write('reset;\n') 
gnuplot:write('set terminal wxt 2;\n') 
gnuplot:write('set border 0;\n') 
gnuplot:write('unset xtics;\n') 
gnuplot:write('unset ytics;\n') 
gnuplot:write('set polar;\n') 
gnuplot:write('set grid polar;\n') 
gnuplot:write('set trange [-pi:2 * pi];\n') 
gnuplot:write(string.format('set rrange [-0:%f];\n', rho_max)) 
gnuplot:write('set size square;\n') 
gnuplot:write('set view equal xy;\n') 
-- gnuplot:write(string.format('set xlabel "%f";\n', rho_mean - 1.0)) 
gnuplot:write(string.format('set arrow 1 from 0,0 to %f,%f;\n', rho_max * math.cos(theta_min), rho_max * math.sin(theta_min))) 
gnuplot:write(string.format('set label 1 " origin" at %f,%f left rotate by %f;\n', rho_max * math.cos(theta_min), rho_max * math.sin(theta_min), math.deg(theta_min))) 
gnuplot:write('plot "-" using 1:2:3:4 notitle with vectors, "-" using 1:2 notitle with lines, "-" using 1:2 notitle with lines;\n') 
for _, point in ipairs(chpc) do 
    gnuplot:write(string.format('0 0 %f %f\n', point[1] * math.pi, point[2])) 
end 
gnuplot:write('e\n') 
for _, point in ipairs(chpc) do 
    gnuplot:write(string.format('%f %f\n', point[1] * math.pi, point[2])) 
end 
gnuplot:write('e\n') 
do 
    local points_count = 512 
    local dx = 2.0/points_count 
    local x = 0.0 
    for i = 1, points_count do 
     gnuplot:write(string.format('%f %f\n', x * math.pi, solution:polynomial(x))) 
     x = x + dx 
    end 
    gnuplot:write('e\n') 
end 
gnuplot:flush(); 

gnuplot:write('reset;\n') 
gnuplot:write('set terminal wxt 3;\n') 
gnuplot:write(string.format('set xrange [-1:2];\n')) 
gnuplot:write(string.format('set yrange [0:2];\n')) 
gnuplot:write(string.format('set size ratio %f;\n', rho_max/3.0)) 
gnuplot:write(string.format('set xtics %f;\n', 0.5)) 
gnuplot:write(string.format('set ytics %f;\n', 0.5)) 
gnuplot:write('set grid xtics ytics;\n') 
gnuplot:write(string.format('set arrow 1 nohead from 0,%f to 2,%f linetype 3;\n', chpc[1][2], chpc[1][2])) 
gnuplot:write(string.format('set label 1 "glue points " at 0,%f right;\n', chpc[1][2])) 
gnuplot:write('plot "-" using 1:2 notitle with lines, "-" using 1:2 notitle with lines;\n') 
for _, point in ipairs(chpc) do 
    gnuplot:write(string.format('%f %f\n', point[1], point[2])) 
end 
gnuplot:write('e\n') 
do 
    local points_count = 512 
    local dx = 2.0/points_count 
    local x = 0.0 
    for i = 1, points_count do 
     gnuplot:write(string.format('%f %f\n', x, solution:polynomial(x))) 
     x = x + dx 
    end 
    gnuplot:write('e\n') 
end 
gnuplot:flush(); 

os.execute('pause'); 
gnuplot:write('exit\n'); 
gnuplot:flush(); 
gnuplot:close() 

번째 단말은 라그랑주 다항식 포함 근사.

관련 문제