niedziela, 6 maja 2012

MathML

Uwaga - ten artykuł stanowić ma swego rodzaju "ściągawkę" - dlatego będzie co jakiś czas uzupełniany.

Prędzej czy później każdego spotka problem, w jaki sposób napisać wzór matematyczny w jakimś dokumencie (*). Nowoczesne pakiety biurowe (ja używam OpenOffice) mają edytory formuł. Ale do publikacji na stronach trzeba używać czegoś innego. Można wstawić obrazek stworzony różnymi technikami (np. jako screenshot z takiego edytora). Zauważyłem, że niektórzy tworzą takie obrazki LaTeXem. Może i jest to łatwe, ale jak dla mnie za dużo zabawy + wgrywania masy drobnych obrazków (nie mówiąc o tym, że zdążyłem już sporo zapomnieć). Ale na szczęście jest coś takiego jak MathML. Jest to - w dużym skrócie mówiąc - taki HTML do pisania formuł matematycznych.

(*) - No dobra, nie każdego .

MathML istnieje w dwóch odmianach - Presentation Markup i Content Markup. Obydwa są wymienne i można je nawet kombinować. Różnica jest taka, że przy pomocy Presentation Markup mamy większą kontrolę nad wyglądem formuły, a dzięki Content Markup mamy większą kontrolę nad "działaniem" formuły. Ja zamierzam korzystać z Presentation Markup i tę odmianę MathML chcę w dużym uproszczeniu tu opisać. Jeśli ktoś jest zainteresowany tematem bardziej, niech odwiedzi stronę W3C.org - MathML.

Spis treści

  1. Budowa
    1. Praktyczne uwagi
  2. Spis elementów
    1. Podstawowe elementy
    2. Elementy grupujące
    3. Elementy formatujące wygląd
    4. Tablice i macierze
  3. Symbole specjalne
    1. Dodatkowe znaki
    2. Litery greckie
    3. Znaki interpunkcyjne
    4. Symbole literowe
    5. Strzałki
    6. Operatory
  4. Fonty

Budowa

Aby wstawić kawałek kodu MathML w pliku html, musimy po prostu wstawić coś takiego:

<math xmlns="http://www.w3.org/1998/Math/MathML">
<mrow>...</mrow>
</math>

Znacznik <math> niejako odgranicza kod MathML od reszty dokumentu. Domyślnie <math> formatowany jest jako element inline, dlatego warto jeszcze wstawić (chyba że nam na tym nie zależy) display="block" i ew. style="text-align: left;".

Znacznik <mrow> jest podstawowym i najważniejszym elementem struktury formuły w MathML. Każda logiczna całość struktury formuły powinna być zawarta w swoich własnych <mrow>. Nawet takie trywialne części formuły jak a*b w formule 1+a*b+c:

<mn>1</mn>
<mo>+</mo>
<mrow>
  <mi>a</mi>
  <mo>*</mo>
  <mi>b</mi>
</mrow>
<mo>+</mo>
<mi>c</mi>

Ma to za zadanie zwiększenie kontroli nad formatowaniem formuły (chodzi głównie o łamanie linii - ale nie zauważyłem, żeby to dawało jakieś widoczne efekty). Osobiście nie zamierzam raczej tak się rozdrabniać - pewnie to błąd, ale ostatecznie Presentation Markup służy głównie do wyświetlania.

Inne miejsce, gdzie stosowanie <mrow> jest zalecane, to np. jako argumenty bardziej złożonych struktur, takich jak ułamki (<mfrac>) czy pierwiastki (<msqrt>). Jeśli jednak jeden z argumentów jest bardzo prosty (pojedynczy element), można ominąć <mrow>. Przykładowo 1/(a*b):

<mfrac>
  <mn>1</mn> <!-- powinno być zawarte w <mrow> ale nie musi być -->
  <mrow>
    <mi>a</mi>
    <mo>*</mo>
    <mi>b</mi>
  </mrow>
</mfrac>

Ogólnie - tak jak można z formuły zbudować drzewko operacji (kiedyś się tak w podstawówce w bodajże 1 klasie robiło, nie wiem jak jest teraz), tak samo można zbudować drzewko ze znaczników HTML, MathML czy ogólnie XML, i obydwa drzewka powinny do siebie pasować.

