LINUX.ORG.RU

Как нарисовать кривую Безье в свободном ПО под Linux.

 


0

2

Возникла необходимость нарисовать квадратичную кривую безье. Ткнулся в Inkscape - не умеет, gimp - не умеет, kig - не умеет, LibreOffice - не умеет. Конечно, у них у всех есть свои инструменты для рисования кривых линий, но мне нужна именно стандартная кривая Безье 2-го порядка.

★★★★★

Последнее исправление: next_time (всего исправлений: 1)

Ответ на: комментарий от Sem_SemiuS

интересует исключительно свободное ПО, даже бесплатная проприетарщина не нужна

next_time ★★★★★
() автор топика
Ответ на: комментарий от unfo

Специально написал именно нарисовать, а не построить: желательно именно в графическом редакторе, чтобы можно было любую из 3-х точек видеть перед глазами изменения. Но всё равно спасибо: в самом, ну уж совсем крайнем случае сгодится.

next_time ★★★★★
() автор топика
Ответ на: комментарий от router

Это - кубические, мне нужны квадратичные.

next_time ★★★★★
() автор топика
Ответ на: комментарий от unfo

Эээ, во-первых оно, походу, вообще не работает: требует выбрать «2 selected path», когда выбираешь, второй path удаляется, да и всё. Во-вторых, оно предназначено, видимо, для построения кривой безье, а мне надо для рисования. Т.е. оно, опять же, (видимо) не позволит двигать точки, на основе которых строится кривая с отображением изменений в реальном времени.

next_time ★★★★★
() автор топика
Ответ на: комментарий от RedEyedMan3

Здесь важно упомянуть следующее: тот же Libre Office поддерживает гораздо более крутые фишки для рисования кривых — например возможность прозрачных аффинных трансвормаций нарисованных от руки(!) кривых просто волшебна. Это, как если бы в каком-то безумном параллельном мире США запустили бы в космос вояджер и на Луну космонавтов, но при этом не смогли бы освоить производство нормальных автомобилей. Wait, oh shit...

next_time ★★★★★
() автор топика

Раз уж ни о каких дополнительных ограничениях не сказано, то FontForge.

Поддерживает и квадратичные и кубические кривые Безье.

frob ★★★★★
()
Ответ на: комментарий от next_time

Для inkscape есть соответствующая бага.
А так, на pygtk/cairo наваять «приложение» с единственной функцией — рисование кривой Безье второго порядка, выглядит задачей на полчаса.

frob ★★★★★
()

Может быть в geogebra получится.

kinik ★★☆
()
Ответ на: комментарий от next_time

По-моему, ответ на этот вопрос должен лежать где-то очень близко к ответу на вопрос «а зачем тебе рисовать квадратичную кривую Безье?»

frob ★★★★★
()
Ответ на: комментарий от next_time

С телефона пишу, отсего и бред выходит.

Opengl, квадрат с спецшейдером. Возможно в несколько итераций чтоб лишний раз не дергать шейдер.

Остается разве что написать opencl-рендерер. Самого бесят эти кривые.

ckotinko ☆☆☆
()
Ответ на: комментарий от frob
#!/usr/bin/env python
# Copyright (C) 2007-2013,	frob@gnome.org

import gtk, cairo

class Point():
	def __init__(self,x=None,y=None):
		self.x = x
		self.y = y

	def draw(self,ctx):
		ctx.rectangle(self.x-2.5,self.y-2.5,5,5)
		ctx.stroke()

