pomiar odległości w QGraphicsView

0

Czy znacie jakieś sposoby, bądź ktoś z was tworzył coś co działaniem mogło by przypominać narzędzie miarki z popularnych programów graficznych lub typu CAD. Kompletnie nie wiem jak się za to zabrać, a koncepcja moja jest taka aby zaznaczyć dwa punkty w obrazie wyświetlanym w QGraphicsView i "zmierzyć" odległość między nimi.

Nie wiem czy na podstawie współrzędnych x i y, które taki kliknięty punkt zwraca np. poprzez liczenie przeciwprostokątnej (przyjmując, że dwa punkty to jej końce a wirtualny punkt tworzący tak jakby trójkąt z trzech punktów uda mi się uzyskać poprzez odjęcie wartości y z dwóch poprzednich punktów) i jakąś konwersje tej wartości na minimetry, czy uzyskam w ten sposób pożądany efekt i czy da się to w ogóle takim tokiem myślenia zrobić? A może istnieją jakieś inne biblioteki bądź funkcje,,które mogą znacznie ułatwić sprawę?

Ktoś, coś, jakiś pomysł?

0

Odległość? Proponuje użycie wektorów (matematyka) o ile jest taka możliwość.

0

Hmm za pomocą wektorów? obecnie testuje obydwa rozwiązanie jednak póki co nie daje to miarodajnego odniesienie do odległości w mm. Jakieś, inne konkretne pomysły jak to wykonać? Jakiej biblioteki użyć? Czy moje myślenie nie nie jest błędne? Za wszystkie wskazówki będę wdzięczny.

0

Nie rozumiem z czym masz problem. Masz obiekty na scenie, które odpowiadają za reprezentację jakiś danych. Te obiekty mogą być klikalne przez myszkę, wiec rozpoznanie tych obiektów ich pozycji i związanych z nimi danych to żaden problem. Mając te dane policzenie odległości i jej "dorysowanie" to też nie problem.

0

Na nowym formie w QGraphicsView wyświetlam dwa obrazy "na sobie". Z poprzedniego forma dostaje wyklikane współrzędne (po 6 na każdy obrazek). Rysuje je ponownie na "nałożonych" obrazach w nowym formie i odpowiednio według pierwszej, klikniętej współrzędnej na jednym jak i drugim obrazie zmieniam pozycje drugiego obrazu w pionie i poziomie:

pixmapItem2->moveBy(-(QString(wspP[6][1]).toDouble()-QString(wspP[0][1]).toDouble()), 0);
pixmapItem2->moveBy(0, -(QString(wspP[6][2]).toDouble()-QString(wspP[0][2]).toDouble()));

tak aby współrzędna nr 1 z jednego i drugiego obrazu się pokryły, analogicznie biorę drugą współrzędną w kolejności i chce obrócić nałożony obraz względem współrzędnej nr 1 tak aby obydwie współrzędne nr 2 się pokryły (możliwe że nałożony obraz będzie trzeba minimalnie wyskalować) pomiędzy pozostałymi współrzędnymi muszę mieć możliwość zmierzenia odległości gdyż one nie mają prawa się pokryć.

Aby nieznacznie obrócić i nałożyć na siebie współrzędne nr 2 z obydwu obrazów (dopasowuje tylko obraz drugi - nałożony, jako pixmapItem2) kombinuje z QTransform, ale tutaj muszę mieć kąt, i póki co nie daje to porządanego efektu.