Praktyczne uwagi

  • Nawiasy. <mrow> powinien obejmować nawiasy.
    <mrow>
      <mo>(</mo>
        <mrow> <!-- opcjonalne mrow wewnątrz nawiasów -->
        ...
        </mrow>
      <mo>)</mo>
    </mrow>
    
  • Funkcje.
    <mi>funkcja</mi>
    <mo>&ApplyFunction;</mo>
    <mrow>
      <mo>(</mo>
      <mi>x</mi> <!-- przykładowa zawartość -->
      <mo>)</mo>
    </mrow>
    
  • Sumy, Iloczyny. Znaki sumy oraz iloczynu zapisujemy jako operatory.
    <munderover>
      <mo>&sum;</mo> <!-- ważne! sumę ∑ i iloczyn ∏ (&sum; oraz &prod;) 
                          zapisujemy jako operatory -->
      <mrow>
        <mi>i</mi>
        <mo>=</mo>
        <mn>1</mn>
      </mrow>
      <mi>n</mi>
    </munderover>
    <mrow> <!-- opcjonalny? mrow -->
    ...  <!-- zawartość sumy -->
    </mrow>
    
  • Całki. Znaki całki zapisujemy jako operatory. Znak dx jako dwa oddzielne identyfikatory d i x (ja piszę razem).
    <munderover> <!-- jeśli całka oznaczona -->
      <mo>&int;</mo> <!-- ważne! znak całki piszemy jako operator -->
      <mi>a</mi> <!-- albo mn - zależy od konkretnego przypadku -->
      <mi>b</mi>
    </munderover>
    <mrow>
      ... <!-- funkcja całkowana, opcjonalnie w mrow -->
    </mrow>
    <mi>d</mi> <!-- nie wiem, czemu tak -->
    <mi>x</mi> <!-- ja piszę dx w jednym mi -->
    
  • Granice. Symbol granicy (lim) piszemy jako identyfikator.
    <munder>
      <mi>lim</mi>
      <mrow>
        <mi>n</mi>
        <mo>&rarr;</mo> <!-- strzałkę piszemy jako operator -->
        <mo>&infin;</mo> <!-- nie wiem, czy nieskończoność piszemy jako operator, czy identyfikator -->
      </mrow>
    </munder>
    <mrow>
      ...  <!-- wyrażenie, opcjonalnie w mrow -->
    </mrow>
    
  • Separatory. Przecinki, średniki, apostrofy itp. piszemy jako operatory. Wielokropek jako identyfikator.
  • Pochodne funkcji. Pochodne jako apostrofy F', albo ∂F czy podobnie piszemy jako operatory. Podobnie gradienty (symbol nabla ∇). Różniczki w całkach najwyraźniej nie.
  • Wyznacznik macierzy. Jakiekolwiek nawiasy (w tym także pionowe kreski - również jako znak wartości bezwzględnej) piszemy jako operatory. Wyznacznik macierzy 'det' również piszemy jako operator.
  • Klamry grupujące. Klamry grupujące nad czy pod wyrażeniami piszemy jako operatory.
  • Stopień kąta °. Jako liczba. Nie wiem, czy razem z wartością liczbową kąta, czy osobno.

Spis Elementów

Pełny spis elementów oraz ich dokładny opis można znaleźć na stronie w3c.org.

Podstawowe elementy

Te elementy mogą zawierać tylko zawartość matematycznej formuły. Wszystkie pozostałe mogą zawierać tylko inne elementy MathML.

  • <mi> - identyfikator, nazwa zmiennej, funkcji itp.
  • <mn> - po prostu liczba (lub stała literowa?)
  • <mo> - operator (generalnie rzecz biorąc). Do operatorów zalicza się np. zastosowanie funkcji ⁡ ale o tym niżej.
  • <mtext> - zawiera "zwykły" tekst - np. jako opis lub komentarz do formuły. Można go użyć do wstawiania spacji pomiędzy elementami (&ThinSpace; , &ThickSpace; ).

Elementy grupujące

  • <mrow> - podstawowy element grupujący. Może być czasem pominięty.
  • <mfrac> - służy do tworzenia ułamków. Wymaga dwóch argumentów (licznik i mianownik).
  • <msqrt> - pierwiastek kwadratowy. Wymaga jednego argumentu (może zawierać dowolną ich ilość - traktowane są wtedy jakby były zawarte domyślnie w <mrow>).
  • <mroot> - dowolny pierwiastek. Wymaga dwóch argumentów (zawartość i stopień).
  • <mphantom> - daje niewidzialność i +5 do Cichego Chodu . Elementy w nim zawarte będą renderowane jako niewidzialne, ale będą zajmować tyle samo miejsca, co zwykle. Przydatne przy grupowaniu elementów. Przykład z w3c.org:
    <mfrac>
      <mrow>
        <mi> x </mi>
        <mo> + </mo>
        <mi> y </mi>
        <mo> + </mo>
        <mi> z </mi>
      </mrow>
      <mrow>
        <mi> x </mi>
        <mphantom>
          <mo form="infix"> + </mo>
          <mi> y </mi>
        </mphantom>
        <mo> + </mo>
        <mi> z </mi>
      </mrow>
      </mfrac>
    
    wyrenderuje: x + y + z x + y + z
  • <mfenced> - prosta i skrócona forma nawiasowania. Zamiast pisać:
    <mrow>
      <mo>(</mo>
      <mrow> <mi>x</mi> <mo>,</mo> <mi>y</mi> </mrow>
      <mo>)</mo>
    </mrow>
    
    można napisać:
    <mfenced> <mi>x</mi> <mi>y</mi> </mfenced> 
    
    Ogólna uwaga do nawiasowania: <mrow> powinien obejmować nawiasy. Myślę, że to co wewnątrz nawiasów można zawrzeć w <mrow> opcjonalnie.