class MainWindow (gtk.Window):
	def __init__(self):
		gtk.Window.__init__(self)
		self.connect('destroy', lambda *w: gtk.main_quit())
		self.da = gtk.DrawingArea()
		
		self.p0 = Point(100,200)
		self.p1 = Point(200,50)
		self.p2 = Point(300,200)
		
		self.curpnt = None
		self.drag = False
		
		self.size = 400
		self.set_size_request(self.size,self.size)
		self.set_title("B Curve")
		self.add(self.da)
		self.da.set_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.POINTER_MOTION_HINT_MASK)
		self.da.connect("expose_event", self.expose)
		self.da.connect("motion_notify_event",self.on_motion_notify)
		self.da.connect("button_press_event",self.on_btn_press)
		self.da.connect("button_release_event",self.on_btn_release)
		self.connect("key-press-event", self.on_key_press)
		self.show_all()


	def expose(self,da,ev,surface=None):
		x,y,width,height = da.allocation
		if surface is None:
			ctx = da.window.cairo_create()
		else:
			cs = cairo.ImageSurface (cairo.FORMAT_ARGB32, self.size, self.size)
			ctx = cairo.Context (cs)
		
		if ev and ev.area:
			ctx.rectangle(ev.area[0],ev.area[1],ev.area[2],ev.area[3])
			ctx.clip()
		ctx.set_source_rgb(1,1,1)
		ctx.rectangle(x,y,width,height)
		ctx.fill()
		ctx.set_line_width(1)
		ctx.set_source_rgba(.5,.5,.5,1)
		ctx.move_to(self.p0.x+.5,self.p0.y+.5)
		ctx.line_to(self.p1.x+.5,self.p1.y+.5)
		ctx.line_to(self.p2.x+.5,self.p2.y+.5)
		ctx.stroke()
		ctx.set_source_rgba(0,0,0,1)
		self.p0.draw(ctx)
		self.p1.draw(ctx)
		self.p2.draw(ctx)
		
		c1x = self.p0.x+2*(self.p1.x-self.p0.x)/3.
		c2x = self.p2.x+2*(self.p1.x-self.p2.x)/3.
		c1y = self.p0.y+2*(self.p1.y-self.p0.y)/3.
		c2y = self.p2.y+2*(self.p1.y-self.p2.y)/3.
		ctx.set_source_rgba(.8,0,0,1)
		ctx.move_to(self.p0.x+.5,self.p0.y+.5)
		ctx.curve_to(c1x,c1y,c2x,c2y,self.p2.x,self.p2.y)
		ctx.stroke()
		if surface:
			return cs

	def on_motion_notify(self,da,ev):
		if ev.is_hint:
			ex, ey, state = ev.window.get_pointer()
		else:
			ex = ev.x
			ey = ev.y
			state = ev.state
		if not self.drag:
			if abs(ev.x-self.p0.x) < 2.5 and abs(ev.y-self.p0.y) < 2.5:
				self.curpnt = self.p0
			elif abs(ev.x-self.p1.x) < 2.5 and abs(ev.y-self.p1.y) < 2.5:
				self.curpnt = self.p1
			elif abs(ev.x-self.p2.x) < 2.5 and abs(ev.y-self.p2.y) < 2.5:
				self.curpnt = self.p2
			else:
				self.curpnt = None
		else:
			self.curpnt.x = ev.x
			self.curpnt.y = ev.y
			self.expose(da,None)


	def on_btn_press(self,btn,ev):
		if self.curpnt:
			self.drag = True
		else:
			self.drag = False


	def on_btn_release(self,btn,ev):
		self.drag = False


	def on_key_press(self,w,event):
		if event.keyval in (67,99) and event.state&gtk.gdk.CONTROL_MASK: #^C
			self.copy_to_clp()


	def copy_to_clp(self):
		size = int(self.size)
		pixmap = gtk.gdk.Pixmap (None, size, size, 24)
		cr = pixmap.cairo_create ()
		cr.save()
		cr.set_source_rgb(1,1,1)
		cr.rectangle(0,0,size,size)
		cr.fill()
		cs = self.expose(self.da,None,1)
		cr.set_source_surface (cs, 0, 0)
		cr.paint ()
		cr.restore()
		pixbuf = gtk.gdk.Pixbuf (gtk.gdk.COLORSPACE_RGB, True, 8, size, size)
		pixbuf = pixbuf.get_from_drawable (pixmap, gtk.gdk.colormap_get_system(), 0, 0, 0, 0, size, size)
		clp = gtk.Clipboard()
		clp.set_image(pixbuf)

def main ():
	MainWindow ()
	gtk.main ()