double pi = 3.14;

    double a    = pi/180 * 45.0; //przykładowy kąt 45 stopni
    double sina = sin(a);
    double cosa = cos(a);

    QTransform transformacjaPixmapItem2(1, 0, 0, 1, -(QString(wspP[6][1]).toDouble()-QString(wspP[0][1]).toDouble()), -(QString(wspP[6][2]).toDouble()-QString(wspP[0][2]).toDouble()));
    QTransform obracaniePixmapItem2(cosa, sina, -sina, cosa, 0, 0);
    QTransform skalowaniePixmapItem2(1.0, 0, 0, 1.0, (QString(wspP[7][1]).toDouble()-QString(wspP[1][1]).toDouble()), (QString(wspP[7][2]).toDouble()-QString(wspP[1][2]).toDouble()));
    QTransform obrotPixmapItem2 = transformacjaPixmapItem2 * obracaniePixmapItem2 * skalowaniePixmapItem2;

Samo obrazanie w taki sposób działa, jednak obrót zostaje wykonany o zadaną wartość kąta a nie odpowiadającą pokryciu współrzędnych nr 2

Mając współrzędne dwóch punktów, gdzie mam możliwość powiększania i zmniejszania obrazu rolką myszki w tym QGraphicsView po ich odpowiednim odjęciu dostaje wartosć w pikselach, jednak inna ona jest jeśli wykonuje pomiar na dużym powiększeniu a inna jeśli wykonuje pomiar na oddaleniu sceny w rzeczonym QGraphicsView.

Co może być nie tak z tym QTransform i jak poprawnie zrobić to mierzenie odległości?

0

prawdziwy majstersztyk, w pojedynczej linijce kodu masz niespotykane nagromadzenie WTF. Wygląda na to, że na każdym poziomie masz coś źle, od szczegółów takich jak QString(wartość).toDouble() po cały projekt relacji klas.
Jeśli ciebie nie boli głowa od czytania tego kodu, to podziwiam.

Niestety twój opis jest tak mętny, że nadal nie wiadomo co chcesz zrobić. Radzę zacznij od opisania jaką funkcjonalność ma mieć twój program (w tej chwili nie rozumiem po kiego grzyba wciskasz tam pixmapItem, skoro ze wcześniejszego opisu wynika, ze masz dane wektorowe - odwołałeś się do CAD-a).

QTransform zapewnia ci zestaw funkcji do obrotów itp (np rotate), więc nie musisz tego tworzyć ręcznie. No chyba, że lubisz takie krzaczki.

0

Może dlatego mam ciągle jakieś problemy, że to jest mój pierwszy i chyba jedyny projekt w obiektowym C++ i do tego jeszcze w Qt. Nie planuje dalej wiązać przyszłości z tym językiem a niestety projekt muszę wykonać. Głowa mnie już troche od tego wszystkiego boli jednak pozostały w sumie dwie ostatnie rzeczy do zrobienia o których pisałem posta wyżej i na zawsze się pożegnam z Qt dlatego nagromadzenie różnej maści udziwnień musze jakoś przeboleć :/

Do sedna:

pixmapItem'ów używam aby "nałożyć" na siebie dwa obrazy i aby były przezroczyste w pewnym stopniu a tutaj funkcja setOpacity działa dość dobrze, a poza tym na rzecz pixmapItem'ów mogę wywołać moveBy co ułatwia mi pozycjonowanie obrazów "na sobie" w pionie i w poziomie względem konkretnych współrzędnych i do tego momentu jest ok. Wyświetlam dwa obrazy i pozycjonuje je w pionie i poziomie względem współrzędnej którą mam w tablicy.

Schody zaczynają się gdy chce "nałożony" obraz nieznacznie obrócić. Znaczy to, że mając punkt, który jest osią obrotu drugiego obrazu względem tła (obrazu numer jeden) i osobne dwa punkty (jeden na jednym obrazie, drugi na drugim), muszę obrócić ten drugi obraz w taki sposób aby te punkty się pokryły.

