Как да разширите фигура, създадена от много криви на Безие (JavaScript и canvas)

Създадох просто JavaScript приложение за чертане на квадратни криви на Безие. Всички криви на Безие са част от една форма (втората крива на Безие започва от точката, където завършва първата крива на Безие, третата крива започва от точката, където завършва втората крива на Безие,... и последната крива завършва там, където започва първата крива).

Броят на кривите на Безие във фигурите е 2 или повече (не е посочено точно колко).

След като създадох форма, имам масив от криви на Безие. Например нещо подобно:

array(3): {
   [0]:  object(8): {
      sx:  number: 130
      sy:  number: 175
      cp1x:  number: 119
      cp1y:  number: 151
      cp2x:  number: 175
      cp2y:  number: 120
      ex:  number: 212
      ey:  number: 181
   }
   [1]:  object(8): {
      sx:  number: 212
      sy:  number: 181
      cp1x:  number: 212
      cp1y:  number: 181
      cp2x:  number: 269
      cp2y:  number: 237
      ex:  number: 147
      ey:  number: 226
   }
   [2]:  object(8): {
      sx:  number: 130
      sy:  number: 175
      cp1x:  number: 130
      cp1y:  number: 175
      cp2x:  number: 147
      cp2y:  number: 226
      ex:  number: 147
      ey:  number: 226
   }
} 

Искам да създам същата форма, но разширена за X пиксела. Например, ако моята форма е създадена от 2 криви на Безие, които правят елипса с радиус R, искам да начертая по-голяма елипса със същата среда с радиус R + X. Прекарах 3 дни в опити да реша това, но наистина не знам как да го направим.

Благодаря много за съветите.


person 1daemon1    schedule 01.11.2013    source източник
comment
Ако се опитвате да мащабирате, мислили ли сте някога да мащабирате платното с метода на мащаба, вместо да се опитвате да манипулирате формите? developer.mozilla.org/en-US/docs/ Web/Guide/HTML/Canvas_tutorial/   -  person Rick Suggs    schedule 01.11.2013
comment
Благодаря за съвета, но за съжаление мащабирането/увеличаването не решава проблема ми, защото трябва да имам отделни координати с нова форма (искам да ги запазя в DB).   -  person 1daemon1    schedule 01.11.2013
comment
Но можете да мащабирате всички координати с (R+X)/R. (Някои незначителни забележки: 2 контролни точки означават, че имате кубични криви на Безие, можете само да приближите елипса, но не и да направите такава, а елипсата няма радиус.)   -  person Teepeemm    schedule 01.11.2013
comment
Защо просто не запазите мащаба в базата данни и когато отворите извличането на формата, нарисувайте оригинала, но започнете с платно, мащабирано по същия начин като запазената форма? Това е много по-лесно и по-просто от изчисляването на нови точки от желан радиус.   -  person Rick Suggs    schedule 01.11.2013
comment
Трябва да изпратя разширена форма в DB с помощта на REST API, нямам избор. Благодаря много за предложенията. Реших да променя логиката на приложението си и сега нямам нужда от разширена крива.   -  person 1daemon1    schedule 04.11.2013


Отговори (3)


Проклетите криви на Безие…Обичам ги и ги мразя!!

Неуспех №1

Една крива на Безие не може да бъде разширена с помощта на друга крива на Безие:

Уикипедия: Кривата с фиксирано отместване спрямо дадена крива на Безие, често наричана крива на отместване (лежаща „успоредна“ на оригиналната крива, като отместването между релсите в железопътна линия), не може да бъде точно оформена от крива на Безие.

Грешка №2

Ако знаете, че кривите ви образуват затворена правилна форма (има център—центроид), можете да използвате context.translate. Проблемът е, че вашият примерен набор от Безие няма центроид. Всъщност не много комплекти Безие имат центроид.

Трябва да работи...но математиката създава главоболия

  1. Изчислете много X/Y по пътя, които образуват безиерите.
  2. При всеки X/Y изчислете ъгъла на допирателната към кривата.
  3. Изчислете перпендикулярния ъгъл на този допирателен ъгъл.
  4. Придвижете се навън по тази перпендикулярна линия с дължината, която искате да разширите безиерата.
  5. Запазете X/Y в тази разгъната точка.
  6. Свържете всички разширени точки с помощта на context.lineTo.

Просто сте разширили затворен набор от криви на Безие!

Имам някаква математика за това, но ще отнеме време, за да го събера в завършено решение. Ако опиташ, ще ти помогна, ако имаш проблеми...

person markE    schedule 01.11.2013

Не можете да компенсирате крива с друга крива, но можете да компенсирате крива с поликрива и аз обяснявам как обикновено се прави това на http://pomax.github.io/bezierinfo/#offsetting -- кодът се обработва, но е доста лесен за пренасяне към (неоптимизиран ) JavaScript. По-важната част е, че ако искате да направите това по "правилния" начин, трябва да направите малко програмиране (и разбиране). Ако просто искате нещо, което изглежда добре, просто преминете през кривата на X стъпки (да речем for(var i=0; i<1; i+=0.01) {...}), намерете нормалата във всяка точка, изместете нормалата с толкова пиксели, от които се нуждаете, и свържете всички тези точки. Линейните приближения са доста прилични, стига кривите да не са дълги хиляди пиксели.

person Mike 'Pomax' Kamermans    schedule 02.11.2013

Отговорих на подобен въпрос тук Как да генерирам дебела крива на Безие?

Има публикация в блог, обясняваща как да начертаете офсетна крива http://brunoimbrizi.com/unbox/2015/03/offset-curve/

И интерактивен пример, написан на javascript: http://codepen.io/brunoimbrizi/pen/VYEWgY

// code is too big to post here, please see the source on codepen
person imbrizi    schedule 13.03.2015