Редактор формул на Vb

Для неординарных вопросов. Если вы опытный программист, попавший в трудную ситуацию, — вам сюда.

Модератор: gaidar

Правила форума
Этот раздел не предназначен для того, чтобы вы адресовали свою проблему профессионалам.
Этот раздел предназначен для профессионалов, которые столкнулись с проблемой и не могут решить ее самостоятельно.
Если вы считаете себя профессионалом, а свою проблему сложной — вам сюда.
Если модератор посчитает, что вы ошиблись, то на первый раз он перенесет ваше сообщение в основной раздел без последствий для автора. Во второй раз тема будет закрыта, а автору будет выписано нарушение. В третий раз автор будет забанен.
next
Обычный пользователь
Обычный пользователь
 
Сообщения: 59
Зарегистрирован: 26.03.2002 (Вт) 23:01

Редактор формул на Vb

Сообщение next » 30.10.2007 (Вт) 16:32

Я конечно же не профессионал в Vb, но вопрос мне кажется сложным.
Итак понадобилось мне написать редактор формул, наподобие MathType, но с той лишь разницей, что формулы он должен был строить по некоторому коду, к примеру:

Код: Выделить всё
b-\drb{b}{x}


Т.е от b отнять дробь
Код: Выделить всё
b/x


сразу же оговорюсь, что верстальщики формул наподобие Latex мне не подходят (во первых это слишком мощно для моей маленькой программы, во вторых время компиляции латех документа очень долго, в третьих формула должна быть легко компилируема в рисунок jpg)

Результатом моего желания явилась эта программа (написана целиком на Vb6, проект прилагаю).

По сути это написанный мной некогда редактор карт для простых игрушек с использованием StretchBlt, но переделанный под отбражение формул.

Не буду описывать весь код, суть в том, что элементы формул, такие как x,y,z,+ запихнуты в коллекцию текстур брашей, браши добавляются в определенное место на форме (документе).

Суть программы в том, чтобы найти позицию для каждого браша (поставить знак в нужное место на форме).

За это отвечает в программе следующая функция:

Код: Выделить всё
Private Function CalcFormula(fstring As String, nx As Single, ny As Single, sizeum As Variant, ex As Boolean) As PicTexSize
Dim i As Integer
Dim res As Boolean
Dim sm As String
Dim fsize As PicTexSize
Dim perpr As String
Dim vtpr As String
Dim xs1 As Integer
Dim xs2 As Integer
i = 0
dist = 3
allsizeH = 0
begx = nx
If fstring = "" Then CalcFormula.height = 0: CalcFormula.width = 0: Exit Function
Do

i = i + 1
sm = Mid(fstring, i, 1)
'Добавление односимовольного браша-формулы
If SetTexFor(sm) Then
plussizeH = GetPixSize(nowPix).height
If allsizeH = 0 Then allsizeH = plussizeH
If ex = True Then addBrush nx, ny - GetPixSize(nowPix).height / 2, sizeum, sizeum
nx = nx + GetPixSize(nowPix).width + dist * sizeum * sizeum
End If
'Добавление многосимвольного браша формулы
If sm = "\" Then
xs = InStr(i, fstring, " ")
  If xs <> 0 Then
    sm = Mid(fstring, i + 1, xs - i - 1)
      i = xs
      If SetTexFor(sm) Then
        plussizeH = GetPixSize(nowPix).height
        If allsizeH = 0 Then allsizeH = plussizeH
If ex = True Then addBrush nx, ny - GetPixSize(nowPix).height / 2, sizeum, sizeum
      nx = nx + GetPixSize(nowPix).width * sizeum + dist * sizeum
      End If
  End If
End If
'Добавление сложного браша формулы
If sm = "\" Then
    xs1 = 0
    xk1 = 0
    xs2 = 0
    xk2 = 0
xs1 = InStr(i, fstring, "{")
If xs1 <> 0 Then sm = Mid(fstring, i + 1, xs1 - i - 1) Else sm = ""
If xs1 = 0 Then
  xk1 = 0
  xs2 = 0
  perpr = ""
Else
  xk1 = GetLastStr(xs1, fstring, "}", "{")
  If xk1 = 0 Then perpr = "" Else perpr = Mid(fstring, xs1 + 1, xk1 - xs1 - 1): i = xk1
End If
If xk1 <> 0 Then xs2 = InStr(xk1, fstring, "{")
If xs2 = 0 Then
  vtpr = ""
  xk2 = 0
Else
  xk2 = GetLastStr(xs2, fstring, "}", "{")
  If xk2 = 0 Then vtpr = "" Else vtpr = Mid(fstring, xs2 + 1, xk2 - xs2 - 1): i = xk2