QTransform obrotPixmapItem2;
    obrotPixmapItem2.translate((QString(wspP[6][1]).toDouble()-QString(wspP[0][1]).toDouble()), (QString(wspP[6][2]).toDouble()-QString(wspP[0][2]).toDouble())); //oś obrotu
    obrotPixmapItem2.rotate(-(QString(wspP[7][1]).toDouble()-QString(wspP[1][1]).toDouble()), Qt::XAxis); // wspP[1][1] to x wspP[1][2] to y punktu na obrazie nr 1 <--
    obrotPixmapItem2.rotate(-(QString(wspP[7][2]).toDouble()-QString(wspP[1][2]).toDouble()), Qt::YAxis); // wspP[7][1] to x wspP[7][2] to y punktu na obrazie nr 2 <-- punkty te mają się pokryć przez rotacje obrazu nr 2
    obrotPixmapItem2.scale(1.0, 1.0);
    obrotPixmapItem2.translate(-(QString(wspP[6][1]).toDouble()-QString(wspP[0][1]).toDouble()), -(QString(wspP[6][2]).toDouble()-QString(wspP[0][2]).toDouble()));
    pixmapItem2->setTransform(obrotPixmapItem2);
    pixmapItem2->update();

Używam rotate() jednak jako argument przyjmuje ona kąt, a ja mam dwie współrzędne, które muszą się pokryć, a co za tym idzie kąt może być zmienny wraz z załadowaniem innej pary obrazów.

0

Co do samego mierzenia odległości to moja początkowa koncepcja wektorowa zawiodła (różne wartości przy różnym stopniu powiekszenia) i musze od nowa napisać tą funkcjonalność, choć kompletnie nie wiem jak to mogę a raczej jak to mam zrobić. Jakieś propozycje ludzi, którzy jeszcze nie zwątpili we mnie? :/

0

Bierzesz się za duży projekt i bardziej zaawansowany freamework, kiedy nadal nie umiesz dobrze programować. IMO nadal powinieneś być w fazie zadań na SPOJ lub coś w tym stylu. Najlepiej to widać po tym jak próbujesz zwalić winę na narzędzia. Tymczasem po twoim kodzie wyraźnie widać, że bez względu na język/freamework będziesz miał te same kłopoty, bo masz problem z napisaniem jednej zrozumiałej dla ludzi linijki. Mało tego wygląda na to, że celowo komplikujesz sobie życie (ta tablica wspP ewidentnie zawiera zły typ przez co zawsze musisz robić bezsensowne konwersje).

Popatrz na kod, który np dałem tu. Nie chodzi nawet o sam algorytm, ale czytelność poszczególnych linijek.

Gdy pisałem "Radzę zacznij od opisania jaką funkcjonalność ma mieć twój program" to miałem nadzieje, że napiszesz coś zrozumiałego, np przepiszesz treść zadania jakie dostałaś do wykonania (albo dasz linka do tego zadania). Tymczasem ty cały czas opisujesz jak próbujesz to coś osiągnąć (a skoro ci to nie wychodzi to raczej nie mam szans tego zrozumieć). Napisz CO chcesz zrobić, a zapomnij na razie JAK chcesz to zrobić.

0

Masz 100% racje we wszystkim co piszesz, niestety :/ Mam świadomość, że nie umiem dobrze programować, bo w sumie nie mam dużego zawodowego doświadczenia w programowaniu a na studiach informatycznych nikogo nie nauczą programować (pokazują tylko możliwości i mniej więcej mówią czym można je osiągnąć a nie w jaki dokładnie sposób). To już zależy od człowieka czy chce się tym zajmować i czy ma jakiekolwiek pojęcie. Pewnie powiesz że ja pojęcia nie mam biorąc się za taki projekt - może i masz racje, nie neguje tego bo sam widzę ile podczas każdego kolejnego projektu się uczę i nie brak mi zapału bo chcę kiedyś powiedzieć, że umiem programować. Teraz tego nie mówię (powołuje się czasami na jakieś projekty, które wykonywałem, ale jak dobrze się przyjrzeć to żaden z nich nie zasługuje na miano projektu z prawdziwego zdarzenia - raczej małe programiki), z resztą dlatego udzielam się na tym forum aby postawione sobie cele realizować z waszą pomocą i nabierać przy tym doświadczenia, od ludzi, którzy niejednokrotnie mają już kilkuletnie doświadczenie, a jak wiadomo należy uczyć się od najlepszych :). Co do Qt, do samego środowiska w sumie nic nie mam, jednak wkurza mnie czasami rozrzucenie typowej klasy na kilka plików, może to kwestia przyzwyczajenia albo nastawienia. Nie miałem wcześniej do czynienia z Qt i pewnie po zakończeniu tego projektu nie będę miał z nim do czynienia długo o ile wcale.