Elementy formatujące wygląd

  • <msub> - indeks dolny. Wymaga 2 argumentów (podstawa, indeks).
  • <msup> - indeks górny (np. potęga). Wymaga 2 argumentów (podstawa, indeks).
  • <msubsup> - jednocześnie indeks dolny i górny. Wymaga 3 argumentów (podstawa, indeks dolny, indeks górny).
  • <munder> - do umieszczania elementów pod innymi elementami. Wymaga 2 argumentów (podstawa, podpis).
  • <mover> - podobnie, ale nad.
  • <munderover> - podobnie jak <msubsup>. Wymaga 3 argumentów (podstawa, podpis, nadpis).

Tablice i macierze

Tablice konstruuje się podobnie jak w HTML. Macierz to po prostu tablica zawarta w nawiasach ( <mo>(</mo> <mtable>...</mtable> <mo>)</mo> ). Z resztą za pomocą takiej tablicy można różne rzeczy skonstruować (np. takie dzielenie, jak "na papierze").

  • <mtable> - tablica. Zawiera wiersze tablicy.
  • <mtr> - wiersz tablicy. Zawiera komórki tablicy.
  • <mtd> - komórka w wierszu. Zawiera swoją zawartość (nie musi być w <mrow>). Podobnie jak w HTML można łączyć komórki poziomo lub pionowo (rowspan="m", colspan="n").

Symbole specjalne

Symbole specjalne to po prostu "literki" w unicode, które mają odpowiedni wygląd. W internecie można znaleźć pełno różnych tabel z kodami unicode.

Dodatkowe znaki

°&deg;&#xb0;Symbol stopnia kątowego
±&plusmn;&#xb1;plus-minus
×&times;&#xd7;Znak mnożenia - x
÷&divide;&#xf7;Znak dzielenia (minus z kropkami)

Litery greckie

Α&Alpha;&#x0391;
Β&Beta;&#x0392;
.........
α&alpha;&#x03B1;
β&beta;&#x03B2;
.........

Znaki interpunkcyjne

&thinsp;
&ThinSpace;
&#x2009;Wąska spacja
  &ThickSpace;-Szeroka spacja
&lsquo;&#x2018;Lewy, pojedynczy cudzysłów.
&rsquo;&#x2019;Prawy, pojedynczy cudzysłów.
&sbquo;&#x201a;Lewy, dolny, pojedynczy cudzysłów.
&ldquo;&#x201c;Lewy, podwójny cudzysłów.
&rdquo;&#x201d;Prawy, podwójny cudzysłów.
&bdquo;&#x201e;Lewy, dolny, podwójny cudzysłów.
&permil;&#x2030;Promile
&prime;&#x2032;Prim, minuty kątowe.
&Prime;&#x2033;Podwójny prim, sekundy kątowe.
&MediumSpace;&#x205f;Średnia spacja.
&af;
&ApplyFunction;
&#x2061;Operator zastosowania funkcji. Przykładowo sin(x) powinno się zapisać
<mi>sin</mi>
<mo>&ApplyFunction;</mo>
<mrow>
  <mo>(</mo><mi>x</mi><mo>)</mo>
</mrow>
Ważny niby dla formatowania (nie łamie linii), ale na siłę można se go darować (ja stosuję).
&it;
&InvisibleTimes;
&#x2062;Symbol niewidzialnego mnożenia (np. w wyrażeniu 4bc). Podobnie jak &ApplyFunction; ważny dla formatowania.
&ic;
&InvisibleComma;
&#x2063;Służy np. do rozdzielania indeksów (zamiast x1,2 można napisać x12 gdzie 1 i 2 oddzielone niewidzialnym przecinkiem - że niby nie 12 tylko 1 i 2).
-&#x2064;Niewidzialny plus, jak np. w ułamku 1⅔ (1+⅔).

Symbole literowe

-&#x2102;C z podwójnymi kreskami (zbiór liczb zespolonych).
-&#x2115;N z podwójnymi kreskami (zbiór liczb naturalnych).
-&#x211a;Q z podwójnymi kreskami (zbiór liczb wymiernych).
&real;&#x211c;Real
-&#x211d;R z podwójnymi kreskami (zbiór liczb rzeczywistych).
-&#x2124;Z z podwójnymi kreskami (zbiór liczb całkowitych).
&alefsym;&#x2135;Alef
&CapitalDifferentialD;&#x2145;D z podwójnymi kreskami.
&DifferentialD;&#x2146;d z podwójnymi kreskami.
&ExponentialE;&#x2147;e z podwójnymi kreskami.
&ImaginaryI;&#x2148;i z podwójnymi kreskami.
-&#x2149;j z podwójnymi kreskami.