if __name__ == '__main__':
	main ()

Точки перетаскиваются. По Ctrl-C копирует картинку в клипборд.

frob ★★★★★
()
Ответ на: комментарий от anonymous

это опять же построение, а не рисование

next_time ★★★★★
() автор топика
Ответ на: комментарий от frob

я к тому, что время можно провести с большей пользой, чем рисовать очередной, 9000-й калькулятор, но за код спасибо

next_time ★★★★★
() автор топика
Ответ на: комментарий от petrosha

Потому что есть «домашние заготовки», т.ч. можно выкинуть лишнее, добавить нужное и не париться с вспоминанием того, как получить копию изображения из DrawingArea в буфере обмена =)

frob ★★★★★
()
Ответ на: комментарий от cdshines

Построить или даже организовать хеллоуворлд по рисованию кривых безье я и сам могу на любом языке программирования, вопрос был именно о готовом нехеллоуворлдном ПО.

Это не то, но я бы в любом случае взял гнуплот и всякие scipy/numpy и там бы уже делал.

насколько я понимаю, это опять построение, а не рисование

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

Да на здоровье.

Это «внеочередной» калькулятор, поскольку как ты сам мог убедиться, квадратичные кривые поддерживаются только там, где они действительно нужны (например, FontForge, «потому что TrueType»).
Сферическому коню в вакууме наличие их поддержки в Inkscape, GIMP или LO нигде не трёт.

Зачем квадратичные кривые конкретно тебе?

frob ★★★★★
()

А на кубических безье мышкой поставить концы направляющих в одну точку не судьба?

Vit ★★★★★
()
Ответ на: комментарий от frob

Зачем квадратичные кривые конкретно тебе?

Понадобилось для демонстрации кривых Безье 2-го порядка + заодно, демонстрации Свободного ПО. Ну и чисто для себя — на мой взгляд кривые Безье 2-го порядка воспринимаются проще, чем 1-го.

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

От опорных точек в любое место рисуете треугольник, затем направляющие кубической безье ставите вдоль его сторон на 2/3 их длины. Будет квадратичная.

http://www.caffeineowl.com/graphics/2d/vectorial/bezierintro.html

Я по этой статье писал апроксимацию кубических безье квадратичными сплайнами, для ttf фонтов.

Vit ★★★★★
()
Ответ на: комментарий от next_time

Понадобилось для демонстрации кривых Безье 2-го порядка + заодно, демонстрации Свободного ПО.

Ага ну т.е. самому делать лень а тут как раз такой повод потыкать пальцами в кучу свободного ПО в котором „ниосилили“. Ну ок. fxd.

init_6 ★★★★★
()
Ответ на: комментарий от Vit

От опорных точек в любое место рисуете треугольник, затем направляющие кубической безье ставите вдоль его сторон на 2/3 их длины. Будет квадратичная.

всё так, но ведь это - костыли, к тому же, годный софт уже подсказали: Как нарисовать кривую Безье в свободном ПО под Linux. (комментарий)

next_time ★★★★★
() автор топика
Ответ на: комментарий от init_6

всё осилили, FontForge уже подсказали, тема уже полдня как помечена решённой

Ага ну т.е. самому делать лень

Читать уже научитесь, если не тред, то хотя бы сообщение, на которое отвечаете: «демонстрации Свободного ПО». Откуда следует, что вариант «накатал наколенке за полчаса» не годится.

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

Читать уже научитесь, если не тред, то хотя бы сообщение, на которое отвечаете: «демонстрации Свободного ПО». Откуда следует, что вариант «накатал наколенке за полчаса» не годится.

В данном случае как раз вариант „накатал наколенке за полчаса“ решает поскольку области где оно реально надо конечно же есть… но вот распространены они не так широко.

А я бы сразу выбрал бы свободно открытый python в котором бы считал и gnuplot в котором бы спокойно нарисовал затем все что нужно.

init_6 ★★★★★
()
Ответ на: комментарий от waker

оно не для рисования кривых, а для построения — это разные вещи

next_time ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.