Co do nieszczęsnego projektu i konkretnego wytłumaczenia o co mi chodzi i co chce zrobić.
Wyświetlam dwa obiekty pixmapItem - jeden na drugim z pewnym poziomem przezroczystości (tak aby można było dostrzec różnice), zaznaczam po 2 punkty (markery) na każdym z obrazów, współrzędne tych punktów ładuje do wspomnianej tablicy wspP po to aby obraz na pierwszym planie odpowiednio przemieścić i obrócić tak aby markery z pixmapItem1 i pixmapItem2 się pokryły. Pierwszą część tak jakby zrobiłem tzn. obraz przemieściłem w pionie i poziomie według pierwszej pary markerów (pierwszy marker na obrazie nr 1 i pierwszy marker na obrazie nr 2)

QGraphicsPixmapItem *pixmapItem2 = scenaWynikowa->addPixmap(mapaPikseli2);
pixmapItem2->setGraphicsEffect(poziomPrzezroczystosci);
pixmapItem2->moveBy(refX1, 0);
pixmapItem2->moveBy(0, refY1);

teraz za pomocą drugiej pary markerów chcę obiekt pixmapItem2 obrócić w taki sposób aby druga para markerów się pokryła. Obraz pixmapItem2 muszę jednak obrócić względem pierwszej pary markerów, tzn. tych które pozycjonują obraz w pionie i w poziomie. Mam współrzędne drugiej pary markerów aczkolwiek metoda rotate() wywoływana na rzecz obiektu typu QTransform przyjmuje jako argument kąt a nie współrzędną x i y. Ot cały problem.

double pi = 3.14;
double a    = pi/180 * 1.0;
double sina = sin(a);
double cosa = cos(a);

QTransform transformacjaPixmapItem2(1, 0, 0, 1, refX1, refY1);
QTransform obracaniePixmapItem2(cosa, sina, -sina, cosa, 0, 0);
QTransform skalowaniePixmapItem2(1.0, 0, 0, 1.0, -refX2, -refY2);
QTransform obrotPixmapItem2 = transformacjaPixmapItem2 * obracaniePixmapItem2 * skalowaniePixmapItem2;
pixmapItem2->setTransform(obrotPixmapItem2);
pixmapItem2->update();

Taki kod działa jedynie dla stałej wartości kąta (tutaj 1 stopień), ja jednak nie znam tej wartości, mam dwie współrzędne które mają się zrównać.
Przygotowałem schemat aby to lepiej zobrazować (chodzi mi o przejście między kropkiem 2 a 3 - w tej chwili krok 2 jest wykonywany):
user image
(plik także w załączniku do tego posta, gdyby były problemy z otwarciem)
Myślę że jest to już teraz zrozumiałe.

Co do odmierzania odległości, to kombinuje w tej chwili z rysowaniem prostych myszką za pomocą QPainter i metody draw, a jak już mi to zadziała to myślę że z długością lini w pikselach - konwersja na minimetry nie będzie jakaś skomplikowana. Za dużo kombinowałem wcześniej przez co wydawało mi się że jest to nie do zrobienia, czego owocem był ten topic a jak to mówią proste rozwiązania są najlepsze. No chyba że macie jakieś inne pomysły? Chętnie się z nimi zapoznam.

1 użytkowników online, w tym zalogowanych: 0, gości: 1