Strzałki

&larr;&#x2190;
&uarr;&#x2191;
&rarr;&#x2192;
&darr;&#x2193;
&harr;&#x2194;
-&#x2195;
&lArr;&#x21d0;
&uArr;&#x21d1;
&rArr;&#x21d2;
&dArr;&#x21d3;
&hArr;&#x21d4;
-&#x21d5;

Operatory

&forall;&#x2200;Dla każdego.
&part;&#x2202;Różniczka.
&exist;&#x2203;Istnieje.
&empty;&#x2205;Zbiór pusty.
&nabla;&#x2207;Odwrócona delta.
&isin;&#x2208;Należy do zbioru.
&notin;&#x2209;Nie należy do zbioru.
&prod;&#x220f;Iloczyn.
&sum;&#x2211;Suma.
&minus;&#x2212;Minus, plus - zwykły plus, zwykły minus to myślnik.
&prop;
&vprop;
&#x221d;Symbol proporcjonalności.
&infin;&#x221e;Nieskończoność.
&and;&#x2227;Logiczne i.
&or;&#x2228;Logiczne lub.
&cap;&#x2229;Iloczyn zbiorów.
&cup;&#x222a;Suma zbiorów.
&int;&#x222b;Symbol całki.
&cong;&#x2245;Asymptotycznie równe.
&asymp;&#x2248;Przybliżone równa się.
&ne;&#x2260;Nie równe.
&equiv;&#x2261;Identyczne.
&le;&#x2264;Mniejsze równe.
&ge;&#x2265;Większe równe.
&sub;&#x2282;Podzbiór.
&sup;&#x2283;Nadzbiór.
&nsub;&#x2284;Nie podzbiór.
&sube;&#x2286;Podzbiór lub równy.
&supe;&#x2287;Nadzbiór lub równy.
&oplus;&#x2295;Plus w kółku.
&otimes;&#x2297;Razy w kółku.
&sdot;&#x22C5Operator mnożenia kropka.

Fonty

Tak jak w programowaniu, w matematyce również ważne są czytelne fonty. Niedopuszczalne jest przykładowo, żeby nie można było rozróżnić 1 i małe l, czy 0 i duże O. Ważne są też czytelne symbole.

Niestety nie udało mi się znaleźć fontu, który byłby idealny - te, które mają czytelne 1 i l, mają brzydkie niektóre symbole, a te które mają czytelne symbole, mają też trudno odróżnialne 1 i l. Ostatecznie zdecydowałem się na taki, który ma czytelne i rozróżnialne 1 i l.

Na stronie Mozilli można przeczytać, że dobrymi fontami dla zapisu matematycznego są STIX, Asana Math oraz MathJax. Niestety mają one podobnie wyglądające 1 i l. Tylko MathJax_Math jest pod tym względem w miarę porządny(*). Jest trochę podobny do Trebuchet MS, który wg. mnie również nadaje się do MathML (i ma tę zaletę, że powinien być domyślnie zainstalowany na każdym systemie - a przynajmniej tak słyszałem).

(*) - jest to moja własna opinia oparta na własnym doświadczeniu. Możliwe że się totalnie mylę (mogłem coś sknocić z fontami, albo źle odczytać znaki ).


Linki

5 komentarzy:

  1. Hejka, Piszę w komentarzu bo jakoś normalnie nie mogę się z Toba skontaktować. Nie znamy się ale chcialabym się zapytać czy umiałbys jeszcze zrobić taka stronę w httml z mathML?
    Pozdrawiam, A.

    OdpowiedzUsuń
    Odpowiedzi
    1. Myślę, że nie byłoby problemu, ale musiałbym sobie co nieco odświeżyć, bo już dawno tego nie robiłem.

      Z góry jednak uprzedzam, że nie mam zbytnio czasu zajmować się projektowaniem ani tworzeniem żadnych stron (jeśli o to ci chodzi) - co najwyżej mógłbym podpowiedzieć coś niecoś (ale niezbyt wiele - nigdy nie zajmowałem się tym profesjonalnie).

      Usuń
    2. No nic, ale dziekuje za odpowiedź. Wsumie to szukam osoby, która by mi właśnie taką stronę zaprojektowala. Dalej bede ciągnąć swoje poszukiwania.
      Pozdrawiam.

      Usuń
    3. Pozdrawiam i życzę powodzenia.

      Usuń
  2. Bardzo fajny artykuł. Jestem pod wrażeniem.

    OdpowiedzUsuń