poniedziałek, 30 marca 2009

Zapraszam na AUTOMATICON 2009

Już niedługo 01 kwietnia 2009 (w Prima aprilis ;) ) kolejne, XV Międzynarodowe Targi Automatyki i Pomiarów AUTOMATICON®09. Chciałbym wszystkich moich czytelników zaprosić na prezentację (którą współtworzyłem), która będzie miała miejsce w godz. 11.00 - 11.45, sala B-1.

Prezentacja poświęcona jest rodzinie oprogramowania CommServer, która pozwala na realizację komunikacji między różnorodnymi systemami przy kosztach nieporównywalnie niższych od potencjalnych zysków. Minimalizacja kosztów jest wynikiem zastosowania międzynarodowych standardów komunikacyjnych i rozwiązań niewymagających programowania. Oprogramowanie posiada certyfikaty zgodności dla standardu OPC i było testowane pod nadzorem organizacji OPC Foundation z kilkudziesięcioma produktami najbardziej liczących się w branży producentów. Pozwala na realizację integracji we własnym zakresie i - w efekcie - na zbudowanie systemu otwartego. Jako przykład użycia pokazano zastosowanie integracji systemów telemetrii do prezentacji aktualnej produkcji w systemie GIS i ERP. Innym przykładem jest zastosowanie oprogramowania do integracji systemów automatyki w celu uzyskania dodatkowych korzyści w produkcji z efektu synergii w ciepłownictwie, gdzie grupa elektrociepłowni uzyskuje dodatkowe korzyści w procesie produkcji energii elektrycznej dzięki zsynchronizowanemu prowadzeniu procesu dystrybucji ciepła.

Praktyka pokazuje, że dzięki integracji systemów zarządzania przedsiębiorstwem (MES, SAP, ERP, GIS, itd.) z systemami sterowania i monitorowania produkcji (PLC, SCADA, HMI) można uzyskać dodatkowe zyski dzięki optymalizacji i uzyskanemu efektowi synergii. Warunkiem integracji jest umożliwienie wprowadzenia danych czasu rzeczywistego do systemów zarządzania i na odwrót.

1 kwietnia 2009, godz. 11.00 - 11.45, sala B-1, Warszawskie Centrum EXPO XXI

Szczegóły dotyczące targów http://www.automaticon.pl/

Lokalizacja http://www.automaticon.pl/lokalizacja.php

Zaproszenie