End If
 
  If (perpr <> "" And sm <> "") Then
    fsize = AddSlFunc(sm, perpr, vtpr, nx, ny, sizeum, ex)
    nx = nx + fsize.width + dist * sizeum
    plussizeH = fsize.height
  End If

End If





If plussizeH > allsizeH Then allsizeH = plussizeH
If i = Len(fstring) Then CalcFormula.height = allsizeH: CalcFormula.width = nx - begx: nx = begx: Exit Function
Loop

End Function


Может быть все довольно сложновато, но на первый взгляд:
взглянем внимательней:
nx - начало текущего фрагмента формулы по оси x
ny - средняя линия (т.е. горизонтальная линия проходящая через середину текущего фрагмента формулы)
fstring - код формулы
sizeum - коофициент уменьшения размера фрагмента формулы, 1 без уменьшения
ex - указатель отображать ли элементы формулы или лишь расчитывать размер фрагмента.

Итак данная функция расчитывает размер фрагмента формулы и отображает элементы (браши) на средней линии (или не отображает).

Для того, чтобы отображать сложные элементы (такие как дробь или степень) существует отдельная функция:

Код: Выделить всё
Private Function AddSlFunc(tfor As String, par1 As String, par2 As String, nx As Single, ny As Single, sizeum As Variant, ex As Boolean) As PicTexSize
Dim fsize As PicTexSize
Dim f2size As PicTexSize
Dim tpar1 As String
Dim tpar2 As String
'Добавление сложных брашей
Select Case tfor
Case "drb"
'Добавление дроби
tpar1 = par1
tpar2 = par2
'Предрасчет размеров числителей и знаменателей
fsize = CalcFormula(tpar1, nx, ny, sizeum, False)
f2size = CalcFormula(tpar2, nx, ny, sizeum, False)
'Добавление числителя и знаменателя.
fsize = CalcFormula(tpar1, nx, ny - (fsize.height) / 2 - 3, sizeum, ex)
f2size = CalcFormula(tpar2, nx, ny + (f2size.height) / 2 + 3, sizeum, ex)
SetTexFor ("-")
If f2size.width >= fsize.width Then AddSlFunc.width = f2size.width Else AddSlFunc.width = fsize.width
addBrush nx, ny, (AddSlFunc.width / GetPixSize(nowPix).width), 1
AddSlFunc.height = fsize.height + f2size.height + 4
AddSlFunc.width = AddSlFunc.width
Case "dg"
'Добавление степени'
fsize = CalcFormula(par1, nx, ny, sizeum, False)
fsize = CalcFormula(par1, nx, ny, sizeum, ex)
f2size = CalcFormula(par2, nx, ny, sizeum * 0.8, False)
f2size = CalcFormula(par2, nx + fsize.width, ny - fsize.height / 2, sizeum * 0.8, ex)
AddSlFunc.width = (fsize.width + f2size.width)
AddSlFunc.height = fsize.height + f2size.height
End Select

End Function


Обе данные функции возвращают размеры формул в типе Pictexsize.
Последняя функция имеет параметрами:

tfor - название слож функции (если дробь то drb)
par1, par2 - в дроби числитель и знаменатель (фрагменты формулы)
ну и те же параметры, что в первой функции.
Суть работы второй функции в следующем - расчитать размер числителя и знаменателя рекурсивно запустив опять CalcFormula, но уже для фрагментов числителя и знаменателя. Получив размеры фрагментов формул числителя и знаменателя запускаем CalcFormula для обоих и рендерим числитель над средней линией а знаменатель под средней линией и на средней линии ренедерим прямую. Получаем красивую такую дробь. Попытался объяснить как мог.

Итак внимание, вопрос: все прекрасно работает, НО введите формулу:
\drb{x\drb{x}{b}}{b}. Во второй дроби (внутренней) b залез под черту первой. Почему? Сижу над этим вопросом уже неделю.

Все функции описанные выше, а также ряд вспомогательных находятся в модуле формы: frmOptions
[/code]
Вложения
fomul.rar
(78 Кб) Скачиваний: 296

Hk
Начинающий
Начинающий
 
Сообщения: 6
Зарегистрирован: 14.12.2007 (Пт) 13:50

Сообщение Hk » 14.12.2007 (Пт) 18:11

Текстуры скинь:

Run-time error '76':
Path not found: 'd:\test_laboratory\Образцы\Не законченные\mathob\mathsim\img2.gif'
Path not found: 'd:\test_laboratory\Образцы\Не законченные\mathob\mathsim\min.gif'
Path not found: 'd:\test_laboratory\Образцы\Не законченные\mathob\mathsim\x.gif'


Вернуться в Раздел для Профессионалов

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 10

    TopList