Napisy przestrzenne (WPF 3D), a ich wektory położenia (przykłady w języku C#)

Chciałbym zwrócić uwagę na jeszcze jedną sprawę. Istotne są też wektory które wyznaczają płaszczyznę na której umieszczany jest napis (wektory vectorUp i vectorOver w przedstawionym wcześniej przykładzie).Jeżeli napis umieszczany jest na pewnym obiekcie należącym do sceny, wtedy wyznaczenie odpowiednich wektorów jest proste (ew. może się okazać konieczność ich normalizacji). Trudniejsze jest natomiast dobranie odpowiednich wektorów, gdy napisy mają służyć do opisu sceny i mają się pojawiać na powierzchni wyznaczanej przez płaszczyznę która jest prostopadła do kierunku patrzenia. W tym przypadku należy wybrać takie wektory, które będą wzajemnie do siebie prostopadłe oraz prostopadłe do kierunku patrzenia. Do wyznaczenia takich wektorów należy użyć własności iloczynu skalarnego, którego wartość wynosi 0 jeżeli wektory są prostopadłe.

Funkcja wyznaczająca takie wektory może mieć postać:

void UpdateViewToLookDirection(Vector3D LookDirection)

{

Vector3D look = LookDirection;

look.Normalize();

TextVectorOver = new Vector3D(-look.Y, look.X, 0);

TextVectorUp = new Vector3D(-look.Z * look.X, -look.Z * look.Y, look.Y * look.Y + look.X * look.X);

TextVectorOver.Normalize();

TextVectorUp.Normalize();

}

(przedstawione tutaj powyżej rozwiązanie nie jest może optymalne, ale na pewno poprawia czytelność napisów, nie będąc również skomplikowane w implementacji - jeśli ktoś ma lepszy pomysł chętnie poznam)

Funkcję tą należy wywołać każdorazowo przy zmianie kierunku patrzenia. Kierunek patrzenia można odczytać z używanego Viewport'u 3D:

PerspectiveCamera camera = (PerspectiveCamera)mainViewport.Camera;

Vector3D newlookdirection = Panel3DMath.Transform3DVector(camera.Transform,camera.LookDirection);

W przykładowym kodzie wyżej pokazany jest jeszcze sposób transformowania wektora patrzenia, w oparciu o transformatę wykorzystaną aktualnie do obracania kamery. Funkcja Transform3DVector powinna mieć natomiast postać:

public static Vector3D Transform3DVector(Transform3D transform, Vector3D vector)

{

Point3D input = new Point3D(vector.X, vector.Y, vector.Z);

Point3D output;

if (transform.TryTransform(input, out output))

{

return new Vector3D(output.X, output.Y, output.Z);

}

return vector;

}

(To tylko jedna z części artykułu, przeczytaj pozostałe: 1, 2, 3, 4, 5, 6, 7)

piątek, 27 marca 2009

Napisy przestrzenne (WPF 3D) (przykłady w języku C#)

Aby zobaczyć jak tworzyć etykiety 3D, zobaczymy jak działa funkcja, która to realizuje: CreateTextLabel3D. Ta funkcja jest odpowiedzialna za wytworzenie obiektu typu ModelVisual3D , zawierającego etykiety 3D. Funkcja ta będzie miała następującą deklarację:

public static ModelVisual3D CreateTextLabel3D( string text, Brush textColor, bool isDoubleSided, double height, Point3D basePoint, bool isBasePointCenterPoint, Vector3D vectorOver, Vector3D vectorUp);

Parametry wywołania:

  • text - tekst który chcemy narysować
  • textColor - kolor tekstu
  • isDoubleSided - czy ma być widoczny z dwóch stron?
  • height - wysokość znaków
  • basePoint - punkt bazowy etykiety
  • isBasePointCenterPoint - jeśli ustawione na true punkt bazowy jest punktem centralnym etykiety
  • vectorOver - wektor poziomy napisu
  • vectorUp - wektor pionowy napisu

Funkcja zwraca: element dodawany do Viewport3D
Uwaga: Dwa wektory: vectorOver i vectorUp tworzą powierzchnię, na której rysowany jest tekst. obydwa wektory używane są do wyliczeń wielkości etykiety więc najlepiej, by każda ich współrzędna była 0 lub 1. np. [1,1,0] lub [1,0,1], etc...

Jak ona działa?

  1. W pierwszym kroku tworzymy TextBlock , który zawiera naszą etykietę.

    TextBlock textblock = new TextBlock(new Run(text));

    textblock.Foreground = textColor; // ustawianie koloru

    textblock.FontFamily = new FontFamily("Arial"); // ustawianie czcionki

  2. W drugim kroku, tworzymy pędzel i materiał TextBlock , który zawiera stworzony w poprzednim kroku.

    DiffuseMaterial mataterialWithLabel = new DiffuseMaterial();

    // Allows the application of a 2-D brush,

    // like a SolidColorBrush or TileBrush, to a diffusely-lit 3-D model.

    // we are creating the brush from the TextBlock

    mataterialWithLabel.Brush = new VisualBrush(textblock);

  3. Teraz czas jest na przygotowanie objektu 3D, który zostanie pokryty tekstem

    //calculation of text width (assumming that characters are square):

    double width = text.Length * height;

    // we need to find the four corners

    // p0: the lower left corner; p1: the upper left

    // p2: the lower right; p3: the upper right

    Point3D p0 = basePoint;

    // when the base point is the center point we have to set it up in different way

    if(isBasePointCenterPoint)

    p0 = basePoint - width / 2 * vectorOver - height / 2 * vectorUp;

    Point3D p1 = p0 + vectorUp * 1 * height;

    Point3D p2 = p0 + vectorOver * width;

    Point3D p3 = p0 + vectorUp * 1 * height + vectorOver * width;

    // we are going to create object in 3D now:

    // this object will be painted using the (text) brush created before

    // the object is rectangle made of two triangles (on each side).

    MeshGeometry3D my3D_Restangle = new MeshGeometry3D();

    my3D_Restangle.Positions = new Point3DCollection();

    my3D_Restangle.Positions.Add(p0); // 0

    my3D_Restangle.Positions.Add(p1); // 1

    my3D_Restangle.Positions.Add(p2); // 2

    my3D_Restangle.Positions.Add(p3); // 3

    // when we want to see the text on both sides:

    if (isDoubleSided)

    {

    my3D_Restangle.Positions.Add(p0); // 4

    my3D_Restangle.Positions.Add(p1); // 5

    my3D_Restangle.Positions.Add(p2); // 6

    my3D_Restangle.Positions.Add(p3); // 7

    }

    my3D_Restangle.TriangleIndices.Add(0);

    my3D_Restangle.TriangleIndices.Add(3);

    my3D_Restangle.TriangleIndices.Add(1);

    my3D_Restangle.TriangleIndices.Add(0);

    my3D_Restangle.TriangleIndices.Add(2);

    my3D_Restangle.TriangleIndices.Add(3);

    // when we want to see the text on both sides:

    if (isDoubleSided)

    {

    my3D_Restangle.TriangleIndices.Add(4);

    my3D_Restangle.TriangleIndices.Add(5);

    my3D_Restangle.TriangleIndices.Add(7);

    my3D_Restangle.TriangleIndices.Add(4);

    my3D_Restangle.TriangleIndices.Add(7);

    my3D_Restangle.TriangleIndices.Add(6);

    }

  4. W kolejnym kroku pokrywamy stworzony przed chwilą obiekt 3D używając materiału stworzonego na początku. // texture coordinates must be set to // stretch the TextBox brush to cover // the full side of the 3D label. my3D_Restangle.TextureCoordinates.Add(new Point(0, 1)); my3D_Restangle.TextureCoordinates.Add(new Point(0, 0)); my3D_Restangle.TextureCoordinates.Add(new Point(1, 1)); my3D_Restangle.TextureCoordinates.Add(new Point(1, 0)); // when the label is double sided: if (isDoubleSided) { my3D_Restangle.TextureCoordinates.Add(new Point(1, 1)); my3D_Restangle.TextureCoordinates.Add(new Point(1, 0)); my3D_Restangle.TextureCoordinates.Add(new Point(0, 1)); my3D_Restangle.TextureCoordinates.Add(new Point(0, 0)); }
  5. Teraz jest czas na stworznie obiektu ModelVisual3D z napisem

    ModelVisual3D result = new ModelVisual3D();

    // we are setting the content:

    // our 3D rectangle object covered with materila that is made of label

    // (TextBox with text)

    result.Content = new GeometryModel3D(my3D_Restangle, mataterialWithLabel);

    return result;

(To tylko jedna z części artykułu, przeczytaj pozostałe: 1, 2, 3, 4, 5, 6, 7)

czwartek, 26 marca 2009

Rozwiązanie w praktyce (WPF, C#: Tworzenie napisów w scenach 3D)

Przykładowy kod dołączony do artykułu (dostępny tutaj ) rysuje układ współrzędnych. Scena może być obracana i położenie kamery może być zmieniane przy użyciu suwaków. Pola wyborów znajdujące się w lewym panelu okna aplikacji pozwalają na włączanie i wyłączanie widzialności poszczególnych elementów sceny (w szczególności etykiet 3D i 2D).

Aplikacja może się na pierwszy rzut oka wydawać skomplikowana, jednak są w niej wykorzystane proste elementy WPF 3D i każdy powinien zrozumieć o co w niej chodzi. W tym artykule chciałbym się skupić na tworzeniu napisów i dwóch podejściach opisanych powyżej.

(To tylko jedna z części artykułu, przeczytaj pozostałe: 1, 2, 3, 4, 5, 6, 7)

środa, 25 marca 2009

Dwa podejścia przy tworzeniu napisów w scenach WPF 3D

Naszym celem jest umieszczenie jakichś napisów w tworzonej scenie 3D. Możemy tutaj wyróżnić dwa podejścia:

  • Tworzenie napisów 3D
  • Tworzenie napisów 2D w oparciu o lokalizacje 3D
Podejście pierwsze wymaga stworzenie (narysowanie) obiektu w przestrzeni a następnie pokrycie go napisem. W tym celu tworzony jest pędzel z napisem, którym maluje się obiekt w przestrzeni. Przykładowa scena zawierająca tak stworzone napisy znajduje się na poniższym rysunku:

Podejście drugie wymaga na warstwie zawierającej Viweport3D umieszczenie warstwy zawierającej obiekt typu Canvas, który jest przeżroczysty, na nim umieszczamy TexBlock'i w odpowiedniej lokalizacji, która związana jest z pewnym punktem w przestrzeni. Podejście takie przedstawione jest na rysunku poniżej:

Oczywiście, każde rozwiązanie ma swoje wady i zalety. Etykiety 3D, bazujące na pierwszym podejściu, są bardziej przydatne, gdy tekst jest elementem sceny. Napisy tworzone przy pomocy drugiego podejścia, są zwykle bardziej czytelne, ale bardziej odróżniają się od sceny i obsługa ich jest bardziej skomplikowana. Rysunek poniżej przedstawia porównanie obydwu metod:

(To tylko jedna z części artykułu, przeczytaj pozostałe: 1, 2, 3, 4, 5, 6, 7)

wtorek, 24 marca 2009

Artykuł: Tworzenie napisów dla scen 3D tworzonych przy pomocy WPF

Promuj

Jakiś czas temu postanowiłem rozpocząć moją przygodę grafiką 3D generowaną za pomocą Windows Presentation Foundation (WPF). Muszę przyznać, że biorąc pod uwagę prostotę z jaką można tworzyć grafikę 3D jest to na prawdę dobre narzędzie. Bez większych problemów opanowałem generowaną przy pomocy trójkątów w przestrzeni grafikę, tym bardziej, że bardzo wiele artykułów opisuje właśnie te elementy. Schody pojawiły się w momencie, gdy postanowiłem dodać do moich grafik 3D jakieś napisy. Dlatego właśnie tworzeniu napisów w scenach WPF 3D chciałbym poświęcić niniejszy artykuł.

Aby ułatwić czytanie, artykuł został podzielony na części:

  1. Wstępniak (czyli ten tekst)
  2. Dwa podejścia przy tworzeniu napisów w scenach WPF 3D
  3. Rozwiązanie w praktyce
  4. Napisy przestrzenne (WPF 3D)
  5. Napisy przestrzenne (WPF 3D), a ich wektory położenia
  6. Napisy płaskie (WPF 2D)
  7. Podsumowanie i historia zmian

Zapraszam do lektury (kolejne części będą się pojawiały jako kolejne posty).

(To tylko jedna z części artykułu, przeczytaj pozostałe: 1, 2, 3, 4, 5, 6, 7)

Promuj

poniedziałek, 23 marca 2009

Google Analytics, to nie wszystko, czyli przeglądanie logów serwera IIS (Windows Internet Information Services) z wykorzystaniem LogParser

Narzędzia typu "Google Analytics" są niezwykle pomocne przy śledzeniu popularności witryny, którą administrujemy lub współtworzymy. Niestety czasami są one niewystarczające. Po pierwsze łatwo zmienić ustawienia przeglądarki, by nie wykonywała skryptu dostarczonego prze Google'a (a który odpowiedzialny jest za zbieranie informacji). Po drugie skrypt Google'a można umieścić tylko w kodzie witryny, nie można dodać go do pliku który jest pobierany, czy web-serwisu. W takim przypadku konieczne staje się analizowanie logów serwera WWW. Oczywiście nie należy tego robić ręcznie, a w sieci można odnaleźć wiele programów oferujących zaawansowane funkcje, zbliżone do Google Analytics. Niestety najczęściej nie są one darmowe.

Niedawno stanąłem przed koniecznością przejrzenia logów serwera IIS (Windows Internet Information Services), aby zobaczyć statystyki pobierania pewnych plików (dla których nie możliwe było śledzenie z wykorzystaniem Google Analytics). Ponieważ od początku odrzuciłem możliwość wykorzystania płatnych narzędzi, więc ilość pozostałych możliwości okazała się dość ograniczona. Na szczęście udało mi się znaleźć narzędzie Microsoft'u:

LogParser

Do pobrania dostępny jest tutaj:

http://www.microsoft.com/DownLoads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07&displaylang=en

Jego opis jest tutaj:

http://www.microsoft.com/technet/scriptcenter/tools/logparser/default.mspx

Natomiast przykłady zastosowań:

LogParser jest na pierwszy rzut oka bardzo prostym narzędziem. Obsługuje się go z linii poleceń. Ciekawe jest w nim to, że można do niego przekazywać kwerendy (podobne do SQL'a) i w ten sposób pobierać intersujące nas dane. Zobaczmy przykład: Załóżmy że chcemy przekonać się jakie web-serwisy (i ile razy) były wywoływane z mojego komputera. Web-serwisy na moim komputerze mają postać plików o rozszerzeniu .asmx. Logi IIS w moim komputerze znajdują się w katalogu: 'C:\WINDOWS\system32\LogFiles\W3SVC1\'. Odpowiednie wywołanie będzie więc wyglądało następująco:

C:\Program Files\Log Parser 2.2>logparser "select cs-uri-stem,s-ip,count (*) FROM 'C:\WINDOWS\system32\LogFiles\W3SVC1\ex*.log' where cs-uri-stem like '%.asmx' GROUP by cs-uri-stem,s-ip"
cs-uri-stem s-ip COUNT(ALL *)
-----------------------------------------------
---- ------------
/CAS.OPCWSDataAccess/OPCAdvancedDataAccess.asmx - 42
Statistics:
-----------
Elements processed: 64
Elements output: 1
Execution time: 0.02 seconds


W efekcie widzimy, że został wywołany web-serwis: OPCAdvancedDataAccess.asmx w ilości 42 razy. Dla osób lubiących bazy danych możliwe jest również proste przeniesienie logów do bazy danych, wystarczy wpisać komendę podobną do poniższej:

LogParser "SELECT date, time, s-sitename as SiteName,s-ip as Ip, cs-method as Method, cs-uri-stem as UriStem, cs-uri-query as UriQuery, s-port as Port, cs-username as Username, c-ip as CIp, cs(User-Agent) as UserAgent, sc-status as Status,sc-substatus as SubStatus, sc-win32-status as WinStatus INTO MyLog FROM logfile.log WHERE Cip not like '127.0.0.1' " -i:IISW3C -o:SQL -server:uzytkownik\sqlexpress -database:log -driver:"SQL Server" -createTable:ON -iCheckpoint:C:\myCheckpoint.lpc
Co ciekawe LgoParser może być wykorzystywany nie tylko do logów IIS ale do niemal dowolnych logów dostępnych w systemie Windows. Istnieją również różne nakładki, które wykorzystują LogParser (np. w oparciu o środowisko .NET) i tworzą dla niego pewne GUI upraszczając jego wykorzystanie.

wtorek, 17 marca 2009

Tworzenie obrazu zawierającego filmowe miniatury.

W poprzednim poście pojawił obraz, który był złożony ze zrzutów ekranowych z filmu:

Ponieważ przygotowanie tego obrazka, zajęło mi kilka chwil, dlatego chciałbym się podzielić z moimi czytelnikami wiedzą, jak można taką grafikę przygotować.

Zacznijmy więc od narzędzia, którym można to przygotować. Ja znalazłem, że taką funkcjonalność zawiera oprogramowanie Media Player Classic. Jest on dość popularny i ja np. miałem go już zainstalowany w ramach pakietu kodeków: K-Lite Codec Pack. W celu uzyskania obrazu (jak ten powyższy) wystarczy otworzyć film, zrobić pauzę, a następnie z menu "File" wybrać "Save Thumbnails...". W oknie zapisywania wybieramy plik do zapisu, typ (BMP, JPG), wielkość docelowego obrazu oraz ilość wierszy i kolumn miniatur. W zasadzie proste i łatwe, niestety czekała mnie niemiła niespodzianka: okno z napisem: "GetCurrentImage failed".

Dopiero dłuższa chwila poszukiwań sprawiła, że problem rozwiązałem problem. W tym celu należało wejść w menu View -> Option. Wybrać na drzewku gałąź Output i w "DirectShow Video" wybrać inne niż oznaczony gwiazdką wyjście, np. System Default jak na rysunku poniżej:

Mam nadzieję, że te proste wskazówki pomogą jeszcze komuś innemu poza mną.

poniedziałek, 16 marca 2009

Zaawansowane technologie komunikacyjne w praktyce, czyli CommServer (połączenie z PLC) oraz algorytmy ASA i MPR

Niedawno zajmowałem się w pracy, tworzeniem filmów instruktażowych dotyczących oprogramowania CommServer, komunikacji ze sterownikami przemysłowymi i zaawansowanych technologii komunikacyjnych. Muszę przyznać, że okazało się to dość czasochłonnym zajęciem, biorąc pod uwagę, że trzeba było zacząć od scenariusza i planu, później kręcenie i powtórki, a na końcu żmudny montaż.

Moje przykłady zostały oparte o połączenie między CommServer'em a sterownikiem PLC SAIA PCD3. Mam nadzieję, że filmy okażą się interesujące, zapraszam wszystkich do ich obejrzenia (filmy dostępne są w języku angielskim):

Przykładowe obrazy z filmów:

piątek, 13 marca 2009

"Google: Twoja Wyszukiwarka" (AdSense dla wyszukiwania) na blogu

Ciekawe kogo zdziwił pusty post na tym blogu opublikowany w ostatni piątek (2008-03-06 ok godz 20) pt. "Wyszukiwarka"?

Nie, to nie była pomyłka a prosty manewr - sposób w jaki można opublikować wyniki z wyszukiwarki Google na swoim blogu. Przejdźmy jednak do konkretów. Wykorzystana została usługa "AdSense dla wyszukiwania". Pozwala ona na dodanie do strony internetowej wyszukiwarkę Google. Oczywiście dodanie samego pola do wprowadzania zapytania i przycisku szukaj nie stanowi żadnego problemu: wystarczy dodać w wybranym miejscu gadżet pozwalający na wpisaniu dowolnego kodu HTML i JavaScrip, da to w efekcie np.:

Teraz mamy dwie możliwości:

  • wyniki wyszukiwania możemy wyświetlać na nowej stronie (rozwiązanie mało ciekawe)
  • wyniki wyszukiwania możemy wyświetlać na swoim blogu

Aby skorzystać z drugiej opcji należy wkleić w kod swojej witryny (bloga) odpowiedni kod dostarczany przez instalator usługi "AdSense dla wyszukiwania". Pytanie tylko gdzie można to zrobić? Możliwe jest wklejenie tego kodu bezpośrednio do szablonu XML(HMTL) bloga, jednak wydaje mi się że wyświetlanie tych wyników na każdej stronie chyba będzie mało estetyczne. Dlatego wymyśliłem inną możliwość:

  1. Stworzyłem pustego posta pt.: Wyszukiwarka
  2. Post ten tylko na pierwszy rzut oka nie ma treści, gdyż do jego kodu HTML został wprowadzony dostarczany przez instalator usługi Adsense kod.
  3. Dzięki temu można wyświetlić wyniki wyszukiwania w polu właśnie tego posta.

Mam madzieję że spodobała się moim czytelnikowm takie rozwiązania, zapraszam do wypróbowania i jeśli macie coś do dodania, czekam na komentarze.

Posty powiązane / Related posts