diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 173fb138319fc0bd3923ad2077c522145e4122f6..81d1c47cbcf61292bc12dc889d45a1b06cfc9111 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -79,10 +79,10 @@ publish:
     - apt-get update -qq && apt-get install -y -qq lftp
     #- lftp -c "set ftp:ssl-allow no; open -u $FTP_USERNAME,$FTP_PASSWORD $FTP_HOST; mirror -Rnev $CI_PROJECT_DIR/application/target ./$FTP_TARGET_DIR --ignore-time --parallel=10 --exclude-glob .git* --exclude .git/"
     - lftp -c "set ftp:ssl-allow yes; set ssl:verify-certificate false; open -u $FTP_USERNAME,$FTP_PASSWORD $FTP_HOST; cd $FTP_TARGET_DIR; mput -c $CI_PROJECT_DIR/application/target/$PROJECT_ARTIFACT_ID-$VERSION.zip; put -c $CI_PROJECT_DIR/application/target/$PROJECT_ARTIFACT_ID-$VERSION.zip -o $PROJECT_ARTIFACT_ID-LATEST.zip"
-    - lftp -c "set ftp:ssl-allow no; open -u $FTP_USERNAME,$FTP_PASSWORD $FTP_HOST; mirror -Rnev $CI_PROJECT_DIR/target/site/apidocs ./$FTP_TARGET_DIR/apidocs --ignore-time --parallel=10"
-    - lftp -c "set ftp:ssl-allow no; open -u $FTP_USERNAME,$FTP_PASSWORD $FTP_HOST; mirror -Rnev $CI_PROJECT_DIR/MeshModel/target/site/apidocs ./$FTP_TARGET_DIR/apidocs-MeshModel --ignore-time --parallel=10"
-    - lftp -c "set ftp:ssl-allow no; open -u $FTP_USERNAME,$FTP_PASSWORD $FTP_HOST; mirror -Rnev $CI_PROJECT_DIR/GUI/target/site/apidocs ./$FTP_TARGET_DIR/apidocs-GUI --ignore-time --parallel=10"
-    - lftp -c "set ftp:ssl-allow no; open -u $FTP_USERNAME,$FTP_PASSWORD $FTP_HOST; mirror -Rnev $CI_PROJECT_DIR/Comparison/target/site/apidocs ./$FTP_TARGET_DIR/apidocs-Comparison --ignore-time --parallel=10"
+    - lftp -c "set ftp:ssl-allow no; open -u $FTP_USERNAME,$FTP_PASSWORD $FTP_HOST; mirror -Rev $CI_PROJECT_DIR/target/site/apidocs ./$FTP_TARGET_DIR/apidocs --ignore-time --parallel=10"
+    - lftp -c "set ftp:ssl-allow no; open -u $FTP_USERNAME,$FTP_PASSWORD $FTP_HOST; mirror -Rev $CI_PROJECT_DIR/MeshModel/target/site/apidocs ./$FTP_TARGET_DIR/apidocs-MeshModel --ignore-time --parallel=10"
+    - lftp -c "set ftp:ssl-allow no; open -u $FTP_USERNAME,$FTP_PASSWORD $FTP_HOST; mirror -Rev $CI_PROJECT_DIR/GUI/target/site/apidocs ./$FTP_TARGET_DIR/apidocs-GUI --ignore-time --parallel=10"
+    - lftp -c "set ftp:ssl-allow no; open -u $FTP_USERNAME,$FTP_PASSWORD $FTP_HOST; mirror -Rev $CI_PROJECT_DIR/Comparison/target/site/apidocs ./$FTP_TARGET_DIR/apidocs-Comparison --ignore-time --parallel=10"
   tags:
     - shared-fi
   rules:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e178090832e6d547b8efdc28340627a885f271e4..06cfc5fef280ca70c5fc8191317ebaaea5d958c1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,57 +1,576 @@
-* 513fe51 -- Update pom.xml version.
-* 4003fd4 -- Use Gaussian curvature for symmetry plane by default
-*   14adb31 -- Merge branch 'issue12' into 'master'
+* 169c15e -- Update pom.xml version.
+* c6dbf83 -- Version tag changed from vYYYY.MM to YYYY.MM
+*   26990b9 -- Merge branch '102-adapt-hd-control-panel' into 'master'
 |\  
-| * fc88197 -- Final styling before merge
-| * 7550d1e -- symmetry plane is being displayed amd calculated when requested
-| * 1dcc5d5 -- symmetry plane GUI buttons
+| * 14be265 -- Fixed JavaDoc typos and errors
+| * 4112acd -- Typo fixed
+| * 281a084 -- Feature point is higlighted when the cursor hovers over its name
+| * 0456b54 -- Minor refactoring
+| * a093ec3 -- Repeated scene rendering eliminated
+| * bf98047 -- Weighted feature points displayed as a wire sphere
+| * be396a7 -- Scene extended to display any drawable objects
+| * 2fec543 -- Variable render modes of drawable feature points
+| * 47cfea0 -- Javadoc fix
+| * 48a5ff8 -- Javadoc fix
+| * cfd0137 -- Initially select only non-NaN feature points
+| * 923a129 -- Initially select all feature points for the weighted Hausdorff distance
+| * 1039fb0 -- Heatmap of Hausdorff distance re-rendered after ICP is performed
+| * 1492977 -- Remove "Hausdorff Distance" and "Registration" buttons from the toolbar
+| * fe0fb33 -- Display statistics of ordinary and weighted Hausdorff distance side by side
+| * af7464a -- Do not recompute Hausdorff distance if not necessary (feature point is not selected)
+| * f890f4d -- Recompute weighted distance immediately on any checkbox/slider action
+| * 608c6fb -- Unnecessarily repeated computation of feature point weights eliminated
+| * 9b0c8eb -- Feature point weights displayed next to the FP-radius slider
 |/  
-*   35bd24e -- Merge branch '63-fix-significantpoints' into 'master'
+*   c63de42 -- Merge branch '101-implemenet-gui-for-weighted-hd' into 'master'
 |\  
-| * 139379a -- Added test files, for sure
-| * 7465c8b -- Typos
-| * 03b964a -- Removed obsolete local method
+| * 01c5914 -- Javadoc finished
+| * 6cdc16c -- Unnecessarily repeated computation on weighted-HD-ON/OFF switch eliminated
+| * 260b207 -- Index-in-bounds check added
+| * 26dde5e -- For-loop replaced by stream
+| * 6a15d1e -- Computation of weighted Hausdorff distance implemented
+| * e529f21 -- Prioritized Hausdorff distance computation corrected for missing feature points
+| * 90b834f -- Stream replaced with for-loop
+| * 659c352 -- Overview of feature point weights implemented
+| * 009fae1 -- Overview of Hausdorff distance statistics implemented
+| * 6bb1fe5 -- Action for the computation of weighted Hausdorff distance prepared
+| * 956a7c8 -- Conditions for button enabling corrected
+| * 50a5431 -- Button for repetition of computation of the weighted Hausdorff distance added
+| * 8de1f74 -- Check box for weighted Hausdorff distance added
+| * b87d11d -- Selection of feature points by their type corrected
+| * 48225d0 -- Change size of selected feature points
+| * aa1e526 -- Highlight selected feature points
+| * 1e6786c -- Display list of feature points
+| * ebcab44 -- Minor corrections of javadoc and code style
+| * 9ee50db -- Action event extended to carry additional data
+| * 92a5472 -- Variable radii of priority spheres around individual feature points
+| * 8a88a6c -- Negative radius check implemented
+| * f37c188 -- Drawable face holds HumanFace
+| * 9c78eab -- Using visitor for computation of weighted Hausdorff distance
+| * 7f1992d -- Variable sizes of drawable feature points
 |/  
-*   7ca60fa -- Merge branch '62-refactor-symmetryestimator-as-visitor' into 'master'
+*   1f62d3d -- Merge branch '68-implement-weighted-HD-sphere-around-feature-point-step-2' into 'master'
 |\  
-| * 74086ba -- Final refactoring
-| * 086b5d3 -- Documentation
-| * 2dd4888 -- SignificantPoints is visitor now
-| * 1991af7 -- SymmetryEstimator is visitor now
-| * 6472f36 -- Adaptation to multiple mesh facets
-| * cc26da1 -- image:latest changed to image:3-jdk-11
-|/  
-*   737a43b -- Merge branch '60-remove-concurrency-from-visitors' into 'master'
-|\  
-| * bd8233f -- Style check
-| * 725fc32 -- Removed the concurrency paramater from visitors
+| * d8de484 -- Feature point weights implemented correctly
+| * 74b71a4 -- Error of multiplication by zero at zero scalar product fixed
+| * 406b65b -- Wrong computation of weighted Hausdorff distance on FPs reverted
+| * f7d8911 -- Javadoc finished
+| * 7a6a0fe -- Javadoc for methods finished
+| * 7a36c33 -- Javadoc modified with respect to feature point types
+| * 5934630 -- Empty lines added for better readability
+| * 631596f -- PrioritySphere Javadoc updated
+| * 856f3a2 -- Tests for prioritized Hausdorff distance visitor implemented
+| * a418e28 -- Error fixed
+| * ec0abc6 -- Test infrastructure for prioritized-HD-HumanFace visitor prepared
+| * cd8f6dc -- Priority sphere tests updated for weighted distance
+| * 8131fba -- Visitor modified to computie priorities with respect to the closest feature point
+| * e809a0d -- HumanFace added to Maps - in case multiple faces with same MeshFacets and different sets of feature points occurred
+| * d90652b -- Sum of weighted distances around feature points implemented
+| * 39aab8e -- PrioritySphere visitor clears list of priorities when a facet is processed repeatedly
+| * ad15fe8 -- HumanFace visitor modified to accept multiple feature point types
+| *   7535bb0 -- Merge remote-tracking branch 'origin/master' into 68-implement-weighted-HD-sphere-around-feature-point-step-2
+| |\  
+| |/  
+|/|   
+* |   b10d46a -- Merge branch '100-improve-icp-registration-panel' into 'master'
+|\ \  
+| * | 29232a1 -- Removed GUI artefacts
+| * | d0e0920 -- Fixed ICP transformation of feature points
+| * | c830581 -- Registration panel extended with Hausdorff distance
+| * | 6424c69 -- Complex registration panel
+| * | 76ee47a -- Color of FPs and their statistics
+|/ /  
+* |   b55dbb1 -- Merge branch '99-fix-and-refactor-canvas' into 'master'
+|\ \  
+| * | b35ec78 -- Finished control panel buttons
+| * | 3b8cc30 -- Checkstyle fixes
+| * | ff01aba -- Minor refactoring
+| * | 58e55f2 -- Refactor with respect to rules
+| * | eb5bffa -- Refactored design of canvas
+|/ /  
+| * 6491cf7 -- Map of priorities modified to accept multiple feature point types
+| * 9137500 -- Constructor adapted to accept set of feature point types
 |/  
-*   4e682e3 -- Merge branch '54-adapt-hausdorffdistance-for-icp' into 'master'
+* cb4bb77 -- CHANGELOG.md file updated with commits between the current and previous tag.
+* 807ff47 -- Update pom.xml version.
+*   2392ba3 -- Merge branch '98-setup-basic-layout' into 'master'
 |\  
-| * f365493 -- Fixed errors
-| *   42849fa -- Merge branch 'master' into 54-adapt-hausdorffdistance-for-icp
+| * 2e85cb2 -- Added icons
+| * 8c183a7 -- Stylecheck
+| * 5a82334 -- Feature points
+| * 7e38442 -- Code cleansing
+| * d3b6438 -- Refactored RegistrationPanel
+| * da5bea1 -- Project top component moved to core package
+| * 452de28 -- Javadoc
+| * bcc53f2 -- Face-to-face tab with Hausdorff distance
+| * 340bb27 -- Improved curvature coontrol panel
+| * 610bcda -- Basic functional curvature panel
+| * 82c73c7 -- Improved logic of the symmetry panel and control panel builder
+| * 588745c -- Major refactoring; GUI builder
+| * d342ce3 -- CurvatureAlg put into SymmetryConfig
+| * 094efa0 -- Distinguishing drawables in the scene + refactoring
+| * bfa771b -- Aggregated action listeners for rendering
+| * 0030579 -- Added rendering mode icons
+| * 6aa7c19 -- Added 3-state button to the rendering toolbar
+| *   4c4bf4e -- Merge branch 'master' of gitlab.fi.muni.cz:grp-fidentis/analyst2 into 98-setup-basic-layout
 | |\  
 | |/  
 |/|   
-* |   0774ac0 -- Merge branch '53-improve-closestnodemultiplevisitor' into 'master'
+* |   fb2638e -- Merge branch '68-implement-weighted-hausdorff-distance-sphere-around-feature-point' into 'master'
 |\ \  
-| * | 85cee61 -- Improved KdTreeDistance
-* | |   4e4f529 -- Merge branch '53-improve-closestnodemultiplevisitor' into 'master'
+| * | bc48f2f -- putIfAbsent replaced with computeIfAbsent
+| * | 9933957 -- Typo fixed
+| * | df6af6f -- Method for radius computation extracted
+| * | 7695a58 -- Feature points implement Serializable
+| * | 3ebdc53 -- Own parallel implementation deleted and existing implementation used instead
+| * | e2fa67e -- PrioritySphere tests implemented
+| * | 93e4485 -- Fixed error in adding collection of facets
+| * | de03315 -- Javadoc modified
+| * | 97d5bd2 -- HausdorffDistancePrioritized javadoc added
+| * | 3499640 -- PrioritySphere javadoc added
+| * | 8fb687e -- Attribute renamed
+| * | 3dcc33b -- Forgotten merge conflict message resolved
+| * | 0b63e7c -- Code commented as it is in master branch
+| * | daf41b6 -- HumanFace javadoc added
+| * |   2cec121 -- Merge remote-tracking branch 'origin/master' into 68-implement-weighted-hausdorff-distance-sphere-around-feature-point
+| |\ \  
+| |/ /  
+|/| |   
+* | |   5fe20e6 -- Merge branch '93-fix-transparency' into 'master'
+|\ \ \  
+| * | | 88d9192 -- Final minor improvements
+| * | | dfd5d8b -- Removed test output
+| * | | e273b36 -- Fixed bug in HumanFaceFactory
+| * | |   a1ee456 -- Merge origin/master into 93-fix-transparency
+| |\ \ \  
+| |/ / /  
+|/| | |   
+| * | | 78c5c80 -- Fixed PostRegistrationCP
+| | * | 4c2896e -- Prioritized distance computation parallelized
+| | * | 5f27f6f -- Prioritized distance on sphere moved to separate visitor
+| | * | a8f31cd -- Computation of prioritized Hausdorff distance parallelized
+| | * | 9c45918 -- Tests of feature points use checked exception
+| | * | 6e72aad -- Import of feature points uses checked exception
+| | * |   d194114 -- Merge remote-tracking branch 'origin/master' into 68-implement-weighted-hausdorff-distance-sphere-around-feature-point
+| | |\ \  
+| | * | | fc7e127 -- Revert "Attributes instantiation enabled for child classes"
+| | * | | 6c66eb5 -- Delete prioritized Hausdorff distance mesh visitor
+| | * | | 3a94028 -- Prioritized Hausdorff distance implemented as a Human face visitor
+| | * | | 5f4976f -- Feature point position stored as Point3d
+| | * | | 9d0e677 -- Feature point compilation error fixed
+| | * | | cb0bb4d -- Human face visitor declared
+| | * | | 2205423 -- Javadoc fixed
+| | * | | 0aefaac -- Feature points added to HumanFace
+| | * | | 494ae8b -- Feature points import/export service made static; Inappropriate Optimal return value changed
+| | * | |   c0b5f22 -- Merge remote-tracking branch 'origin/master' into 68-implement-weighted-hausdorff-distance-sphere-around-feature-point
+| | |\ \ \  
+| | * | | | 1cb76b6 -- Temporary int replaced by Feature point type
+| | * | | | e2ed0ea -- Compilation error fixed
+| | * | | |   41b5366 -- Merge remote-tracking branch 'origin/master' into 68-implement-weighted-hausdorff-distance-sphere-around-feature-point
+| | |\ \ \ \  
+| | * \ \ \ \   4beaebd -- Merge remote-tracking branch 'origin/master' into 68-implement-weighted-hausdorff-distance-sphere-around-feature-point
+| | |\ \ \ \ \  
+| | * | | | | | 943f6b8 -- Priority list update implemented
+| | * | | | | | a1f3f72 -- Attributes instantiation enabled for child classes
+| | * | | | | | 609d5a1 -- Wrong data type corrected
+| | * | | | | | adee569 -- Distance priority calculator implemented
+| | * | | | | | 0010cd6 -- Prioritized Hausdorff distance class initialization
+| | | | | | | * 32d757b -- Introduced basic Drawable hierarchy
+| | | | | | | * b112d96 -- Rendering toolbar
+| | | | | | | * 45b31d1 -- Added rendering toolbar
+| | | | | | | * 8cb9711 -- ...
+| |_|_|_|_|_|/  
+|/| | | | | |   
+* | | | | | |   36fab79 -- Merge branch '96-introduce-facefilechooser' into 'master'
+|\ \ \ \ \ \ \  
+| * | | | | | | 20c2263 -- Removed obsolete PreferencesTopComponent
+| * | | | | | | 8309038 -- Removed obsolete ModelFileFilter
+| * | | | | | |   3aba2a6 -- Merge branch 'master' of gitlab.fi.muni.cz:grp-fidentis/analyst2 into 96-introduce-facefilechooser
+| |\ \ \ \ \ \ \  
+| |/ / / / / / /  
+|/| | | | | | |   
+* | | | | | | | fd5190b -- CHANGELOG.md file updated with commits between the current and previous tag.
+* | | | | | | | ce11ac0 -- Update pom.xml version.
+* | | | | | | |   f549947 -- Merge branch '88-improved-maping-distances-on-heatmap' into 'master'
+|\ \ \ \ \ \ \ \  
+| * | | | | | | | 414f402 -- Histogram works with values for more facets
+| * | | | | | | | b8a7b71 -- added histogram panel to heatMapTestApp
+| * | | | | | | | c5224c4 -- changed histogram to JPanel
+| * | | | | | | | 17cf55c -- changed displaying histogram
+| * | | | | | | | 03021b7 -- Fixed computing frequencies
+| * | | | | | | | 24aee65 -- Using histogram in HeatMapTests
+| * | | | | | | | 2e8478d -- Added histogram class
+| | |_|_|_|/ / /  
+| |/| | | | | |   
+* | | | | | | |   8499395 -- Merge branch '93-fix-transparency' into 'master'
+|\ \ \ \ \ \ \ \  
+| | |_|/ / / / /  
+| |/| | | | | /   
+| |_|_|_|_|_|/    
+|/| | | | | |     
+| * | | | | | 3ea5512 -- Minor refactoring
+| * | | | | | 37db6d0 -- Fixed small bug
+| * | | | | | e5803dc -- Minor Jvadoc changes
+| * | | | | | 1881e36 -- Javadoc finished
+| * | | | | | a213ab6 -- Added some javadoc
+| * | | | | | 75102c6 -- Fixed backface to render properly
+| * | | | | | 6607c8b -- Files moved, created registration package, minor refactoring
+| * | | | | | 36092a1 -- Added back light
+| * | | | | | 2f3d960 -- Wireframe removed
+| * | | | | | 0edd94e -- UI refactor and redesign, changed base colors
+| * | | | | | 45d893b -- UI refactor
+| * | | | | | 7472f45 -- UI redesign
+| * | | | | | 641f1c9 -- Refactored animation
+| * | | | | | 02559b1 -- Animation now works
+| * | | | | | ba5c798 -- Implemented custom feature points thershold
+| * | | | | | aa4ea94 -- Refactored to use FeaturePoint class
+| | | * | | | b8872bf -- Added FileChooserBuilder
+| | | * | | | 97993b7 -- Added new standsrd Option panel into the netbeans platform application
+| | | * | | | 1876fc7 -- Added getName() to HumanFace
+| |_|/ / / /  
+|/| | | | |   
+* | | | | |   fdf994f -- Merge branch '93-fix-transparency' into 'master'
+|\ \ \ \ \ \  
+| |/ / / / /  
+| * | | | | 265034b -- Added mock feature points and their functionality
+| * | | | | 71f74cf -- Added apply all functionality
+| * | | | | f7677ee -- Refactored PostRegstrationCP
+| * | | | | 9a1016c -- Added render mode controls, wireframe mode removed from SceneRenderer
+| * | | | | 4ea0f30 -- Added highlights controls
+| * | | | | 40432fe -- Moved transformation code into function
+| * | | | | f9c00ee -- Renders material instead of color
+| * | | | | 7317d4c -- Fixed transparency rendering, by reversing rendering order
+| * | | | | 40cc5fd -- Changed transparency to float
+* | | | | |   3f037c1 -- Merge branch '91-introduce-symmetrytransformer' into 'master'
+|\ \ \ \ \ \  
+| |/ / / / /  
+|/| | | | |   
+| * | | | | fbd9d12 -- Finalization
+| * | | | | ed288d4 -- Minor refactoring
+| * | | | | c093fc2 -- Re-implementation
+* | | | | |   ec62563 -- Merge branch '86-registration-panel' into 'master'
+|\ \ \ \ \ \  
+| |/ / / / /  
+|/| | | | |   
+| * | | | | 45056bb -- Camera refactoring
+| * | | | |   a7d88c9 -- Resolved merge conflict
+| |\ \ \ \ \  
+| |/ / / / /  
+|/| | | | |   
+* | | | | |   10a7b25 -- Merge branch '90-create-icp-visitor' into 'master'
+|\ \ \ \ \ \  
+| |_|_|_|_|/  
+|/| | | | |   
+| * | | | | 9cb3de7 -- IcpVisitor renamed to IcpTransformator
+| * | | | | bf7053f -- Removed old Icp class
+| * | | | | d549463 -- Rre-using IcpVisitor for batch registration
+| * | | | | e63a831 -- Javadoc
+| * | | | | 6402a9e -- Removed parallel computation of avg template face
+| * | | | | e359b9e -- Fixed computation of avg template face
+| * | | | | 352992b -- Fixed computation of free memory
+| * | | | | 5ff5868 -- Introduce average mesh visitor
+| * | | | | ebb5057 -- Face caching re-implemented and renamed to HumanFaceFactory
+| * | | | | 1ebf43e -- Typos in Javadoc
+| * | | | | 9215813 -- HumanFace extended with the k-d tree computation methods
+| * | | | | 84bd611 -- Underasmpling classes renamed
+| * | | | | fd41844 -- Minor improvements
+| * | | | | 28088f7 -- Fixed randrom reduction
+| * | | | | fb40103 -- Added IcpVisitor with basic vertex-reduction strategies
+|/ / / / /  
+| * | | | 27a4a8c -- Fixed and refactored to use double instead of float
+| * | | | 27f951a -- Adjusted changing factors, added buttons for smaller change
+| * | | | 2b49cf2 -- Added change based on bounding box
+| * | | | 27a739d -- All adjustment previews work
+| * | | | ebfe905 -- Rotation adjustment preview works
+| * | | | fded70e -- Adjusted PostRegistrationCP, look and buttons actions
+| * | | | 60e0cbb -- Added translation, rotation and scale rendering
+| * | | | a693d6c -- Refactored and adjusted color
+| * | | | 764fc93 -- Color and transparency are working, created testing panel
+| * | | | cd56a11 -- Moved PostRegistrationCP into tab package, implemented color rendering
+| * | | | dbcbe11 -- Enabled color in GL and added color to DrawableMesh
+| * | | |   438cc64 -- Merge origin/master into 86-registration-panel
+| |\ \ \ \  
+| |/ / / /  
+|/| | | |   
+* | | | |   d2d3f77 -- Merge branch 'fix-ICP' into 'master'
+|\ \ \ \ \  
+| * | | | | 7291810 -- Final refactoring
+| * | | | | 11b9b34 -- Quaternion extends Quat4d
+| * | | | | 7708b06 -- Further minor improvements
+| * | | | | 9d39bf3 -- Fixed javadoc
+| * | | | | 7516822 -- Fixed code style
+| * | | | | e519994 -- fix Quaternion
+| * | | | |   c829856 -- ICP with Point3d
+| |\ \ \ \ \  
+| | * | | | | 1d9816f -- ICP fixed
+| | * | | | | 1cb13a8 -- not working ICP
+| * | | | | | 4f2204d -- ICP with Point3d
+| | |_|/ / /  
+| |/| | | |   
+* | | | | |   0ee763b -- Merge branch '89-refactor-scene-classes' into 'master'
+|\ \ \ \ \ \  
+| |/ / / / /  
+|/| | | | |   
+| * | | | | f6f4da2 -- Further refactoring
+| * | | | | ecfe983 -- Removed newgui package, classes moved to gui
+| * | | | | 81f5828 -- Fixed bug in setting backgound color
+| * | | | | bc86001 -- Update
+| * | | | | 58669b7 -- Initial refactoring
+|/ / / / /  
+| | * | | f7d2f43 -- aditional PostRegistrationCP adjustments
+| | * | | 97d7f14 -- Adjusted basic PostRegistrationCP
+| | * | | 06c014a -- Finished basic PostRegistrationCP
+| | * | | f855a0b -- Edited PostRegistrationCP
+| | * | | 2b77f49 -- Deleted PreRegistration and ReistrationMethod, PostRegistrationPanel renamed as PostRegistrationCP and moved into newgui
+| | * | | f502a81 -- Added transparency slider
+| | * | |   0c74a4d -- Merge origin/master into 86-registration-panel
+| | |\ \ \  
+| |_|/ / /  
+|/| | | |   
+* | | | |   452aceb -- Merge branch '85-replace-vector3d-with-point3d-in-basic-data-structures' into 'master'
+|\ \ \ \ \  
+| * | | | | 24ad990 -- Added new user_cachedir configuration option
+| * | | | | f2294e5 -- Removed residues
+| * | | | | 61a41c4 -- de.ruedigermoeller removed due to dependency issues
+| * | | | | a0d3021 -- netbeans.version increased from RELEASE113 to RELEASE123
+| * | | | | 4d27753 -- org.codehause.mojo replaced with org.apache.netbeans.utilities for nbm-maven-plugin, enabling as to compile with Java11 (we used Java8 so far)
+| * | | | | 8239caa -- MeshPoint cleaned up
+| * | | | | 4cfde95 -- Vertex3d replaced with Point3d
+|/ / / / /  
+| | * | | bd05afe -- Adjusted pre registration and registration test
+| | * | | e1fe968 -- Created after registration customization panel and top component for testing
+| | * | | e2383d2 -- Created registration panel with initial functionality
+| |/ / /  
+|/| | |   
+* | | |   bcb5597 -- Merge branch '84-implement-faster-de-serialization' into 'master'
+|\ \ \ \  
+| * | | | a3d6266 -- Super-fast (de)serialization using the FST library
+| * | | | 848450c -- Buffered read/write
+|/ / / /  
+* | | |   524d2ad -- Merge branch '82-try-opencl-ray-casting' into 'master'
+|\ \ \ \  
+| * | | | 44605c3 -- Concurrent HumanFaceCache
+| * | | | 6d97421 -- Added HumanFaceCache implementations
+| * | | | 37f1bd3 -- Added serialization
+|/ / / /  
+* | | |   97a084d -- Merge branch '37-extend-existing-meshmodel-with-feature-points' into 'master'
+|\ \ \ \  
+| * | | | 2f29bd4 -- Feature points definition
+|/ / / /  
+* | | |   8c73572 -- Merge branch '66-3d-heatmap-visualization' into 'master'
+|\ \ \ \  
+| |/ / /  
+|/| | |   
+| * | | ae0c974 -- removed merge residues
+| * | |   b3fd405 -- Resolved conflicts
+| |\ \ \  
+| |/ / /  
+|/| | |   
+* | | |   e14874d -- Merge branch '76-fix-install-error' into 'master'
+|\ \ \ \  
+| * | | | c46b999 -- Install class moved back to the gui package
+|/ / / /  
+* | | |   2994494 -- Merge branch '75-fix-javadoc-for-gui-module' into 'master'
+|\ \ \ \  
+| * | | | c213b9a -- Fixed javadoc
+|/ / / /  
+* | | |   bc2b2d9 -- Merge branch '74-refactor-gui' into 'master'
+|\ \ \ \  
+| * | | | 27e23eb -- Module structure refactoring
+| * | | | 8900ced -- Introduced RotationAnimator
+| * | | | 779b0b1 -- Fixes
+| * | | | b22caa2 -- Added path preferences to the ProjectTopComponent
+| * | | | 9c771e9 -- CanvasTC is non-singleton
+| * | | | dd42ca2 -- CanvasPanel renamed to Canvas
+| * | | | d37a57e -- Refactored major classes
+| * | | | 5a5a917 -- Introduced Drawable and SceneRenderer
+| * | | | d4b1c5f -- Added Camera implementation
+|/ / / /  
+* | | |   acb4a8e -- Merge branch '1-faces-state-and-pre-selection' into 'master'
+|\ \ \ \  
+| * | | | d72e613 -- added method for removing primary face
+| * | | | 5b97e63 -- updated javadocs, added "remove primary face" method
+| * | | | dc9ad15 -- added absolute layout
+| * | | | 5e6e812 -- added methods for loading primary face from file
+| * | | | 477e282 -- fixed javadocs, added checks whether method inputs are valid or not
+| * | | | 3af86a1 -- added javadocs
+| * | | | 1747c13 -- Basic refactoring and decumention
+| * | | | 545781d -- changed openAtStart to false
+| * | | | 6b12ce2 -- added project attribute
+| * | | | ac73b66 -- added cz.fidentis.analyst to list of public packages
+| * | | | ea01d35 -- removed primary face from constructor
+| * | | |   3c8072f -- Merge branch 'master' into 1-faces-state-and-pre-selection
+| |\ \ \ \  
+| |/ / / /  
+|/| | | |   
+* | | | |   37f0406 -- Merge branch '61-visualize-the-superimposition-registration-of-triangle-meshes' into 'master'
+|\ \ \ \ \  
+| * | | | | 117082b -- Set parameter for ICP that do not deform the face
+| * | | | | 2f1a88e -- Added ICP transformation for testing
+| * | | | |   e72f8fa -- Merge branch 'master' of gitlab.fi.muni.cz:grp-fidentis/analyst2 into 61-visualize-the-superimposition-registration-of-triangle-meshes
+| |\ \ \ \ \  
+| |/ / / / /  
+|/| | | | |   
+| * | | | |   6b0b7a1 -- Merge origin/61-visualize-the-superimposition-registration-of-triangle-meshes into 61-visualize-the-superimposition-registration-of-triangle-meshes
+| |\ \ \ \ \  
+| | * | | | | 0233d7c -- Revert "Added comparison listener for rendering face with color mapped to HS distances"
+| | * | | | | 6a9b9a3 -- Revert "Added temporary simple interface to check face with heatmap"
+| | * | | | | b03909a -- Added temporary simple interface to check face with heatmap
+| | * | | | | d22bc99 -- Added comparison listener for rendering face with color mapped to HS distances
+| * | | | | | e63279a -- Added GLListener for registration, also basic functionality
+| |/ / / / /  
+| * | | | | 2ee24c9 -- Added top component for two faces registration
+| | * | | | d812831 -- added 1:1 button
+| | * | | |   72e0ca7 -- Merge branch 'master' into 1-faces-state-and-pre-selection
+| | |\ \ \ \  
+| |_|/ / / /  
+|/| | | | |   
+* | | | | |   a16eaeb -- Merge branch '36-implement-the-icp-algorithm2' into 'master'
+|\ \ \ \ \ \  
+| * | | | | | 52dfd0d -- Fixed pom.xml - depenedcy of GUI on icp
+| * | | | | | bde7bdd -- Testing
+| * | | | | |   d478bcb -- Merge branch 'master' of gitlab.fi.muni.cz:grp-fidentis/analyst2 into 36-implement-the-icp-algorithm2
+| |\ \ \ \ \ \  
+| |/ / / / / /  
+|/| | | | | |   
+* | | | | | |   30caede -- Merge branch '72-remove-duplicate-vertices-during-the-loading-of-obj-models' into 'master'
+|\ \ \ \ \ \ \  
+| |_|_|_|_|_|/  
+|/| | | | | |   
+| * | | | | | 21613c7 -- Automatically removes duplicite vertices when loading new HumanFace
+|/ / / / / /  
+* | | | | |   63c2cb4 -- Merge branch '70-fix-mean-curvature' into 'master'
+|\ \ \ \ \ \  
+| |_|_|_|_|/  
+|/| | | | |   
+| * | | | | 8151453 -- Tuned heatmap parameters
+| * | | | | 8c53201 -- Parallel computation of curvature
+| * | | | | aa5745b -- Fixed curvature computation
+| * | | | | 8cdbcc8 -- MeshTriangle simplified
+| * | | | | 8228ded -- Fixed curvature calculations
+|/ / / / /  
+| * | | | 709115a -- #36 - method getTransformedFacet
+| * | | | 3215c38 -- Minor refactoring
+| * | | | bf9c480 -- #36 - ready for merge request
+| * | | | 4567bba -- #36 - changed HausdorffDistance visitor
+| * | | | 414ca7c -- #36 - compute rotation parameter
+| * | | | 41ccf55 -- #36 compute transformation parameters
+| | | * | 72d35d5 -- removed primary face panel
+| | | * | d4c89e4 -- added layouts
+| | | * | f05b095 -- removed Dashboard
+| | | * | 328b47d -- created DashboardTopComponent
+| | | * |   b54cae1 -- Merge branch 'master' into 1-faces-state-and-pre-selection
+| | | |\ \  
+| |_|_|/ /  
+|/| | | |   
+* | | | |   ddc66d6 -- Merge branch '71-fix-mesh-topology' into 'master'
+|\ \ \ \ \  
+| * | | | | 5dd4daa -- Introduced TriangleFan class
+| * | | | | c128f6a -- Fixed documentation
+| * | | | | 112642d -- Fixed bug with wrong pointers to apposite corners
+|/ / / / /  
+* | | | |   e72fca2 -- Merge branch '67-fix-gaussian-curvature' into 'master'
+|\ \ \ \ \  
+| * | | | | 2c29f7b -- Final refactoring of testing app
+| * | | | | 2329f9d -- Testing classes moved to GUI
+| * | | | | 48c0f5c -- Documentation
+| * | | | | 9571ef6 -- Added detection of border vertices to the curvature computation
+| * | | | | ae3af2b -- Curvature algorithms merged to a single class
+| * | | | | 0c9a9e8 -- Introduced DeltaCurvature
+| * | | | | 54c850a -- Curvature algorithms re-implemented
+|/ / / / /  
+| | | * | efb68b9 -- removed class Project from GUI
+| | | * |   599db8c -- Merge branch 'master' into 1-faces-state-and-pre-selection
+| | | |\ \  
+| | | |/ /  
+| | |/| |   
+| | | * | 83bee97 -- added buttons text
+| | | * | 7c1b6af -- added simple functions for secondaryFaces modifying
+| | | * | e70bde9 -- added Project import
+| | | * | 5d4fdeb -- created Project class, added primaryFace and secondaryFaces attributes
+| | | * | 57ee47d -- renamed class, removed attributes
+| | | * | e7a0f03 -- removed secondaryFaces list
+| | | * | 7e5e584 -- added panels and buttons
+| | | * | 3a53569 -- created Project panel with primary and secondary faces
+| | | * | 76fd666 -- deleted class project (it was created as jpanel, not jframe)
+| | | * | 2a958c6 -- added primaryFace and secondaryFaces attributes (+get, set)
+| | | * | 3fd9d04 -- created Project class
+| | | | * 5d6b25e -- Added temporary simple interface to check face with heatmap
+| | | | * 83a5a1e -- Added comparison listener for rendering face with color mapped to HS distances
+| |_|_|/  
+|/| | |   
+* | | | c59d91e -- Manual release
+* | | |   f51bff3 -- Merge branch '65-fix-ci-pipeline' into 'master'
+|\ \ \ \  
+| |/ / /  
+|/| | |   
+| * | | a401dc2 -- Update .gitlab-ci.yml
+| * | | 96230fe -- Update .gitlab-ci.yml
+| * | | 208e7d8 -- Update .gitlab-ci.yml
+|/ / /  
+* | |   fe882c5 -- Merge branch '64-fix-javadoc' into 'master'
+|\ \ \  
+| * | | ff1f417 -- Fixed links in Javadoc
+|/ / /  
+* | | c474e34 -- CHANGELOG.md file updated with commits between the current and previous tag.
+* | | 513fe51 -- Update pom.xml version.
+* | | 4003fd4 -- Use Gaussian curvature for symmetry plane by default
+* | |   14adb31 -- Merge branch 'issue12' into 'master'
 |\ \ \  
 | |/ /  
-| * | beb3e08 -- BoundigBox refactored
-| * | 6eadb27 -- Renamed visitors
-| * | 001e0e0 -- ClosestNodeVisitor removed completely
-| * | d7eb6b0 -- Removed ClosetNodeAbstractVisitor
-| * | 9557c2d -- closetNode() moved from abstract class to the ClosestNodeVisitor
-| * | c828f62 -- testing
-| * |   cd1da55 -- Merge remote-tracking branch 'origin/master' into 53-improve-closestnodemultiplevisitor
+|/| |   
+| * | fc88197 -- Final styling before merge
+| * | 7550d1e -- symmetry plane is being displayed amd calculated when requested
+| * | 1dcc5d5 -- symmetry plane GUI buttons
+|/ /  
+* |   35bd24e -- Merge branch '63-fix-significantpoints' into 'master'
+|\ \  
+| * | 139379a -- Added test files, for sure
+| * | 7465c8b -- Typos
+| * | 03b964a -- Removed obsolete local method
+|/ /  
+* |   7ca60fa -- Merge branch '62-refactor-symmetryestimator-as-visitor' into 'master'
+|\ \  
+| * | 74086ba -- Final refactoring
+| * | 086b5d3 -- Documentation
+| * | 2dd4888 -- SignificantPoints is visitor now
+| * | 1991af7 -- SymmetryEstimator is visitor now
+| * | 6472f36 -- Adaptation to multiple mesh facets
+| * | cc26da1 -- image:latest changed to image:3-jdk-11
+|/ /  
+* |   737a43b -- Merge branch '60-remove-concurrency-from-visitors' into 'master'
+|\ \  
+| * | bd8233f -- Style check
+| * | 725fc32 -- Removed the concurrency paramater from visitors
+|/ /  
+* |   4e682e3 -- Merge branch '54-adapt-hausdorffdistance-for-icp' into 'master'
+|\ \  
+| * | f365493 -- Fixed errors
+| * |   42849fa -- Merge branch 'master' into 54-adapt-hausdorffdistance-for-icp
 | |\ \  
 | |/ /  
 |/| |   
-| * | 33317b2 -- KdTreeDistanceToVertices repeated distance computation eliminated
-| * | d5603c0 -- KdTree commented code removed
-| * | 62c8817 -- ClosestNodeMultipleVisitor repeated tree traversal reduced
+* | |   0774ac0 -- Merge branch '53-improve-closestnodemultiplevisitor' into 'master'
+|\ \ \  
+| * | | 85cee61 -- Improved KdTreeDistance
+* | | |   4e4f529 -- Merge branch '53-improve-closestnodemultiplevisitor' into 'master'
+|\ \ \ \  
+| |/ / /  
+| * | | beb3e08 -- BoundigBox refactored
+| * | | 6eadb27 -- Renamed visitors
+| * | | 001e0e0 -- ClosestNodeVisitor removed completely
+| * | | d7eb6b0 -- Removed ClosetNodeAbstractVisitor
+| * | | 9557c2d -- closetNode() moved from abstract class to the ClosestNodeVisitor
+| * | | c828f62 -- testing
+| * | |   cd1da55 -- Merge remote-tracking branch 'origin/master' into 53-improve-closestnodemultiplevisitor
+| |\ \ \  
+| |/ / /  
+|/| | |   
+| * | | 33317b2 -- KdTreeDistanceToVertices repeated distance computation eliminated
+| * | | d5603c0 -- KdTree commented code removed
+| * | | 62c8817 -- ClosestNodeMultipleVisitor repeated tree traversal reduced
+| | |/  
+| |/|   
 | | * 36e8e48 -- #54 - add comment
 | | * c9093f7 -- #54 - set nearest points
 | |/  
diff --git a/Comparison/pom.xml b/Comparison/pom.xml
index 74916c116d25adf3714e0ce5b1c231d10aab4399..68f77d8c81ab972facb8acffbe9f83d8e4e4448e 100644
--- a/Comparison/pom.xml
+++ b/Comparison/pom.xml
@@ -4,7 +4,7 @@
     <parent>
         <groupId>cz.fidentis</groupId>
         <artifactId>FIDENTIS-Analyst-parent</artifactId>
-        <version>2.1.4</version>
+        <version>2021.10</version>
     </parent>
     <artifactId>Comparison</artifactId>
     <packaging>nbm</packaging>
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/BatchProcessor.java b/Comparison/src/main/java/cz/fidentis/analyst/BatchProcessor.java
new file mode 100644
index 0000000000000000000000000000000000000000..1adce12f5c10f12798eddbb13e3809b29a6e5299
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/BatchProcessor.java
@@ -0,0 +1,164 @@
+package cz.fidentis.analyst;
+
+import cz.fidentis.analyst.face.AvgFaceConstructor;
+import cz.fidentis.analyst.face.HumanFace;
+import cz.fidentis.analyst.face.HumanFaceFactory;
+import cz.fidentis.analyst.icp.IcpTransformer;
+import cz.fidentis.analyst.icp.UndersamplingStrategy;
+import cz.fidentis.analyst.kdtree.KdTree;
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.symmetry.SymmetryConfig;
+import cz.fidentis.analyst.symmetry.SymmetryEstimator;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Helper class providing methods for batch N:N processing.
+ * 
+ * @author Radek Oslejsek
+ */
+public class BatchProcessor {
+    
+    /**
+     * Template face computed by averaging vertices processed faces.
+     */
+    private HumanFace templateFace = null;
+    
+    private double avgIcpIterations = 0.0;
+    
+    private SymmetryConfig symmetryConfig;
+    
+    /**
+     * Constructor.
+     * @param symmetryPoints Number of symmetry points used by the symmetry estimator
+     */
+    public BatchProcessor(int symmetryPoints) {
+        symmetryConfig = new SymmetryConfig();
+        this.symmetryConfig.setSignificantPointCount(symmetryPoints); // default 200, best 500
+    }
+
+    /**
+     * Pre-reads faces from given directory into the HumanFactory.
+     * @param dir Directory.
+     * @return Face IDs
+     */
+    public List<String> readFaces(String dir) {
+        List<String> faces = new ArrayList<>();
+        for (File subdir : (new File(dir)).listFiles(File::isDirectory)) {
+            if (subdir.getName().matches("^\\d\\d$")) {
+                for (File file: subdir.listFiles(File::isFile)) {
+                    if (file.getName().endsWith(".obj")) {
+                        //System.out.print(file.getName() + " ");
+                        //if (file.getName().endsWith("00002_01_ECA.obj")) { // FOT DEBUGING
+                            String faceId = HumanFaceFactory.instance().loadFace(file);
+                            faces.add(faceId);
+                        //}
+                    }
+                }
+            }
+        }
+        return faces;
+    }
+    
+    /**
+     * Pre-computes symmetry planes for given faces.
+     * @param faceIDs Face IDs
+     */
+    public void computeSymmetryPlanes(List<String> faceIDs) {
+        for (String facePath: faceIDs) {
+            String faceId = HumanFaceFactory.instance().loadFace(new File(facePath));
+            HumanFace face = HumanFaceFactory.instance().getFace(faceId);
+            SymmetryEstimator se = new SymmetryEstimator(this.symmetryConfig);
+            face.getMeshModel().compute(se);
+            face.setSymmetryPlane(se.getSymmetryPlane(), se.getSymmetryPlaneMesh());
+        }
+    }
+    
+    /**
+     * Registers faces with respect to the given primary face.
+     * 
+     * @param primaryFaceId ID of the primary face
+     * @param faceIDs IDs of faces that are to be superimposed (registered)
+     * @param iters Maximal number of ICP iterations
+     * @param error Maximal error of ICP computation
+     * @param strategy Undersampling strategy
+     */
+    public void superimposeOnPrimaryFace(
+            String primaryFaceId, List<String> faceIDs, int iters, double error, UndersamplingStrategy strategy) {
+        
+        if (faceIDs == null) {
+            throw new IllegalArgumentException("faces");
+        }
+        
+        HumanFaceFactory.instance().setStrategy(HumanFaceFactory.Strategy.MRU);
+        
+        int facesCounter = faceIDs.size();
+        HumanFace primaryFace = HumanFaceFactory.instance().getFace(primaryFaceId);
+        KdTree primKdTree = primaryFace.computeKdTree(true);
+        IcpTransformer icpTransformer = new IcpTransformer(primKdTree, iters, false, error, strategy);
+            
+        for (String faceId: faceIDs) {
+            //String faceId = HumanFaceFactory.instance().getFace(new File(facePath));
+            if (primaryFace.getId().equals(faceId)) { // skip the same face
+                facesCounter--;
+                continue;
+            }
+            
+            HumanFace face = HumanFaceFactory.instance().getFace(faceId);
+            face.getMeshModel().compute(icpTransformer);
+            face.removeKdTree();
+        }
+        
+        int itersCounter = 0;
+        for (MeshFacet f: icpTransformer.getTransformations().keySet()) {
+            itersCounter += icpTransformer.getTransformations().get(f).size();
+        }
+        this.avgIcpIterations = itersCounter / (double) facesCounter;
+    }
+    
+    /**
+     * Computes averaged face. It is supposed that faces used for the computation
+     * are already superimposed (registered) with the template face.
+     * 
+     * @param initTempFaceId ID of the face used as an initial template for the computation of the averaged face
+     * @param faceIDs IDs of faces that are used to compute averaged face
+     */
+    public void computeTemplateFace(String initTempFaceId, List<String> faceIDs) {
+        if (faceIDs == null) {
+            throw new IllegalArgumentException("faces");
+        }
+        
+        this.templateFace = HumanFaceFactory.instance().getFace(initTempFaceId);
+        
+        HumanFaceFactory.instance().setStrategy(HumanFaceFactory.Strategy.MRU);
+        AvgFaceConstructor constructor = new AvgFaceConstructor(this.templateFace.getMeshModel());
+        for (String faceId: faceIDs) {
+            //String faceId = HumanFaceFactory.instance().loadFace(new File(facePath));
+            if (!this.templateFace.getId().equals(faceId)) { // skip the same face
+                HumanFace face = HumanFaceFactory.instance().getFace(faceId);
+                face.computeKdTree(false).accept(constructor);
+            }
+        }
+        
+        this.templateFace.setMeshModel(constructor.getAveragedMeshModel());
+    }
+    
+    /**
+     * Returns template face that can be used for linear time N:N distance computation.
+     * 
+     * @return template face.
+     */
+    public HumanFace getAvgTemplateFace() {
+        return templateFace;
+    }
+    
+    /**
+     * Returns average number of ICP iterations per inspected face.
+     * @return average number of ICP iterations per inspected face.
+     */
+    public double getAvgNumIcpIterations() {
+        return this.avgIcpIterations;
+    }
+    
+}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/Project.java b/Comparison/src/main/java/cz/fidentis/analyst/Project.java
index adf7532b64c5f8309141cacbd2c38dc266b9a529..03de5491dc95bb73c6b97b54b99b21bc991e5747 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/Project.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/Project.java
@@ -13,14 +13,15 @@ import java.util.List;
  */
 public class Project {
     
-    private HumanFace primaryFace;
-    private List<HumanFace> secondaryFaces = new ArrayList<>();
+    //private HumanFace primaryFace;
+    private List<HumanFace> faces = new ArrayList<>();
+    
     
     /**
      * Returns primary face
      * 
      * @return HumanFace primary face 
-     */
+     
     public HumanFace getPrimaryFace() {
         return primaryFace;
     }
@@ -30,7 +31,7 @@ public class Project {
      * 
      * @param primaryFace which will be new primary face
      * @throws IllegalArgumentException when argument primaryFace is null
-     */
+     
     public void setPrimaryFace(HumanFace primaryFace) {
         if (primaryFace == null) {
             throw new IllegalArgumentException("Primary face is null");
@@ -40,18 +41,19 @@ public class Project {
     
     /**
      * Removes primary face and sets primaryFace attribute to null
-     */
+     
     public void removePrimaryFace() {
         this.primaryFace = null;
-    }
+    }*/
+
 
     /**
      * Returns list of HumanFace secondary faces
      * 
      * @return list of secondary faces
      */
-    public List<HumanFace> getSecondaryFaces() {
-        return Collections.unmodifiableList(secondaryFaces);
+    public List<HumanFace> getFaces() {
+        return Collections.unmodifiableList(faces);
     }
 
     /**
@@ -61,60 +63,74 @@ public class Project {
      * secondary faces
      * @throws IllegalArgumentException if one of faces from argument is null
      */
-    public void setSecondaryFaces(List<HumanFace> secondaryFaces) {
-        this.secondaryFaces.clear();
+    public void setFaces(List<HumanFace> secondaryFaces) {
+        this.faces.clear();
         for (int i = 0; i < secondaryFaces.size(); i++) {
             if (secondaryFaces.get(i) == null) {
                 throw new IllegalArgumentException("One of faces is null");
             }
         }
-        this.secondaryFaces.addAll(secondaryFaces);
+        this.faces.addAll(secondaryFaces);
     }
     
     /**
-     * Adds new face to secondaryFaces
+     * Adds new face to faces
      * 
      * @param face HumanFace which will be added to list of secondary faces
      * @throws IllegalArgumentException when argument face is null
      */
-    public void addSecondaryFace(HumanFace face) {
+    public void addFace(HumanFace face) {
         if (face == null) {
             throw new IllegalArgumentException("Face is null");
         }
-        this.secondaryFaces.add(face);
+        this.faces.add(face);
     }
     
     /**
-     * Removes HumanFace from secondaryFaces
+     * Removes HumanFace from faces
      * 
-     * @param face HumanFace which will be removed from secondaryFaces
+     * @param face HumanFace which will be removed from faces
      * @throws IllegalArgumentException when argument face is null
      */
-    public void removeSecondaryFace(HumanFace face) {
+    public void removeFace(HumanFace face) {
         if (face == null) {
             throw new IllegalArgumentException("Face is null");
         }
         
-        for (int i = 0; i < secondaryFaces.size(); i++) {
-            if (secondaryFaces.get(i).equals(face)) {
-                secondaryFaces.remove(i);
+        for (int i = 0; i < faces.size(); i++) {
+            if (faces.get(i).equals(face)) {
+                faces.remove(i);
             }
         } 
     }
     
     /**
      * Removes faces which are sent to this function by list of HumanFace
-     * from secondaryFaces
+     * from faces
      * 
      * @param faces List of HumanFace faces which should be removed from
-     * secondaryFaces
+     * faces
      */
     public void removeSelected(List<HumanFace> faces) {
         for (int i = 0; i < faces.size(); i++) {
-            this.removeSecondaryFace(faces.get(i));
+            this.removeFace(faces.get(i));
+        }
+    }
+    
+    
+    /**
+     * 
+     * @param name String name of the model (face)
+     * @return face from this project faces, if not in project than returns 
+     * null
+     */
+    public HumanFace getFaceByName(String name) {
+        for (HumanFace face : faces) {
+            if (face.getShortName().equals(name)) {
+                return face;
+            }
         }
+        return null;
     }
     
-    /* TODO implement comparable and create comparators for filtering
-    secondaryFaces */
 }
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/face/AvgFaceConstructor.java b/Comparison/src/main/java/cz/fidentis/analyst/face/AvgFaceConstructor.java
new file mode 100644
index 0000000000000000000000000000000000000000..e7fe7d0a25c2f9a5a8ad6d20c765375f34d9bf46
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/face/AvgFaceConstructor.java
@@ -0,0 +1,120 @@
+package cz.fidentis.analyst.face;
+
+import cz.fidentis.analyst.kdtree.KdTree;
+import cz.fidentis.analyst.kdtree.KdTreeVisitor;
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
+import cz.fidentis.analyst.mesh.core.MeshModel;
+import cz.fidentis.analyst.visitors.kdtree.KdTreeClosestNode;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.vecmath.Point3d;
+import javax.vecmath.Vector3d;
+
+/**
+ * Visitor capable to create an average face by deforming given face template
+ * so that its vertices are in the "average position" with respect to the visited faces.
+ * The average position is computed as the centroid of mass of the closest points
+ * from inspected faces.
+ * <strong>It is supposed that the inspected faces are already registered 
+ * (superimposed with the template face and with each other).</strong>
+ * 
+ * @author Radek Oslejsek
+ */
+public class AvgFaceConstructor extends KdTreeVisitor {
+    
+    private MeshModel avgMeshModel = null;
+    
+    private int numInspectedFacets = 0;
+    
+    private final Map<MeshFacet, List<Vector3d>> transformations = new HashMap<>();
+    
+    /**
+     * Constructor.
+     * 
+     * @param templateFacet Mesh facet which is transformed to the averaged mesh
+     * @throws IllegalArgumentException if some parameter is wrong
+     */
+    public AvgFaceConstructor(MeshFacet templateFacet) {
+        this(new HashSet<>(Collections.singleton(templateFacet)));
+        if (templateFacet == null) {
+            throw new IllegalArgumentException("templateFacet");
+        }
+    }
+    
+    /**
+     * Constructor.
+     * 
+     * @param templateFacets Mesh facets that are transformed to the averaged mesh
+     * @throws IllegalArgumentException if some parameter is wrong
+     */
+    public AvgFaceConstructor(Set<MeshFacet> templateFacets) {
+        if (templateFacets == null || templateFacets.isEmpty()) {
+            throw new IllegalArgumentException("templateFacets");
+        }
+        
+        // fill vertTarns with empty list for each facet
+        templateFacets.parallelStream().forEach(
+                f -> this.transformations.put(f, new ArrayList<>(f.getVertices().size()))
+        );
+    }
+    
+    /**
+     * Constructor.
+     * 
+     * @param templateModel Mesh model which is transformed to the averaged mesh
+     * @throws IllegalArgumentException if some parameter is wrong
+     */
+    public AvgFaceConstructor(MeshModel templateModel) {
+        this(new HashSet<>(templateModel.getFacets()));
+    }
+    
+    @Override
+    public void visitKdTree(KdTree kdTree) {
+        avgMeshModel = null;
+        numInspectedFacets++;
+
+        for (MeshFacet myFacet: transformations.keySet()) {
+            for (int i = 0; i < myFacet.getNumberOfVertices(); i++) {
+                Point3d myPoint = myFacet.getVertex(i).getPosition();
+                KdTreeClosestNode visitor = new KdTreeClosestNode(myPoint);
+                kdTree.accept(visitor);
+                
+                // update result:
+                Vector3d moveDir = new Vector3d(visitor.getAnyClosestNode().getLocation());
+                moveDir.sub(visitor.getReferencePoint());
+                if (transformations.get(myFacet).size() < myFacet.getNumTriangles()) { // First inspected facet
+                    transformations.get(myFacet).add(moveDir);
+                } else {
+                    transformations.get(myFacet).get(i).add(moveDir);
+                }
+            }
+        }
+    }
+    
+    /**
+     * Computes and returns the averaged human face.
+     * @return averaged human face
+     */
+    public MeshModel getAveragedMeshModel() {
+        if (avgMeshModel == null) {
+            avgMeshModel = new MeshModel();
+            for (MeshFacet f: transformations.keySet()) { // clone all facets of the template face
+                MeshFacet newFacet = new MeshFacetImpl(f);
+                for (int i = 0; i < newFacet.getNumberOfVertices(); i++ ) { // move all vertices
+                    Vector3d tr = new Vector3d(transformations.get(f).get(i));
+                    tr.scale(1.0/numInspectedFacets);
+                    newFacet.getVertex(i).getPosition().add(tr);
+                }
+                avgMeshModel.addFacet(newFacet);
+            }
+        }
+        return avgMeshModel;
+    }
+    
+}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java
index a0f5d232d0ff01875fc530caf9829a0576b63d65..e30af5c6a5f36e108a803273501ebd48972dab74 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java
@@ -1,12 +1,16 @@
 package cz.fidentis.analyst.face;
 
 import com.google.common.eventbus.EventBus;
+import cz.fidentis.analyst.feature.FeaturePoint;
+import cz.fidentis.analyst.feature.services.FeaturePointImportService;
+import cz.fidentis.analyst.kdtree.KdTree;
 import cz.fidentis.analyst.mesh.core.MeshFacet;
 import cz.fidentis.analyst.mesh.core.MeshModel;
 import cz.fidentis.analyst.mesh.events.MeshEvent;
 import cz.fidentis.analyst.mesh.events.MeshListener;
 import cz.fidentis.analyst.mesh.io.MeshObjLoader;
 import cz.fidentis.analyst.symmetry.Plane;
+import cz.fidentis.analyst.visitors.face.HumanFaceVisitor;
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 
@@ -17,6 +21,9 @@ import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+import java.util.ArrayList;
 import java.util.Objects;
 //import org.nustaq.serialization.FSTConfiguration;
 //import org.nustaq.serialization.FSTObjectInput;
@@ -45,12 +52,18 @@ import java.util.Objects;
  */
 public class HumanFace implements MeshListener, Serializable {
     
-    private final MeshModel meshModel;
+    private MeshModel meshModel;
+    
+    private KdTree kdTree;
 
     private Plane symmetryPlane;
+    
+    private MeshFacet symmetryPlaneMesh;
 
     private MeshFacet cuttingPlane;
     
+    private List<FeaturePoint> featurePoints;
+    
     private final transient EventBus eventBus = new EventBus();
     
     private final String id;
@@ -82,6 +95,18 @@ public class HumanFace implements MeshListener, Serializable {
     public MeshModel getMeshModel() {
         return meshModel;
     }
+    
+    /**
+     * 
+     * @param meshModel new mesh model
+     * @throws IllegalArgumentException if new model is missing
+     */
+    public void setMeshModel(MeshModel meshModel) {
+        if (meshModel == null ) {
+            throw new IllegalArgumentException("meshModel");
+        }
+        this.meshModel = meshModel;
+    }
 
     /**
      * Registers listeners (objects concerned in the human face changes) to receive events.
@@ -116,9 +141,11 @@ public class HumanFace implements MeshListener, Serializable {
     /**
      *
      * @param plane The new symmetry plane
+     * @param planeFacet The symmetry plane mesh
      */
-    public void setSymmetryPlane(Plane plane) {
-        symmetryPlane = plane;
+    public void setSymmetryPlane(Plane plane, MeshFacet planeFacet) {
+        this.symmetryPlane = plane;
+        this.symmetryPlaneMesh = planeFacet;
     }
 
     /**
@@ -128,6 +155,10 @@ public class HumanFace implements MeshListener, Serializable {
     public Plane getSymmetryPlane() {
         return symmetryPlane;
     }
+    
+    public MeshFacet getSymmetryPlaneFacet() {
+        return this.symmetryPlaneMesh;
+    }
 
     /**
      *
@@ -146,13 +177,95 @@ public class HumanFace implements MeshListener, Serializable {
     }
     
     /**
-     * Return unique ID of the face.
+     * 
+     * @param points List of feature points
+     */
+    public void setFeaturePoints(List<FeaturePoint> points) {
+        featurePoints = points;
+    }
+    
+    /**
+     * Reads feature points from a file on the given path.
+     * 
+     * @param path Directory where the file is located
+     * @param fileName Name of the file
+     * @throws IOException on I/O failure
+     */
+    public void loadFeaturePoints(String path, String fileName) throws IOException {
+        featurePoints = FeaturePointImportService.importFeaturePoints(path, fileName);
+    }
+    
+    /**
+     * 
+     * @return The face's feature points.
+     */
+    public List<FeaturePoint> getFeaturePoints() {
+        if (featurePoints == null) {
+            return Collections.emptyList();
+        }
+        return Collections.unmodifiableList(featurePoints);
+    }
+    
+    /**
+     * Returns unique ID of the face.
      * 
      * @return unique ID of the face. 
      */
     public String getId() {
         return this.id;
     }
+    
+    /**
+     * Returns short name of the face distilled from the file name. May not be unique.
+     * @return short name of the face distilled from the file name
+     */
+    public String getName() {
+        String name = id.substring(0, id.lastIndexOf('.')); // remove extention
+        name = name.substring(id.lastIndexOf('/')+1, name.length());
+        return name;
+    }
+    
+    /**
+     * Returns short name of the face without its path in the name.
+     * @return short name of the face without its path in the name
+     */
+    public String getShortName() {
+        String name = this.getName();
+        name = name.substring(name.lastIndexOf(File.separatorChar) + 1, name.length());
+        return name;
+    }
+    
+    /**
+     * Returns already computed k-d tree of the triangular mesh or {@code null}.
+     * @return Already computed k-d tree of the triangular mesh or {@code null}
+     */
+    public KdTree getKdTree() {
+        return this.kdTree;
+    }
+    
+    /**
+     * Computes new k-d tree or returns the existing one.
+     * 
+     * @param recompute If {@code true} and an old k-d tree exists, then it is recomputed again. 
+     * Otherwise, the tree is computed only if does not exist yet.
+     * @return K-d tree with the triangular mesh.
+     */
+    public KdTree computeKdTree(boolean recompute) {
+        if (kdTree == null || recompute) {
+            kdTree = new KdTree(new ArrayList<>(meshModel.getFacets()));
+        }
+        return kdTree;
+    }
+    
+    /**
+     * Removes k-d tree from the Human face. 
+     * @return removed k-d tree or {@code null}
+     */
+    public KdTree removeKdTree() {
+        KdTree ret = this.kdTree;
+        this.kdTree = null;
+        return ret;
+    }
 
     /**
      * Creates serialized dump of the human face. Event buses are not stored.
@@ -201,6 +314,15 @@ public class HumanFace implements MeshListener, Serializable {
         }
         */
     }
+    
+    /**
+     * Visits this face.
+     * 
+     * @param visitor Visitor
+     */
+    public void accept(HumanFaceVisitor visitor) {
+        visitor.visitHumanFace(this);
+    }
 
     @Override
     public int hashCode() {
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFaceCache.java b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFaceCache.java
deleted file mode 100644
index 6aadb085fe838f3eeef8e39884e2f733dc80a162..0000000000000000000000000000000000000000
--- a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFaceCache.java
+++ /dev/null
@@ -1,224 +0,0 @@
-package cz.fidentis.analyst.face;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Singleton flyweight factory that creates and caches human faces. Faces are
- * stored in the memory until there is enough space in the Java heap. Then they 
- * are cached on disk automatically. The dumping strategy is directed by sub-classes
- * of this abstract class.
- * <p>
- * Dumping faces on disk and their recovery is time consuming (we use serialization
- * of all data structure, i.e., triangular mesh, k-d tree, etc.). It can be faster
- * to re-load the face from OBJ file again and re-compute the data structures from scratch.
- * </p>
- * <p>
- * Currently, listeners registered to {@code HumanFace} and {@code KdTree} 
- * are neither dumped nor reconstructed!
- * </p>
- * 
- * @author Radek Oslejsek
- */
-public abstract class HumanFaceCache {
-    
-    /**
-     * Keep at least this portion of the Java heap memory free
-     */
-    public static final double MIN_FREE_MEMORY = 0.2; // 20%
-    
-    private final Map<String, HumanFace> inMemoryFaces = new HashMap<>();
-    private final Map<String, File> dumpedFaces = new HashMap<>();
-    
-    /**
-     * Private constructor. Use {@link instance} instead to get and access the instance.
-     */
-    protected HumanFaceCache() {
-    }
-    
-    /**
-     * Loads new face. If the face is already loaded, then the existing instance
-     * is returned. 
-     * 
-     * @param file OBJ file with human face.
-     * @return Human face or {@code null}
-     */
-    public HumanFace loadFace(File file) {
-        try {
-            String faceId = file.getCanonicalPath();
-            //String faceId = Long.toHexString(Double.doubleToLongBits(Math.random()));
-            
-            // In memory face:
-            HumanFace face = inMemoryFaces.get(faceId);
-            if (face != null) {
-                return face;
-            }
-            
-            // Dumped face:
-            face = recoverFace(faceId);
-            if (face != null) {
-                return face;
-            }
-            
-            // New face:
-            return storeNewFace(file);
-        } catch (IOException|ClassNotFoundException|InterruptedException|ExecutionException ex) {
-            Logger.getLogger(HumanFaceCache.class.getName()).log(Level.SEVERE, null, ex);
-            return null;
-        }
-    }
-    
-    /**
-     * Returns a human face. Recovers the face from a dump file if necessary.
-     * 
-     * @param faceId ID of the face
-     * @return Human face or {@code null}
-     */
-    public HumanFace getFace(String faceId) {
-        try {
-            // In memory face:
-            HumanFace face = inMemoryFaces.get(faceId);
-            if (face != null) {
-                return face;
-            }
-            
-            // Dumped face:
-            face = recoverFace(faceId);
-            if (face != null) {
-                return face;
-            }
-            
-            // New face:
-            return null;
-        } catch (IOException|ClassNotFoundException|InterruptedException|ExecutionException ex) {
-            Logger.getLogger(HumanFaceCache.class.getName()).log(Level.SEVERE, null, ex);
-            return null;
-        }
-    }
-    
-    /**
-     * Removed the face from the cache.
-     * 
-     * @param faceId Face ID
-     */
-    public void removeFace(String faceId) {
-        if (inMemoryFaces.remove(faceId) == null) {
-            dumpedFaces.remove(faceId);
-        }
-    }
-    
-    @Override
-    public String toString() {
-        StringBuilder ret = new StringBuilder();
-        ret.append(formatSize(Runtime.getRuntime().freeMemory())).
-                append(" free memory out of ").
-                append(formatSize(Runtime.getRuntime().maxMemory()));
-        ret.append(". In memory: ").
-                append(this.inMemoryFaces.size()).
-                append(", dumped: ").
-                append(this.dumpedFaces.size());
-        return ret.toString();
-    }
-    
-    /**
-     * Recovers the face from the dump file.Heap memory is released (some existing 
-     * face is dumped) if necessary. 
-     * 
-     * @param faceId Face ID
-     * @return Recovered face or {@code null} if the face was not dumped.
-     * @throws IOException on I/O error
-     * @throws ClassNotFoundException on I/O error
-     * @throws java.lang.InterruptedException
-     * @throws java.util.concurrent.ExecutionException
-     */
-    protected HumanFace recoverFace(String faceId) throws IOException, ClassNotFoundException, InterruptedException, ExecutionException {
-        File dumpFile = dumpedFaces.get(faceId);
-        if (dumpFile == null) {
-            return null;
-        }
-
-        // Free memory and recover human face from dump file silultanously:
-        ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
-        final Future<HumanFace> result = executor.submit(() -> HumanFace.restoreFromFile(dumpFile));
-        executor.submit(() -> freeMemory());
-        executor.shutdown();
-        while (!executor.isTerminated()){}
-        HumanFace face = result.get();
-        
-        inMemoryFaces.put(faceId, face);
-        dumpedFaces.remove(faceId);
-        return face;
-    }
-    
-    /**
-     * Instantiates new face.Heap memory is released (some existing face is dumped) if necessary. 
-     * 
-     * @param file OBJ file
-     * @return Face instance.
-     * @throws IOException on I/O error
-     * @throws java.lang.InterruptedException
-     * @throws java.util.concurrent.ExecutionException
-     */
-    protected HumanFace storeNewFace(File file) throws IOException, InterruptedException, ExecutionException {
-        // Free memory and load human face simultaneously:
-        ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
-        final Future<HumanFace> result = executor.submit(() -> new HumanFace(file));
-        executor.submit(() -> freeMemory());
-        executor.shutdown();
-        while (!executor.isTerminated()){}
-        HumanFace face = result.get();
-        inMemoryFaces.put(face.getId(), face);
-        return face;
-    }
-    
-    /**
-     * Checks and releases the heap, if necessary.
-     * 
-     * @return true if some existing face has been dumped to free the memory.
-     * @throws IOException on I/O error
-     */
-    protected boolean freeMemory() throws IOException {
-        double ratio = (double) Runtime.getRuntime().freeMemory() / Runtime.getRuntime().maxMemory();
-        if (ratio > MIN_FREE_MEMORY) {
-            return false;
-        }
-        String faceId = selectFaceForDump();
-        if (faceId != null) {
-            HumanFace face = inMemoryFaces.remove(faceId);
-            dumpedFaces.put(faceId, face.dumpToFile());
-            return true;
-        }
-        return false;
-    }
-    
-    /**
-     * Selects a face that will be dumped to file.
-     * 
-     * @return ID of the face that will be dumped to file.
-     */
-    protected abstract String selectFaceForDump();
-    
-    protected static String formatSize(long v) {
-        if (v < 1024) {
-            return v + " B";
-        }
-        int z = (63 - Long.numberOfLeadingZeros(v)) / 10;
-        return String.format("%.1f %sB", (double)v / (1L << (z*10)), " KMGTPE".charAt(z));
-    }
-    
-    protected Map<String, HumanFace> getInMemoryFaces() {
-        return this.inMemoryFaces;
-    }
-    
-    protected Map<String, File> getDumpedFaces() {
-        return this.dumpedFaces;
-    }
-}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFaceFactory.java b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFaceFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..2198510572f6393420ed3d8d8e7e0e9db56eb480
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFaceFactory.java
@@ -0,0 +1,284 @@
+package cz.fidentis.analyst.face;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Singleton flyweight factory that creates and caches human faces. Faces are
+ * stored in the memory until there is enough space in the Java heap. Then they 
+ * are cached on disk automatically. The dumping strategy can be switched in run-time.
+ * <p>
+ * Currently, listeners registered to {@code HumanFace} and {@code KdTree} 
+ * are neither dumped nor recovered!
+ * </p>
+ * 
+ * @author Radek Oslejsek
+ */
+public class HumanFaceFactory {
+    
+    /**
+     * Dumping strategies.
+     * @author Radek Oslejsek
+     */
+    public enum Strategy {
+        LRU, // least recently used faces are dumped first
+        MRU  // most recently used faces are dumped first
+    }
+    
+    /**
+     * Keep at least this portion of the Java heap memory free
+     */
+    public static final double MIN_FREE_MEMORY = 0.05; // 5%
+    
+    /**
+     * Human faces currently being stored on disk.
+     * <ul>
+     * <li>Key = Face ID<li>
+     * <li>Value = Dump file<li>
+     * </ul>
+     */
+    private final Map<String, File> dumpedFaces = new HashMap<>();
+    
+    /**
+     * Human faces currently being allocated in the memory.
+     * <ul>
+     * <li>Key = Last access time (milliseconds)<li>
+     * <li>Value = Human face<li>
+     * </ul>
+     */
+    private final SortedMap<Long, HumanFace> inMemoryFaces = new TreeMap<>();
+    
+    /**
+     * The usage "table"
+     * <ul>
+     * <li>Key = Face ID<li>
+     * <li>Value = Last access time (milliseconds)<li>
+     * </ul>
+     */
+    private final Map<String, Long> usage = new HashMap<>();
+    
+    /**
+     * The singleton instance
+     */
+    private static HumanFaceFactory factory;
+    
+    /**
+     * Dumping strategy.
+     */
+    private Strategy strategy = Strategy.LRU;
+    
+    
+    /**
+     * Private constructor. Use {@code instance()} method instead to get the instance.
+     */
+    protected HumanFaceFactory() {
+    }
+    
+    /**
+     * Returns the factory singleton instance.
+     * 
+     * @return the factory singleton instance
+     */
+    public static HumanFaceFactory instance() {
+        if (factory == null) {
+            factory = new HumanFaceFactory();
+        }
+        return factory;
+    }
+
+    /**
+     * Changes the dumping strategy
+     * @param strategy Dumping strategy. Must not be {@code null}
+     * @throws IllegalArgumentException if the strategy is missing
+     */
+    public void setStrategy(Strategy strategy) {
+        if (strategy == null) {
+            throw new IllegalArgumentException("strategy");
+        }
+        this.strategy = strategy;
+    }
+    
+    /**
+     * Returns current dumping strategy.
+     * @return current dumping strategy
+     */
+    public Strategy getStrategy() {
+        return this.strategy;
+    }
+    
+    /**
+     * Loads new face. If the face is already loaded, then the ID of existing instance
+     * is returned. To access the human face instance, use {@link getFace}.
+     * 
+     * @param file OBJ file with human face.
+     * @return ID of the human face or {@code null}
+     */
+    public String loadFace(File file) {
+        // Create face ID:
+        String faceId;
+        try {
+            faceId = file.getCanonicalPath();
+            //faceId = Long.toHexString(Double.doubleToLongBits(Math.random()));
+        } catch (IOException ex) {
+            Logger.getLogger(HumanFaceFactory.class.getName()).log(Level.SEVERE, null, ex);
+            return null;
+        }
+        
+        // Existing face
+        HumanFace face = getFace(faceId);
+        if (face != null) {
+            return faceId;
+        }
+        
+        // New face -- free the memory and load human face simultaneously:
+        try {
+            ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
+            final Future<HumanFace> result = executor.submit(() -> new HumanFace(file)); // read from file
+            executor.submit(() -> checkMemAndDump()); // free the memory, if necessary
+            executor.shutdown();
+            while (!executor.isTerminated()){}
+            face = result.get();
+        } catch (InterruptedException|ExecutionException ex) {
+            Logger.getLogger(HumanFaceFactory.class.getName()).log(Level.SEVERE, null, ex);
+            return null;
+        }
+        
+        // Update data structures:
+        long time = System.currentTimeMillis();
+        inMemoryFaces.put(time, face);
+        usage.put(faceId, time);
+        return faceId;
+    }
+    
+    /**
+     * Returns a human face. Recovers the face from the disk if necessary.
+     * 
+     * @param faceId ID of the face
+     * @return Human face or {@code null}
+     */
+    public HumanFace getFace(String faceId) {
+        if (updateAccessTime(faceId)) { // in memory face
+            return inMemoryFaces.get(usage.get(faceId));
+        }
+        
+        File dumpFile = dumpedFaces.get(faceId);
+        if (dumpFile == null) { // unknown face
+            return null;
+        }
+         
+        // Free memory and recover human face from dump file silultanously:
+        HumanFace face;
+        try {
+            ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
+            final Future<HumanFace> result = executor.submit(() -> HumanFace.restoreFromFile(dumpFile)); // recover face from disk
+            executor.submit(() -> checkMemAndDump()); // free the memory, if necessary
+            executor.shutdown();
+            while (!executor.isTerminated()){}
+            face = result.get();
+        } catch (InterruptedException|ExecutionException ex) {
+            Logger.getLogger(HumanFaceFactory.class.getName()).log(Level.SEVERE, null, ex);
+            return null;
+        }
+        
+        // Update data structures:
+        long time = System.currentTimeMillis();
+        dumpedFaces.remove(faceId);
+        inMemoryFaces.put(time, face);
+        usage.put(faceId, time);
+        return face;
+    }
+    
+    @Override
+    public String toString() {
+        StringBuilder ret = new StringBuilder();
+        ret.append(formatSize(presumableFreeMemory())).
+                append(" Java heap memory available (out of ").
+                append(formatSize(Runtime.getRuntime().maxMemory()));
+        ret.append("). In memory: ").
+                append(this.inMemoryFaces.size()).
+                append(", dumped: ").
+                append(this.dumpedFaces.size());
+        return ret.toString();
+    }
+    
+    /**
+     * Updates last access time of the face allocated in the memory. 
+     * Returns {@code false} if the face is not in the memory.
+     * 
+     * @param faceId Face to be updated
+     * @return {@code false} if the face is not in the memory.
+     */
+    protected boolean updateAccessTime(String faceId) {
+        Long oldTime = usage.get(faceId);
+        if (oldTime == null) {
+            return false;
+        }
+        
+        HumanFace face = inMemoryFaces.get(oldTime);
+        
+        long newTime = System.currentTimeMillis();
+        while (inMemoryFaces.containsKey(newTime)) { // wait until we get unique ms
+            newTime = System.currentTimeMillis();
+        }
+        inMemoryFaces.remove(oldTime);
+        inMemoryFaces.put(newTime, face);
+        usage.put(faceId, newTime);
+        return true;
+    }
+    
+    /**
+     * Checks and releases the heap, if necessary.
+     * 
+     * @return true if some existing face has been dumped to free the memory.
+     * @throws IOException on I/O error
+     */
+    protected boolean checkMemAndDump() throws IOException {
+        double ratio = (double) presumableFreeMemory() / Runtime.getRuntime().maxMemory();
+        if (ratio > MIN_FREE_MEMORY) {
+            return false;
+        }
+        
+        Long time = null;
+        switch (strategy) {
+            case MRU:
+                time = inMemoryFaces.lastKey();
+                break;
+            default:
+            case LRU:
+                time = inMemoryFaces.firstKey();
+                break;
+        }
+        
+        HumanFace faceToDump = this.inMemoryFaces.remove(time);
+        this.usage.remove(faceToDump.getId());
+        dumpedFaces.put(faceToDump.getId(), faceToDump.dumpToFile());
+        return true;
+    }
+        
+    protected static String formatSize(long v) {
+        if (v < 1024) {
+            return v + " B";
+        }
+        int z = (63 - Long.numberOfLeadingZeros(v)) / 10;
+        return String.format("%.1f %sB", (double)v / (1L << (z*10)), " KMGTPE".charAt(z));
+    }
+    
+    /**
+     * https://stackoverflow.com/questions/12807797/java-get-available-memory
+     * @return 
+     */
+    protected long presumableFreeMemory() {
+        long allocatedMemory = (Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory());
+        return Runtime.getRuntime().maxMemory() - allocatedMemory;
+    }
+}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFaceListener.java b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFaceListener.java
index aa6cd03a68d3f74568c0d1e9f513ea9e11942ff4..85180285e2d6304625be83b3a7a249ccc32f329c 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFaceListener.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFaceListener.java
@@ -5,7 +5,7 @@ import cz.fidentis.analyst.mesh.events.MeshListener;
 /**
  * Objects implementing this interface can be registered with 
  * a {@link cz.fidentis.analyst.face.HumanFace} object 
- * and then be informed when the human face (some of its internal data strcutures) changes.
+ * and then be informed when the human face (some of its internal data structures) changes.
  * 
  * @author Radek Oslejsek
  */
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFacePrivilegedCache.java b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFacePrivilegedCache.java
deleted file mode 100644
index 3c73e046761d1ce4022f86bba360ac01ce3b8a5a..0000000000000000000000000000000000000000
--- a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFacePrivilegedCache.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package cz.fidentis.analyst.face;
-
-import java.io.IOException;
-import java.util.concurrent.ExecutionException;
-
-/**
- * This cache preserves the first X faces (privileged faces) always in the memory. 
- * Faces that are loaded when there is not enough free memory are always dumped
- * to file and only one of them is stored in the memory when used.
- * 
- * @author Radek Oslejsek
- */
-public class HumanFacePrivilegedCache extends HumanFaceCache {
-    
-    private static HumanFacePrivilegedCache factory;
-    
-    /**
-     * The only one dumped face currently in the memory
-     */
-    private String recoveredFace;
-    
-    /**
-     * Private constructor. Use {@link instance} instead to get and access the instance.
-     */
-    protected HumanFacePrivilegedCache() {
-    }
-    
-    /**
-     * Returns the factory singleton instance.
-     * 
-     * @return the factory singleton instance
-     */
-    public static HumanFacePrivilegedCache instance() {
-        if (factory == null) {
-            factory = new HumanFacePrivilegedCache();
-        }
-        return factory;
-    }
-
-    @Override
-    protected String selectFaceForDump() {
-        if (this.recoveredFace != null) {
-            return this.recoveredFace;
-        } else {
-            // This should not happen. But return any face from the memory, anyway.
-            for (String faceId: getInMemoryFaces().keySet()) {
-                return faceId; 
-            }
-        }
-        return null;
-    }
-    
-    @Override
-    public void removeFace(String faceId) {
-        if (faceId.equals(this.recoveredFace)) {
-            this.recoveredFace = null;
-        }
-        super.removeFace(faceId);
-    }
-    
-    @Override
-    protected HumanFace recoverFace(String faceId) throws IOException, ClassNotFoundException, InterruptedException, ExecutionException {
-        HumanFace face = super.recoverFace(faceId);
-        if (face != null) {
-            this.recoveredFace = face.getId();
-        }
-        return face;
-    }
-}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/icp/EigenvalueDecomposition.java b/Comparison/src/main/java/cz/fidentis/analyst/icp/EigenvalueDecomposition.java
new file mode 100644
index 0000000000000000000000000000000000000000..4a09774de50bc7f03bf8fffa0cc5cca8df93daa0
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/icp/EigenvalueDecomposition.java
@@ -0,0 +1,944 @@
+package cz.fidentis.analyst.icp;
+
+
+import javax.vecmath.Matrix4d;
+
+/**
+ * Eigenvalues and eigenvectors of a real matrix. 
+ * Taken from https://math.nist.gov/javanumerics/jama/doc/Jama/EigenvalueDecomposition.html
+ * and adapted for Matrix4d.
+ * <p>
+ * If A is symmetric, then A = V*D*V' where the eigenvalue matrix D is
+ * diagonal and the eigenvector matrix V is orthogonal.
+ * I.e. A = V.times(D.times(V.transpose())) and
+ * V.times(V.transpose()) equals the identity matrix.
+ * </p>
+ * <p>
+ * If A is not symmetric, then the eigenvalue matrix D is block diagonal
+ * with the real eigenvalues in 1-by-1 blocks and any complex eigenvalues,
+ * lambda + i*mu, in 2-by-2 blocks, [lambda, mu; -mu, lambda].  The
+ * columns of V represent the eigenvectors in the sense that A*V = V*D,
+ * i.e. A.times(V) equals V.times(D).  The matrix V may be badly
+ * conditioned, or even singular, so the validity of the equation
+ * A = V*D*inverse(V) depends upon V.cond().
+ * </p>
+ * 
+ * @author Maria Kocurekova
+ */
+
+public class EigenvalueDecomposition implements java.io.Serializable {
+
+/* ------------------------
+   Class variables
+ * ------------------------ */
+
+    /** Row and column dimension (square matrix).
+     @serial matrix dimension.
+     */
+    private int n;
+
+    /** Symmetry flag.
+     @serial internal symmetry flag.
+     */
+    private boolean issymmetric;
+
+    /** Arrays for internal storage of eigenvalues.
+     @serial internal storage of eigenvalues.
+     */
+    private double[] d, e;
+
+    /** Array for internal storage of eigenvectors.
+     @serial internal storage of eigenvectors.
+     */
+    private double[][] arrayV;
+
+    /** Array for internal storage of nonsymmetric Hessenberg form.
+     @serial internal storage of nonsymmetric Hessenberg form.
+     */
+    private double[][] arrayH;
+
+    /** Working storage for nonsymmetric algorithm.
+     @serial working storage for nonsymmetric algorithm.
+     */
+    private double[] ort;
+
+/* ------------------------
+   Private Methods
+ * ------------------------ */
+
+    // Symmetric Householder reduction to tridiagonal form.
+
+    private void tred2 () {
+
+        //  This is derived from the Algol procedures tred2 by
+        //  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
+        //  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
+        //  Fortran subroutine in EISPACK.
+
+        for (int j = 0; j < n; j++) {
+            d[j] = arrayV[n-1][j];
+        }
+
+        // Householder reduction to tridiagonal form.
+
+        for (int i = n-1; i > 0; i--) {
+
+            // Scale to avoid under/overflow.
+
+            double scale = 0.0;
+            double h = 0.0;
+            for (int k = 0; k < i; k++) {
+                scale = scale + Math.abs(d[k]);
+            }
+            if (scale == 0.0) {
+                e[i] = d[i-1];
+                for (int j = 0; j < i; j++) {
+                    d[j] = arrayV[i-1][j];
+                    arrayV[i][j] = 0.0;
+                    arrayV[j][i] = 0.0;
+                }
+            } else {
+
+                // Generate Householder vector.
+
+                for (int k = 0; k < i; k++) {
+                    d[k] /= scale;
+                    h += d[k] * d[k];
+                }
+                double f = d[i-1];
+                double g = Math.sqrt(h);
+                if (f > 0) {
+                    g = -g;
+                }
+                e[i] = scale * g;
+                h = h - f * g;
+                d[i-1] = f - g;
+                for (int j = 0; j < i; j++) {
+                    e[j] = 0.0;
+                }
+
+                // Apply similarity transformation to remaining columns.
+
+                for (int j = 0; j < i; j++) {
+                    f = d[j];
+                    arrayV[j][i] = f;
+                    g = e[j] + arrayV[j][j] * f;
+                    for (int k = j+1; k <= i-1; k++) {
+                        g += arrayV[k][j] * d[k];
+                        e[k] += arrayV[k][j] * f;
+                    }
+                    e[j] = g;
+                }
+                f = 0.0;
+                for (int j = 0; j < i; j++) {
+                    e[j] /= h;
+                    f += e[j] * d[j];
+                }
+                double hh = f / (h + h);
+                for (int j = 0; j < i; j++) {
+                    e[j] -= hh * d[j];
+                }
+                for (int j = 0; j < i; j++) {
+                    f = d[j];
+                    g = e[j];
+                    for (int k = j; k <= i-1; k++) {
+                        arrayV[k][j] -= (f * e[k] + g * d[k]);
+                    }
+                    d[j] = arrayV[i-1][j];
+                    arrayV[i][j] = 0.0;
+                }
+            }
+            d[i] = h;
+        }
+
+        // Accumulate transformations.
+
+        for (int i = 0; i < n-1; i++) {
+            arrayV[n-1][i] = arrayV[i][i];
+            arrayV[i][i] = 1.0;
+            double h = d[i+1];
+            if (h != 0.0) {
+                for (int k = 0; k <= i; k++) {
+                    d[k] = arrayV[k][i+1] / h;
+                }
+                for (int j = 0; j <= i; j++) {
+                    double g = 0.0;
+                    for (int k = 0; k <= i; k++) {
+                        g += arrayV[k][i+1] * arrayV[k][j];
+                    }
+                    for (int k = 0; k <= i; k++) {
+                        arrayV[k][j] -= g * d[k];
+                    }
+                }
+            }
+            for (int k = 0; k <= i; k++) {
+                arrayV[k][i+1] = 0.0;
+            }
+        }
+        for (int j = 0; j < n; j++) {
+            d[j] = arrayV[n-1][j];
+            arrayV[n-1][j] = 0.0;
+        }
+        arrayV[n-1][n-1] = 1.0;
+        e[0] = 0.0;
+    }
+
+    // Symmetric tridiagonal QL algorithm.
+
+    private void tql2 () {
+
+        //  This is derived from the Algol procedures tql2, by
+        //  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
+        //  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
+        //  Fortran subroutine in EISPACK.
+
+        for (int i = 1; i < n; i++) {
+            e[i-1] = e[i];
+        }
+        e[n-1] = 0.0;
+
+        double f = 0.0;
+        double tst1 = 0.0;
+        double eps = Math.pow(2.0,-52.0);
+        for (int l = 0; l < n; l++) {
+
+            // Find small subdiagonal element
+
+            tst1 = Math.max(tst1,Math.abs(d[l]) + Math.abs(e[l]));
+            int m = l;
+            while (m < n) {
+                if (Math.abs(e[m]) <= eps*tst1) {
+                    break;
+                }
+                m++;
+            }
+
+            // If m == l, d[l] is an eigenvalue,
+            // otherwise, iterate.
+
+            if (m > l) {
+                int iter = 0;
+                do {
+                    iter = iter + 1;  // (Could check iteration count here.)
+
+                    // Compute implicit shift
+
+                    double g = d[l];
+                    double p = (d[l+1] - g) / (2.0 * e[l]);
+                    double r = Math.hypot(p,1.0);
+                    if (p < 0) {
+                        r = -r;
+                    }
+                    d[l] = e[l] / (p + r);
+                    d[l+1] = e[l] * (p + r);
+                    double dl1 = d[l+1];
+                    double h = g - d[l];
+                    for (int i = l+2; i < n; i++) {
+                        d[i] -= h;
+                    }
+                    f = f + h;
+
+
+                    // Implicit QL transformation.
+
+                    p = d[m];
+                    double c = 1.0;
+                    double c2 = c;
+                    double c3 = c;
+                    double el1 = e[l+1];
+                    double s = 0.0;
+                    double s2 = 0.0;
+                    for (int i = m-1; i >= l; i--) {
+                        c3 = c2;
+                        c2 = c;
+                        s2 = s;
+                        g = c * e[i];
+                        h = c * p;
+                        r = Math.hypot(p,e[i]);
+                        e[i+1] = s * r;
+                        s = e[i] / r;
+                        c = p / r;
+                        p = c * d[i] - s * g;
+                        d[i+1] = h + s * (c * g + s * d[i]);
+
+                        // Accumulate transformation.
+
+                        for (int k = 0; k < n; k++) {
+                            h = arrayV[k][i+1];
+                            arrayV[k][i+1] = s * arrayV[k][i] + c * h;
+                            arrayV[k][i] = c * arrayV[k][i] - s * h;
+                        }
+                    }
+                    p = -s * s2 * c3 * el1 * e[l] / dl1;
+                    e[l] = s * p;
+                    d[l] = c * p;
+
+                    // Check for convergence.
+
+                } while (Math.abs(e[l]) > eps*tst1);
+            }
+            d[l] = d[l] + f;
+            e[l] = 0.0;
+        }
+
+        // Sort eigenvalues and corresponding vectors.
+
+        for (int i = 0; i < n-1; i++) {
+            int k = i;
+            double p = d[i];
+            for (int j = i+1; j < n; j++) {
+                if (d[j] < p) {
+                    k = j;
+                    p = d[j];
+                }
+            }
+            if (k != i) {
+                d[k] = d[i];
+                d[i] = p;
+                for (int j = 0; j < n; j++) {
+                    p = arrayV[j][i];
+                    arrayV[j][i] = arrayV[j][k];
+                    arrayV[j][k] = p;
+                }
+            }
+        }
+    }
+
+    // Nonsymmetric reduction to Hessenberg form.
+
+    private void orthes () {
+
+        //  This is derived from the Algol procedures orthes and ortran,
+        //  by Martin and Wilkinson, Handbook for Auto. Comp.,
+        //  Vol.ii-Linear Algebra, and the corresponding
+        //  Fortran subroutines in EISPACK.
+
+        int low = 0;
+        int high = n-1;
+
+        for (int m = low+1; m <= high-1; m++) {
+
+            // Scale column.
+
+            double scale = 0.0;
+            for (int i = m; i <= high; i++) {
+                scale = scale + Math.abs(arrayH[i][m-1]);
+            }
+            if (scale != 0.0) {
+
+                // Compute Householder transformation.
+
+                double h = 0.0;
+                for (int i = high; i >= m; i--) {
+                    ort[i] = arrayH[i][m-1]/scale;
+                    h += ort[i] * ort[i];
+                }
+                double g = Math.sqrt(h);
+                if (ort[m] > 0) {
+                    g = -g;
+                }
+                h = h - ort[m] * g;
+                ort[m] = ort[m] - g;
+
+                // Apply Householder similarity transformation
+                // H = (I-u*u'/h)*H*(I-u*u')/h)
+
+                for (int j = m; j < n; j++) {
+                    double f = 0.0;
+                    for (int i = high; i >= m; i--) {
+                        f += ort[i]*arrayH[i][j];
+                    }
+                    f = f/h;
+                    for (int i = m; i <= high; i++) {
+                        arrayH[i][j] -= f*ort[i];
+                    }
+                }
+
+                for (int i = 0; i <= high; i++) {
+                    double f = 0.0;
+                    for (int j = high; j >= m; j--) {
+                        f += ort[j]*arrayH[i][j];
+                    }
+                    f = f/h;
+                    for (int j = m; j <= high; j++) {
+                        arrayH[i][j] -= f*ort[j];
+                    }
+                }
+                ort[m] = scale*ort[m];
+                arrayH[m][m-1] = scale*g;
+            }
+        }
+
+        // Accumulate transformations (Algol's ortran).
+
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < n; j++) {
+                arrayV[i][j] = (i == j ? 1.0 : 0.0);
+            }
+        }
+
+        for (int m = high-1; m >= low+1; m--) {
+            if (arrayH[m][m-1] != 0.0) {
+                for (int i = m+1; i <= high; i++) {
+                    ort[i] = arrayH[i][m-1];
+                }
+                for (int j = m; j <= high; j++) {
+                    double g = 0.0;
+                    for (int i = m; i <= high; i++) {
+                        g += ort[i] * arrayV[i][j];
+                    }
+                    // Double division avoids possible underflow
+                    g = (g / ort[m]) / arrayH[m][m-1];
+                    for (int i = m; i <= high; i++) {
+                        arrayV[i][j] += g * ort[i];
+                    }
+                }
+            }
+        }
+    }
+
+
+    // Complex scalar division.
+
+    private transient double cdivr, cdivi;
+    private void cdiv(double xr, double xi, double yr, double yi) {
+        double r,d;
+        if (Math.abs(yr) > Math.abs(yi)) {
+            r = yi/yr;
+            d = yr + r*yi;
+            cdivr = (xr + r*xi)/d;
+            cdivi = (xi - r*xr)/d;
+        } else {
+            r = yr/yi;
+            d = yi + r*yr;
+            cdivr = (r*xr + xi)/d;
+            cdivi = (r*xi - xr)/d;
+        }
+    }
+
+
+    // Nonsymmetric reduction from Hessenberg to real Schur form.
+
+    private void hqr2 () {
+
+        //  This is derived from the Algol procedure hqr2,
+        //  by Martin and Wilkinson, Handbook for Auto. Comp.,
+        //  Vol.ii-Linear Algebra, and the corresponding
+        //  Fortran subroutine in EISPACK.
+
+        // Initialize
+        int nn = this.n;
+        int n = nn-1;
+        int low = 0;
+        int high = nn-1;
+        double eps = Math.pow(2.0,-52.0);
+        double exshift = 0.0;
+        double p=0,q=0,r=0,s=0,z=0,t,w,x,y;
+
+        // Store roots isolated by balanc and compute matrix norm
+        double norm = storeRootsGetNorm(nn, low, high);
+        
+        // Outer loop over eigenvalue index
+        int iter = 0;
+        while (n >= low) {
+
+            // Look for single small sub-diagonal element
+            int l = n;
+            while (l > low) {
+                s = Math.abs(arrayH[l-1][l-1]) + Math.abs(arrayH[l][l]);
+                if (s == 0.0) {
+                    s = norm;
+                }
+                if (Math.abs(arrayH[l][l-1]) < eps * s) {
+                    break;
+                }
+                l--;
+            }
+
+            // Check for convergence
+            if (l == n) { // One root found
+                arrayH[n][n] = arrayH[n][n] + exshift;
+                d[n] = arrayH[n][n];
+                e[n] = 0.0;
+                n--;
+                iter = 0;
+            } else if (l == n-1) { // Two roots found
+                w = arrayH[n][n-1] * arrayH[n-1][n];
+                p = (arrayH[n-1][n-1] - arrayH[n][n]) / 2.0;
+                q = p * p + w;
+                z = Math.sqrt(Math.abs(q));
+                arrayH[n][n] = arrayH[n][n] + exshift;
+                arrayH[n-1][n-1] = arrayH[n-1][n-1] + exshift;
+                x = arrayH[n][n];
+
+                if (q >= 0) { // Real pair
+                    z = (p >= 0) ? p + z : p - z;
+                    d[n-1] = x + z;
+                    d[n] = d[n-1];
+                    if (z != 0.0) {
+                        d[n] = x - w / z;
+                    }
+                    e[n-1] = 0.0;
+                    e[n] = 0.0;
+                    x = arrayH[n][n-1];
+                    s = Math.abs(x) + Math.abs(z);
+                    p = x / s;
+                    q = z / s;
+                    r = Math.sqrt(p * p+q * q);
+                    p = p / r;
+                    q = q / r;
+
+                    for (int j = n-1; j < nn; j++) { // Row modification
+                        z = arrayH[n-1][j];
+                        arrayH[n-1][j] = q * z + p * arrayH[n][j];
+                        arrayH[n][j] = q * arrayH[n][j] - p * z;
+                    }
+
+                    for (int i = 0; i <= n; i++) { // Column modification
+                        z = arrayH[i][n-1];
+                        arrayH[i][n-1] = q * z + p * arrayH[i][n];
+                        arrayH[i][n] = q * arrayH[i][n] - p * z;
+                    }
+
+                    for (int i = low; i <= high; i++) { // Accumulate transformations
+                        z = arrayV[i][n-1];
+                        arrayV[i][n-1] = q * z + p * arrayV[i][n];
+                        arrayV[i][n] = q * arrayV[i][n] - p * z;
+                    }
+                } else { // Complex pair
+                    d[n-1] = x + p;
+                    d[n] = x + p;
+                    e[n-1] = z;
+                    e[n] = -z;
+                }
+                n = n - 2;
+                iter = 0;
+            } else { // No convergence yet
+                // Form shift
+                x = arrayH[n][n];
+                y = 0.0;
+                w = 0.0;
+                if (l < n) {
+                    y = arrayH[n-1][n-1];
+                    w = arrayH[n][n-1] * arrayH[n-1][n];
+                }
+
+                if (iter == 10) { // Wilkinson's original ad hoc shift
+                    exshift += x;
+                    for (int i = low; i <= n; i++) {
+                        arrayH[i][i] -= x;
+                    }
+                    s = Math.abs(arrayH[n][n-1]) + Math.abs(arrayH[n-1][n-2]);
+                    x = y = 0.75 * s;
+                    w = -0.4375 * s * s;
+                }
+
+                if (iter == 30) { // MATLAB's new ad hoc shift
+                    s = (y - x) / 2.0;
+                    s = s * s + w;
+                    if (s > 0) {
+                        s = Math.sqrt(s);
+                        if (y < x) {
+                            s = -s;
+                        }
+                        s = x - w / ((y - x) / 2.0 + s);
+                        for (int i = low; i <= n; i++) {
+                            arrayH[i][i] -= s;
+                        }
+                        exshift += s;
+                        x = y = w = 0.964;
+                    }
+                }
+
+                iter = iter + 1;   // (Could check iteration count here.)
+
+                // Look for two consecutive small sub-diagonal elements
+                int m = n-2;
+                while (m >= l) {
+                    z = arrayH[m][m];
+                    r = x - z;
+                    s = y - z;
+                    p = (r * s - w) / arrayH[m+1][m] + arrayH[m][m+1];
+                    q = arrayH[m+1][m+1] - z - r - s;
+                    r = arrayH[m+2][m+1];
+                    s = Math.abs(p) + Math.abs(q) + Math.abs(r);
+                    p = p / s;
+                    q = q / s;
+                    r = r / s;
+                    if (m == l) {
+                        break;
+                    }
+                    if (Math.abs(arrayH[m][m-1]) * (Math.abs(q) + Math.abs(r)) <
+                            eps * (Math.abs(p) * (Math.abs(arrayH[m-1][m-1]) + Math.abs(z) +
+                                    Math.abs(arrayH[m+1][m+1])))) {
+                        break;
+                    }
+                    m--;
+                }
+
+                updateH(m);
+
+                // Double QR step involving rows l:n and columns m:n
+                for (int k = m; k <= n-1; k++) {
+                    boolean notlast = (k != n-1);
+                    if (k != m) {
+                        p = arrayH[k][k-1];
+                        q = arrayH[k+1][k-1];
+                        r = (notlast ? arrayH[k+2][k-1] : 0.0);
+                        x = Math.abs(p) + Math.abs(q) + Math.abs(r);
+                        if (x == 0.0) {
+                            continue;
+                        }
+                        p = p / x;
+                        q = q / x;
+                        r = r / x;
+                    }
+
+                    s = Math.sqrt(p * p + q * q + r * r);
+                    if (p < 0) {
+                        s = -s;
+                    }
+                    if (s != 0) {
+                        if (k != m) {
+                            arrayH[k][k-1] = -s * x;
+                        } else if (l != m) {
+                            arrayH[k][k-1] = -arrayH[k][k-1];
+                        }
+                        p = p + s;
+                        x = p / s;
+                        y = q / s;
+                        z = r / s;
+                        q = q / p;
+                        r = r / p;
+                        
+                        // Row modification
+                        for (int j = k; j < nn; j++) {
+                            p = arrayH[k][j] + q * arrayH[k+1][j];
+                            if (notlast) {
+                                p = p + r * arrayH[k+2][j];
+                                arrayH[k+2][j] = arrayH[k+2][j] - p * z;
+                            }
+                            arrayH[k][j] = arrayH[k][j] - p * x;
+                            arrayH[k+1][j] = arrayH[k+1][j] - p * y;
+                        }
+
+                        // Column modification
+                        for (int i = 0; i <= Math.min(n,k+3); i++) {
+                            p = x * arrayH[i][k] + y * arrayH[i][k+1];
+                            if (notlast) {
+                                p = p + z * arrayH[i][k+2];
+                                arrayH[i][k+2] = arrayH[i][k+2] - p * r;
+                            }
+                            arrayH[i][k] = arrayH[i][k] - p;
+                            arrayH[i][k+1] = arrayH[i][k+1] - p * q;
+                        }
+
+                        // Accumulate transformations
+                        for (int i = low; i <= high; i++) {
+                            p = x * arrayV[i][k] + y * arrayV[i][k+1];
+                            if (notlast) {
+                                p = p + z * arrayV[i][k+2];
+                                arrayV[i][k+2] = arrayV[i][k+2] - p * r;
+                            }
+                            arrayV[i][k] = arrayV[i][k] - p;
+                            arrayV[i][k+1] = arrayV[i][k+1] - p * q;
+                        }
+                    }  // (s != 0)
+                }  // k loop
+            }  // check convergence
+        }  // while (n >= low)
+
+        if (norm != 0.0) {
+            backSubstitute(nn, eps, norm); // Backsubstitute to find vectors of upper triangular form
+            backTransform(nn, low, high); // Back transformation to get eigenvectors of original matrix
+        }    
+    }
+    
+    private void updateH(int m) {
+        for (int i = m+2; i <= n; i++) {
+            arrayH[i][i-2] = 0.0;
+            if (i > m+2) {
+                arrayH[i][i-3] = 0.0;
+            }
+        }
+    }
+    
+    private double storeRootsGetNorm(int nn, int low, int high) {
+        double norm = 0.0;
+        for (int i = 0; i < nn; i++) {
+            if (i < low | i > high) {
+                d[i] = arrayH[i][i];
+                e[i] = 0.0;
+            }
+            for (int j = Math.max(i-1,0); j < nn; j++) {
+                norm = norm + Math.abs(arrayH[i][j]);
+            }
+        }
+        return norm;
+    }
+    
+    private void backSubstitute(int nn, double eps, double norm) {
+        double p=0,q=0,r=0,s=0,z=0,t,w,x,y;
+        
+        for (n = nn-1; n >= 0; n--) {
+            p = d[n];
+            q = e[n];
+
+            // Real vector
+
+            if (q == 0) {
+                int l = n;
+                arrayH[n][n] = 1.0;
+                for (int i = n-1; i >= 0; i--) {
+                    w = arrayH[i][i] - p;
+                    r = 0.0;
+                    for (int j = l; j <= n; j++) {
+                        r = r + arrayH[i][j] * arrayH[j][n];
+                    }
+                    if (e[i] < 0.0) {
+                        z = w;
+                        s = r;
+                    } else {
+                        l = i;
+                        if (e[i] == 0.0) {
+                            if (w != 0.0) {
+                                arrayH[i][n] = -r / w;
+                            } else {
+                                arrayH[i][n] = -r / (eps * norm);
+                            }
+
+                            // Solve real equations
+
+                        } else {
+                            x = arrayH[i][i+1];
+                            y = arrayH[i+1][i];
+                            q = (d[i] - p) * (d[i] - p) + e[i] * e[i];
+                            t = (x * s - z * r) / q;
+                            arrayH[i][n] = t;
+                            if (Math.abs(x) > Math.abs(z)) {
+                                arrayH[i+1][n] = (-r - w * t) / x;
+                            } else {
+                                arrayH[i+1][n] = (-s - y * t) / z;
+                            }
+                        }
+
+                        // Overflow control
+
+                        t = Math.abs(arrayH[i][n]);
+                        if ((eps * t) * t > 1) {
+                            for (int j = i; j <= n; j++) {
+                                arrayH[j][n] = arrayH[j][n] / t;
+                            }
+                        }
+                    }
+                }
+
+                // Complex vector
+
+            } else if (q < 0) {
+                int l = n-1;
+
+                // Last vector component imaginary so matrix is triangular
+
+                if (Math.abs(arrayH[n][n-1]) > Math.abs(arrayH[n-1][n])) {
+                    arrayH[n-1][n-1] = q / arrayH[n][n-1];
+                    arrayH[n-1][n] = -(arrayH[n][n] - p) / arrayH[n][n-1];
+                } else {
+                    cdiv(0.0,-arrayH[n-1][n],arrayH[n-1][n-1]-p,q);
+                    arrayH[n-1][n-1] = cdivr;
+                    arrayH[n-1][n] = cdivi;
+                }
+                arrayH[n][n-1] = 0.0;
+                arrayH[n][n] = 1.0;
+                for (int i = n-2; i >= 0; i--) {
+                    double ra,sa,vr,vi;
+                    ra = 0.0;
+                    sa = 0.0;
+                    for (int j = l; j <= n; j++) {
+                        ra = ra + arrayH[i][j] * arrayH[j][n-1];
+                        sa = sa + arrayH[i][j] * arrayH[j][n];
+                    }
+                    w = arrayH[i][i] - p;
+
+                    if (e[i] < 0.0) {
+                        z = w;
+                        r = ra;
+                        s = sa;
+                    } else {
+                        l = i;
+                        if (e[i] == 0) {
+                            cdiv(-ra,-sa,w,q);
+                            arrayH[i][n-1] = cdivr;
+                            arrayH[i][n] = cdivi;
+                        } else {
+
+                            // Solve complex equations
+
+                            x = arrayH[i][i+1];
+                            y = arrayH[i+1][i];
+                            vr = (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q;
+                            vi = (d[i] - p) * 2.0 * q;
+                            if (vr == 0.0 & vi == 0.0) {
+                                vr = eps * norm * (Math.abs(w) + Math.abs(q) +
+                                        Math.abs(x) + Math.abs(y) + Math.abs(z));
+                            }
+                            cdiv(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi);
+                            arrayH[i][n-1] = cdivr;
+                            arrayH[i][n] = cdivi;
+                            if (Math.abs(x) > (Math.abs(z) + Math.abs(q))) {
+                                arrayH[i+1][n-1] = (-ra - w * arrayH[i][n-1] + q * arrayH[i][n]) / x;
+                                arrayH[i+1][n] = (-sa - w * arrayH[i][n] - q * arrayH[i][n-1]) / x;
+                            } else {
+                                cdiv(-r-y*arrayH[i][n-1],-s-y*arrayH[i][n],z,q);
+                                arrayH[i+1][n-1] = cdivr;
+                                arrayH[i+1][n] = cdivi;
+                            }
+                        }
+
+                        // Overflow control
+
+                        t = Math.max(Math.abs(arrayH[i][n-1]),Math.abs(arrayH[i][n]));
+                        if ((eps * t) * t > 1) {
+                            for (int j = i; j <= n; j++) {
+                                arrayH[j][n-1] = arrayH[j][n-1] / t;
+                                arrayH[j][n] = arrayH[j][n] / t;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    
+    private void backTransform(int nn, int low, int high) {
+        for (int i = 0; i < nn; i++) { // Vectors of isolated roots
+            if (i < low | i > high) {
+                for (int j = i; j < nn; j++) {
+                    arrayV[i][j] = arrayH[i][j];
+                }
+            }
+        }
+
+        for (int j = nn-1; j >= low; j--) { // Back transformation to get eigenvectors of original matrix
+            for (int i = low; i <= high; i++) {
+                double z = 0.0;
+                for (int k = low; k <= Math.min(j,high); k++) {
+                    z = z + arrayV[i][k] * arrayH[k][j];
+                }
+                arrayV[i][j] = z;
+            }
+        }
+    }
+
+
+/* ------------------------
+   Constructor
+ * ------------------------ */
+
+    /** Check for symmetry, then construct the eigenvalue decomposition
+     Structure to access D and V.
+     @param arg    Square matrix
+     */
+
+    public EigenvalueDecomposition(Matrix4d arg) {
+        n = 4;
+        double[][] arrayA = new double[n][n];
+        for (int j = 0; j < n; j++) {
+            for (int i = 0; i < n; i++) {
+                arrayA[i][j] = arg.getElement(i,j);
+            }
+        }
+
+
+        arrayV = new double[n][n];
+        d = new double[n];
+        e = new double[n];
+
+        issymmetric = true;
+        for (int j = 0; (j < n) & issymmetric; j++) {
+            for (int i = 0; (i < n) & issymmetric; i++) {
+                issymmetric = (arrayA[i][j] == arrayA[j][i]);
+            }
+        }
+
+        if (issymmetric) {
+            for (int i = 0; i < n; i++) {
+                for (int j = 0; j < n; j++) {
+                    arrayV[i][j] = arrayA[i][j];
+                }
+            }
+
+            // Tridiagonalize.
+            tred2();
+
+            // Diagonalize.
+            tql2();
+
+        } else {
+            arrayH = new double[n][n];
+            ort = new double[n];
+
+            for (int j = 0; j < n; j++) {
+                for (int i = 0; i < n; i++) {
+                    arrayH[i][j] = arrayA[i][j];
+                }
+            }
+
+            // Reduce to Hessenberg form.
+            orthes();
+
+            // Reduce Hessenberg to real Schur form.
+            hqr2();
+        }
+    }
+
+/* ------------------------
+   Public Methods
+ * ------------------------ */
+
+    /** Return the eigenvector matrix
+     @return     V
+     */
+
+    public Matrix4d getV () {
+        Matrix4d res =  new Matrix4d(arrayV[0][0],arrayV[0][1],arrayV[0][2],arrayV[0][3],
+                arrayV[1][0],arrayV[1][1],arrayV[1][2],arrayV[1][3],
+                arrayV[2][0],arrayV[2][1],arrayV[2][2],arrayV[2][3],
+                arrayV[3][0],arrayV[3][1],arrayV[3][2],arrayV[3][3]);
+
+        return res;
+    }
+
+
+
+    /** Return the block diagonal eigenvalue matrix
+     @return     D
+     */
+
+    public Matrix4d getD () {
+        double[][] arrayD = new double[n][n];
+     /*   Matrix4d X = new Matrix4d();
+        double[][] D=new double[n][n];
+        for (int j = 0; j < n; j++) {
+            for (int i = 0; i < n; i++) {
+                D[i][j] = X.getElement(i, j);
+            }
+        }*/
+
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < n; j++) {
+                arrayD[i][j] = 0.0;
+            }
+            arrayD[i][i] = d[i];
+            if (e[i] > 0) {
+                arrayD[i][i+1] = e[i];
+            } else if (e[i] < 0) {
+                arrayD[i][i-1] = e[i];
+            }
+        }
+        return new Matrix4d(arrayD[0][0],arrayD[0][1],arrayD[0][2],arrayD[0][3],
+                arrayD[1][0],arrayD[1][1],arrayD[1][2],arrayD[1][3],
+                arrayD[2][0],arrayD[2][1],arrayD[2][2],arrayD[2][3],
+                arrayD[3][0],arrayD[3][1],arrayD[3][2],arrayD[3][3]);
+    }
+}
\ No newline at end of file
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/icp/Icp.java b/Comparison/src/main/java/cz/fidentis/analyst/icp/Icp.java
deleted file mode 100644
index c50fe55c95113a2227923dcddb5b1e2aad925480..0000000000000000000000000000000000000000
--- a/Comparison/src/main/java/cz/fidentis/analyst/icp/Icp.java
+++ /dev/null
@@ -1,326 +0,0 @@
-package cz.fidentis.analyst.icp;
-
-import cz.fidentis.analyst.mesh.core.MeshFacet;
-import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
-import cz.fidentis.analyst.mesh.core.MeshPoint;
-import cz.fidentis.analyst.visitors.mesh.HausdorffDistance;
-
-import javax.vecmath.Matrix4d;
-import javax.vecmath.Quat4d;
-import javax.vecmath.Vector3d;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Objects;
-import javax.vecmath.Point3d;
-
-/**
- * Icp represents class for computing the ICP (Iterative closest point) algorithm.
- * It is used to minimize the distance between two {@link cz.fidentis.analyst.mesh.core.MeshFacet}s.
- * This class does not have parameterized constructor, for running ICP algorithm use public method getTransformedFacet.
- * (In case you want change default setup use public method setParameters.)
- *
- * @author Maria Kocurekova
- */
-public class Icp {
-
-    private final List<IcpTransformation> transformations = new LinkedList<>();
-    private MeshFacet transformedFacet = null;
-    private  int maxIteration = 10;
-    private boolean scale;
-    private double error = 0.05;
-
-
-    /**
-     * Change default setup for max count of iteration, scale and error.
-     *
-     * @param maxIteration Max count of running iterations
-     *                     (it includes computing new transformation and applying it).
-     * @param scale In case there is scale, scale factor is also computed.
-     * @param e Max error which is allowed.
-     */
-    public void setParameters(int maxIteration, boolean scale, double e){
-        this.maxIteration = maxIteration;
-        this.scale = scale;
-        this.error = e;
-    }
-
-    /**
-     * GetTransformedFacet represents running of the ICP algorithm. It use methods for computing and applying transformations.
-     * It is running until count of iterations is lower than maxIteration or until we reach lower distance
-     * between two objects than allowed error.
-     *
-     * @param mainFacet MainFacet represents fix faced.
-     *                  We want to align computedFacet according to MainFacet.
-     * @param comparedFacet Facet we want to be aligned.
-     * @return Return transformed facet with new coordinates.
-     */
-    public MeshFacet getTransformedFacet(MeshFacet mainFacet, MeshFacet comparedFacet){
-        transformedFacet = new MeshFacetImpl(comparedFacet);
-
-        HausdorffDistance hausdorffDist = new HausdorffDistance(mainFacet, HausdorffDistance.Strategy.POINT_TO_POINT, false, false);
-
-        int currentIteration = 0;
-        IcpTransformation transformation = null;
-
-        double prevMeanD = Double.POSITIVE_INFINITY;
-
-        while ((currentIteration < maxIteration) &&
-                (Double.isInfinite(prevMeanD) ||  Math.abs(prevMeanD - Objects.requireNonNull(transformation).getMeanD() ) > error )){
-
-            hausdorffDist.visitMeshFacet(transformedFacet);
-            List<Double> distances = hausdorffDist.getDistances().get(transformedFacet);
-            List<Point3d> nearestPoints = hausdorffDist.getNearestPoints().get(transformedFacet);
-
-            if(transformation != null){
-                prevMeanD = transformation.getMeanD();
-            }
-
-            transformation = computeIcpTransformation(nearestPoints, distances);
-            transformations.add(transformation);
-            applyTransformation(transformation);
-            currentIteration ++;
-        }
-
-        return transformedFacet;
-    }
-    
-    /**
-     * Getter for all transformations.
-     * 
-     * @return List of IcpTransformation.
-     */
-    public List<IcpTransformation> getTransformations() {
-        return Collections.unmodifiableList(transformations);
-    }
-
-
-    /***********************************************************
-     *  PRIVATE METHODS
-     ***********************************************************/
-    
-    /**
-     * Compute transformation parameters( translation, rotation and scale factor).
-     *
-     * @param nearestPoints List of nearest points computed by Hausdorff distance.
-     * @param distances list of distances computed by Hausdorff distance
-     * @return Return Icp transformation which is represented by computed parameters.
-     */
-    private IcpTransformation computeIcpTransformation(List<Point3d> nearestPoints, List<Double> distances) {
-        List<MeshPoint>comparedPoints = transformedFacet.getVertices();
-        double x, y, z;
-        double meanX = 0;
-        double meanY = 0;
-        double meanZ = 0;
-        double meanD = 0;
-        double countOfNotNullPoints = 0;
-
-        List<Point3d>centers = computeCenterBothFacets(nearestPoints, comparedPoints);
-        Point3d mainCenter = centers.get(0);
-        Point3d comparedCenter = centers.get(1);
-        Matrix4d sumMatrix = new Matrix4d();
-        Matrix4d multipleMatrix = new Matrix4d();
-
-        for(int i = 0; i < comparedPoints.size(); i++) {
-            if (nearestPoints.get(i) == null){
-                continue;
-            }
-            // START computing Translation coordinates
-            x = nearestPoints.get(i).x - comparedPoints.get(i).getPosition().x;
-            y = nearestPoints.get(i).y - comparedPoints.get(i).getPosition().y;
-            z = nearestPoints.get(i).z - comparedPoints.get(i).getPosition().z;
-
-            meanX += x;
-            meanY += y;
-            meanZ += z;
-            meanD += distances.get(i);
-
-            // START computing Rotation parameters
-            //multipleMatrix =
-            //= (transpose (sumMatrix of relative coordinates of compared point)) x (sumMatrix of relative coordinates of nearest point)
-            multipleMatrix.mulTransposeLeft(
-                    sumMatrixComp(relativeCoordinate(comparedPoints.get(i).getPosition(), comparedCenter)), 
-                    sumMatrixMain(relativeCoordinate(nearestPoints.get(i),mainCenter))
-            );
-            sumMatrix.add(multipleMatrix);
-
-            countOfNotNullPoints ++;
-        }
-
-        meanD /= countOfNotNullPoints;
-        meanX /= countOfNotNullPoints;
-        meanY /= countOfNotNullPoints;
-        meanZ /= countOfNotNullPoints;
-        // END computing translation parameter
-
-        Quat4d rotation = new Quat4d();
-        rotation.set(sumMatrix);
-        rotation.normalize();
-        // END computing rotation parameter
-
-        //computing SCALE parameter
-        double sxUp = 0;
-        double scaleFactor = 0;
-        double sxDown = 0;
-
-        if (scale) {
-            Matrix4d rotationMatrix = new Matrix4d();
-            rotationMatrix.set(rotation);
-            Matrix4d matrixPoint, matrixPointCompare;
-
-            for (int i = 0; i < nearestPoints.size(); i++) {
-                if(nearestPoints.get(i) == null) {
-                    continue;
-                }
-                matrixPoint = pointToMatrix(relativeCoordinate(nearestPoints.get(i), mainCenter));
-                matrixPointCompare = pointToMatrix(relativeCoordinate(comparedPoints.get(i).getPosition(),comparedCenter));
-                matrixPointCompare.mul(rotationMatrix);
-
-                matrixPoint.transpose();
-                matrixPoint.mul(matrixPointCompare);
-                sxUp += matrixPoint.getElement(0, 0);
-
-                matrixPointCompare.transpose();
-                matrixPointCompare.mul(matrixPointCompare);
-                sxDown += matrixPointCompare.getElement(0,0);
-            }
-
-            scaleFactor = sxUp / sxDown;
-
-        } // end computing scale parameter
-
-        return new IcpTransformation(new Vector3d(meanX, meanY, meanZ), rotation, scaleFactor, meanD);
-    }
-
-    /**
-     * Apply computed transformation to compared facet.
-     *
-     * @param transformation Computed transformation.
-     */
-    private void applyTransformation(IcpTransformation transformation) {
-        Point3d meshPointPosition;
-        Quat4d rotationCopy = new Quat4d();
-        Quat4d conjugateRotation = new Quat4d();
-
-
-        for (MeshPoint comparedPoint : transformedFacet.getVertices()) {
-            meshPointPosition = comparedPoint.getPosition();
-
-            Quat4d point = new Quat4d(meshPointPosition.x, meshPointPosition.y, meshPointPosition.z, 1);
-
-            if (transformedFacet.getVertices().size() > 1) {
-                conjugateRotation.conjugate(transformation.getRotation());
-                rotationCopy.mul(point, conjugateRotation);
-                rotationCopy.mul(transformation.getRotation(), rotationCopy);
-            } else {
-                rotationCopy = point;
-            }
-
-            if(scale && !Double.isNaN(transformation.getScaleFactor())) {
-                meshPointPosition.set(rotationCopy.x * transformation.getScaleFactor() + transformation.getTranslation().x +  meshPointPosition.x,
-                        rotationCopy.y * transformation.getScaleFactor() + transformation.getTranslation().y +  meshPointPosition.y,
-                        rotationCopy.z * transformation.getScaleFactor() + transformation.getTranslation().z +  meshPointPosition.z);
-            } else {
-                meshPointPosition.set(rotationCopy.x+ transformation.getTranslation().x + meshPointPosition.x,
-                        rotationCopy.y + transformation.getTranslation().y + meshPointPosition.y,
-                        rotationCopy.z + transformation.getTranslation().z + meshPointPosition.z);
-            }
-
-        }
-    }
-
-    /**
-     * Compute center of both given objects which are represents by list of Vector3d.
-     * Return list of two centers points.
-     *
-     * @param nearestPoints list of the nearest neighbours
-     * @param comparedPoints list fo compared points
-     * @return List with two points. The first one represents center of main facet
-     * and the second one represents center of compared facet.
-     */
-    private List<Point3d> computeCenterBothFacets(List<Point3d> nearestPoints, List<MeshPoint> comparedPoints) {
-        double xN = 0;
-        double yN = 0;
-        double zN = 0;
-
-        double xC = 0;
-        double yC = 0;
-        double zC = 0;
-
-        int countOfNotNullPoints = 0;
-        List<Point3d> result = new ArrayList<>(2);
-
-        for (int i = 0; i < nearestPoints.size(); i++) {
-
-            if(nearestPoints.get(i) == null){
-                continue;
-            }
-
-            xN += nearestPoints.get(i).x;
-            yN += nearestPoints.get(i).y;
-            zN += nearestPoints.get(i).z;
-
-            xC += comparedPoints.get(i).getPosition().x;
-            yC += comparedPoints.get(i).getPosition().y;
-            zC += comparedPoints.get(i).getPosition().z;
-
-            countOfNotNullPoints ++;
-        }
-        result.add(new Point3d(xN/countOfNotNullPoints,yN/countOfNotNullPoints,zN/countOfNotNullPoints));
-        result.add(new Point3d(xC/countOfNotNullPoints,yC/countOfNotNullPoints,zC/countOfNotNullPoints));
-        return result;
-    }
-
-    /**
-     * Compute relative coordinate of given point according to given center.
-     * Relative coordinates represents distance from the center of the mesh to vertex.
-     *
-     * @param p Point of which relative coordinates we want to be computed.
-     * @param center Vector3d which represents center of object.
-     * @return Vector3d which represents coordinates of new point according to center.
-     */
-    private Point3d relativeCoordinate(Point3d p, Point3d center) {
-        return new Point3d(p.x - center.x,p.y - center.y, p.z - center.z);
-    }
-
-    /**
-     * Compute sum matrix of given point. Given point represents compared point.
-     *
-     * @param p Compared point
-     * @return Sum matrix of given point
-     */
-    private Matrix4d sumMatrixComp(Point3d p) {
-        return new Matrix4d(0, -p.x, -p.y, -p.z,
-                p.x, 0, p.z, -p.y,
-                p.y, -p.z, 0, p.x,
-                p.z, p.y, -p.x,0 );
-    }
-
-
-    /**
-     * Compute sum matrix of given point. Given point is point from main facet.
-     *
-     * @param p Compared point
-     * @return Sum matrix of given point
-     */
-    private Matrix4d sumMatrixMain(Point3d p) {
-        return new Matrix4d(0, -p.x, -p.y, -p.z,
-                p.x, 0, -p.z, p.y,
-                p.y, p.z, 0, -p.x,
-                p.z, -p.y, p.x, 0);
-    }
-
-    /**
-     * Convert point (Vector3d) to matrix(Matrix4d).
-     *
-     * @param p Point, we want to be converted.
-     * @return Matrix of point.
-     */
-    private Matrix4d pointToMatrix(Point3d p){
-        return new Matrix4d(p.x, p.y, p.z, 1,
-                0, 0, 0, 0, 0, 0,
-                0,0, 0, 0, 0, 0);
-    }
-
-}
\ No newline at end of file
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/icp/IcpTransformation.java b/Comparison/src/main/java/cz/fidentis/analyst/icp/IcpTransformation.java
index 103958d7ffbd16432d7f338cef7f28933ffa0e44..fcf0fda9110e5afdc8e8d007220d3d088bfb09c2 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/icp/IcpTransformation.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/icp/IcpTransformation.java
@@ -1,6 +1,6 @@
 package cz.fidentis.analyst.icp;
 
-import javax.vecmath.Quat4d;
+import javax.vecmath.Point3d;
 import javax.vecmath.Vector3d;
 
 /**
@@ -10,7 +10,7 @@ import javax.vecmath.Vector3d;
  */
 public class IcpTransformation {
 
-    private final Quat4d rotation;
+    private final Quaternion rotation;
     private final double scaleFactor;
     private final Vector3d translation;
     private final double meanD;
@@ -25,7 +25,7 @@ public class IcpTransformation {
      *                    In case there is no scale the value is 0.
      * @param meanD MeanD represents mean distance between objects.
      */
-    public IcpTransformation(Vector3d translation, Quat4d rotation, double scaleFactor,double meanD) {
+    public IcpTransformation(Vector3d translation, Quaternion rotation, double scaleFactor, double meanD) {
         this.translation = translation;
         this.scaleFactor = scaleFactor;
         this.rotation = rotation;
@@ -36,7 +36,7 @@ public class IcpTransformation {
      * Getter for rotation.
      * @return Return rotation parameter.
      */
-    public Quat4d getRotation() {
+    public Quaternion getRotation() {
         return rotation;
     }
 
@@ -63,4 +63,35 @@ public class IcpTransformation {
     public double getMeanD() {
         return meanD;
     }
+    
+    /**
+     * Apply transformation to given 3D point.
+     *
+     * @param point Original point
+     * @param scale Whether to scale as well
+     * @return transformed point or {@code null}
+     */
+    public Point3d transformPoint(Point3d point, boolean scale) {
+        if (point == null) {
+            return null;
+        }
+        
+        Quaternion rotQuat = new Quaternion(point.x, point.y, point.z, 1);
+        Quaternion rotationCopy = Quaternion.multiply(rotQuat, getRotation().getConjugate());
+        rotQuat = Quaternion.multiply(getRotation(), rotationCopy);
+        
+        if(scale && !Double.isNaN(getScaleFactor())) {
+            return new Point3d(
+                    rotQuat.x * getScaleFactor() + getTranslation().x,
+                    rotQuat.y * getScaleFactor() + getTranslation().y,
+                    rotQuat.z * getScaleFactor() + getTranslation().z
+            );
+        } else {
+            return new Point3d(
+                    rotQuat.x + getTranslation().x,
+                    rotQuat.y + getTranslation().y ,
+                    rotQuat.z + getTranslation().z
+            );
+        }
+    }
 }
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/icp/IcpTransformer.java b/Comparison/src/main/java/cz/fidentis/analyst/icp/IcpTransformer.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4775d97a97b01f297f58712233425a57a094b0f
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/icp/IcpTransformer.java
@@ -0,0 +1,470 @@
+package cz.fidentis.analyst.icp;
+
+import cz.fidentis.analyst.kdtree.KdTree;
+import cz.fidentis.analyst.mesh.MeshVisitor;
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshModel;
+import cz.fidentis.analyst.mesh.core.MeshPoint;
+import cz.fidentis.analyst.visitors.mesh.HausdorffDistance;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import javax.vecmath.Matrix4d;
+import javax.vecmath.Point3d;
+import javax.vecmath.Vector3d;
+
+/**
+ * Visitor applying the Iterative Closest Point (ICP) algorithm to minimize 
+ * Hausdorff distance of two triangular meshes. 
+ * Inspected mesh facets are transformed (!) (vertices are moved) and the history 
+ * of their transformations (transformation performed in each ICP iteration) is returned.
+ * <p>
+ * This visitor <strong>is not thread-safe</strong> due to efficiency reasons
+ * and because of the algorithm principle, when it iterates multiple times through 
+ * each inspected facet. Therefore, concurrent ICP transformation has to use 
+ * an individual ICP visitor for each transformed (inspected) mesh facet.
+ * Sequential inspection of multiple facets using a single visitor's instance 
+ * is possible.
+ * </p>
+ * 
+ * @author Maria Kocurekova
+ * @author Radek Oslejsek
+ */
+public class IcpTransformer extends MeshVisitor   {
+    
+    /**
+     * Transformed mesh facets and their history of transformations.
+     * Key = visited mesh facets. 
+     * Value = History of transformations (transformation performed in each ICP iteration).
+     */
+    private final Map<MeshFacet, List<IcpTransformation>> transformations = new HashMap<>();
+    
+    /**
+     * Maximal number of ICP iterations
+     */
+    private final int maxIteration;
+    
+    /**
+     * Whether to scale mesh facets as well
+     */
+    private final boolean scale;
+    
+    /**
+     * Acceptable error. When reached, then the ICP stops.
+     */
+    private final double error;
+    
+    /**
+     * K-d tree of the primary triangular mesh(es).
+     */
+    private final KdTree primaryKdTree;
+    
+    private final UndersamplingStrategy reductionStrategy;
+    
+    /**
+     * Constructor.
+     * 
+     * @param mainFacet Primary mesh facet. Must not be {@code null}. 
+     * Inspected facets are transformed toward this primary mesh.
+     * @param maxIteration Maximal number of ICP iterations (it includes computing 
+     * new transformation and applying it). A number bigger than zero.
+     * Reasonable number seems to be 10.
+     * @param scale If {@code true}, then the scale factor is also computed.
+     * @param error Acceptable error. A number bugger than or equal to zero. 
+     * When reached, then the ICP stops. Reasonable number seems to be 0.05.
+     * @param strategy One of the reduction strategies. If {@code null}, then {@link NoUndersampling} is used.
+     * @throws IllegalArgumentException if some parameter is wrong
+     */
+    public IcpTransformer(MeshFacet mainFacet, int maxIteration, boolean scale, double error, UndersamplingStrategy strategy) {
+        this(new HashSet<>(Collections.singleton(mainFacet)), maxIteration, scale, error, strategy);
+        if (mainFacet == null) {
+            throw new IllegalArgumentException("mainFacet");
+        }
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param mainFacets Primary mesh facets. Must not be {@code null}. 
+     * Inspected facets are transformed toward these primary mesh. 
+     * @param maxIteration Maximal number of ICP iterations (it includes computing 
+     * new transformation and applying it). A number bigger than zero.
+     * Reasonable number seems to be 10.
+     * @param scale If {@code true}, then the scale factor is also computed.
+     * @param error Acceptable error. A number bugger than or equal to zero. 
+     * When reached, then the ICP stops. Reasonable number seems to be 0.05.
+     * @param strategy One of the reduction strategies. If {@code null}, then {@link NoUndersampling} is used.
+     * @throws IllegalArgumentException if some parameter is wrong
+     */
+    public IcpTransformer(Set<MeshFacet> mainFacets, int maxIteration, boolean scale, double error, UndersamplingStrategy strategy) {
+        if (mainFacets == null) {
+            throw new IllegalArgumentException("mainFacets");
+        }
+        if (maxIteration <= 0) {
+            throw new IllegalArgumentException("maxIteration");
+        }
+        if (error < 0.0) {
+            throw new IllegalArgumentException("error");
+        }
+        this.primaryKdTree = new KdTree(new ArrayList<>(mainFacets));
+        this.error = error;
+        this.maxIteration = maxIteration;
+        this.scale = scale;
+        this.reductionStrategy = (strategy == null) ? new NoUndersampling() : strategy;
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param mainModel Primary mesh model. Must not be {@code null}. 
+     * Inspected facets are transformed toward this primary mesh.
+     * @param maxIteration Maximal number of ICP iterations (it includes computing 
+     * new transformation and applying it). A number bigger than zero.
+     * Reasonable number seems to be 10.
+     * @param scale If {@code true}, then the scale factor is also computed.
+     * @param error Acceptable error. A number bugger than or equal to zero. 
+     * When reached, then the ICP stops. Reasonable number seems to be 0.05.
+     * @param strategy One of the reduction strategies. If {@code null}, then {@link NoUndersampling} is used.
+     * @throws IllegalArgumentException if some parameter is wrong
+     */
+    public IcpTransformer(MeshModel mainModel, int maxIteration, boolean scale, double error, UndersamplingStrategy strategy) {
+        this(new HashSet<>(mainModel.getFacets()), maxIteration, scale, error, strategy);
+        if (mainModel.getFacets().isEmpty()) {
+            throw new IllegalArgumentException("mainModel");
+        }
+    }
+    
+    /**
+     * Constructor.
+     * 
+     * @param primaryKdTree The k-d tree of the primary mesh. Must not be {@code null}. 
+     * Inspected facets are transformed toward this primary mesh.
+     * @param maxIteration Maximal number of ICP iterations (it includes computing 
+     * new transformation and applying it). A number bigger than zero.
+     * Reasonable number seems to be 10.
+     * @param scale If {@code true}, then the scale factor is also computed.
+     * @param error Acceptable error. A number bugger than or equal to zero. When reached, then the ICP stops.
+     * @param strategy One of the reduction strategies. If {@code null}, then {@link NoUndersampling} is used.
+     * @throws IllegalArgumentException if some parameter is wrong
+     */
+    public IcpTransformer(KdTree primaryKdTree, int maxIteration, boolean scale, double error, UndersamplingStrategy strategy) {
+        if (primaryKdTree == null) {
+            throw new IllegalArgumentException("primaryKdTree");
+        }
+        if (maxIteration <= 0) {
+            throw new IllegalArgumentException("maxIteration");
+        }
+        if (error < 0.0) {
+            throw new IllegalArgumentException("error");
+        }
+        this.primaryKdTree = primaryKdTree;
+        this.error = error;
+        this.maxIteration = maxIteration;
+        this.scale = scale;
+        this.reductionStrategy = (strategy == null) ? new NoUndersampling() : strategy;
+    }
+    
+    /**
+     * Returns the history of transformations (transformation performed in each 
+     * ICP iteration for each inspected mesh facet).
+     * Keys in the map contain mesh facets that were inspected and transformed. 
+     * For each transformed facet, a list of transformations to the primary mesh
+     * is stored. The order of transformations corresponds to the order of ICP iterations, 
+     * i.e., the i-th value is the transformation applied in the i-th iteration on the visited mesh facet.
+     * It also means that the size of the list corresponds to the number of iterations 
+     * performed for given mesh facet.
+     * 
+     * @return The history of transformations (transformation performed in each ICP iteration for each inspected mesh facet).
+     */
+    public Map<MeshFacet, List<IcpTransformation>> getTransformations() {
+        return Collections.unmodifiableMap(transformations);
+    }
+    
+    
+    /**
+     * This visitor is <strong>is not thread-safe</strong>.
+     * Therefore, concurrent ICP transformations have to use an individual ICP visitor for each 
+     * transformed (inspected) mesh facet.
+     * 
+     * @return {@code false}.
+     */
+    @Override
+    public boolean isThreadSafe() {
+        return false;
+    }
+    
+    /**
+     * Returns the maximal number of ICP iterations used for the computation.
+     * 
+     * @return the maximal number of ICP iterations used for the computation
+     */
+    public int getMaxIterations() {
+        return this.maxIteration;
+    }
+    
+    /**
+     * Returns maximal acceptable error used for the computation.
+     * 
+     * @return maximal acceptable error used for the computation
+     */
+    public double getError() {
+        return this.error;
+    }
+    
+    /**
+     * Returns {@code true} if the inspected mesh faces were also scaled.
+     * 
+     * @return {@code true} if the inspected mesh faces were also scaled.
+     */
+    public boolean getScale() {
+        return this.scale;
+    }
+    
+    /**
+     * Returns k-d tree of the primary mesh to which other meshes has been transformed.
+     * 
+     * @return k-d tree of the primary mesh
+     */
+    public KdTree getPrimaryKdTree() {
+        return this.primaryKdTree;
+    }
+    
+    @Override
+    public void visitMeshFacet(MeshFacet transformedFacet) {
+        HausdorffDistance hausdorffDist = new HausdorffDistance(
+                this.primaryKdTree, 
+                HausdorffDistance.Strategy.POINT_TO_POINT, 
+                false, // relative distance
+                true   // parallel computation
+        );
+        
+        MeshFacet reducedFacet = new UndersampledMeshFacet(transformedFacet, reductionStrategy);
+
+        int currentIteration = 0;
+        IcpTransformation transformation = null;
+        
+        if (!transformations.containsKey(transformedFacet)) {
+            transformations.put(transformedFacet, new ArrayList<>(maxIteration));
+        }
+
+        double prevMeanD = Double.POSITIVE_INFINITY;
+
+        while ((currentIteration < maxIteration) &&
+                (Double.isInfinite(prevMeanD) || Math.abs(prevMeanD - Objects.requireNonNull(transformation).getMeanD()) > error )) {
+
+            hausdorffDist.visitMeshFacet(reducedFacet); // repeated incpection re-calculates the distance
+            List<Double> distances = hausdorffDist.getDistances().get(reducedFacet);
+            List<Point3d> nearestPoints = hausdorffDist.getNearestPoints().get(reducedFacet);
+
+            if (transformation != null) {
+                prevMeanD = transformation.getMeanD();
+            }
+
+            transformation = computeIcpTransformation(nearestPoints, distances, reducedFacet);
+            transformations.get(transformedFacet).add(transformation);
+            applyTransformation(transformedFacet, transformation);
+            currentIteration ++;
+        }        
+    }
+    
+    /***********************************************************
+     *  PRIVATE METHODS
+     ***********************************************************/
+
+    /**
+     * Compute transformation parameters( translation, rotation and scale factor).
+     * Based on old FIDENTIS implementation
+     *
+     * @param nearestPoints List of nearest points computed by Hausdorff distance.
+     * @param distances list of distances computed by Hausdorff distance
+     * @return Return ICP transformation which is represented by computed parameters.
+
+     */
+    private IcpTransformation computeIcpTransformation(List<Point3d> nearestPoints, List<Double> distances, MeshFacet transformedFacet) {
+        List<MeshPoint>comparedPoints = transformedFacet.getVertices();
+        double meanD = 0;
+        double countOfNotNullPoints = 0;
+
+        List<Point3d>centers = computeCenterBothFacets(nearestPoints, comparedPoints);
+        Point3d mainCenter = centers.get(0);
+        Point3d comparedCenter = centers.get(1);
+
+        Matrix4d sumMatrix = new Matrix4d();
+        Matrix4d multipleMatrix = new Matrix4d();
+
+        for(int i = 0; i < comparedPoints.size(); i++) {
+            if (nearestPoints.get(i) == null){
+                continue;
+            }
+            // START computing Translation coordinates
+            meanD += distances.get(i);
+
+            Point3d relativeC = relativeCoordinate(comparedPoints.get(i).getPosition(),comparedCenter);
+            Point3d relativeN = relativeCoordinate(nearestPoints.get(i),mainCenter);
+
+            // START computing Rotation parameters
+            multipleMatrix.mulTransposeLeft(sumMatrixComp(relativeC), sumMatrixMain(relativeN));
+            sumMatrix.add(multipleMatrix);
+
+            countOfNotNullPoints ++;
+        }
+
+        meanD /= countOfNotNullPoints;
+
+        Vector3d translation = new Vector3d(
+                mainCenter.x - comparedCenter.x,
+                mainCenter.y - comparedCenter.y, 
+                mainCenter.z - comparedCenter.z);
+
+        // END computing translation parameter
+
+        Quaternion q = new Quaternion(new EigenvalueDecomposition(sumMatrix));
+        q.normalize();
+        // END computing rotation parameter
+
+        //computing SCALE parameter
+        double scaleFactor = 0;
+        if (scale) {
+            double sxUp = 0;
+            double sxDown = 0;
+            Matrix4d rotationMatrix = q.toMatrix();
+            for (int i = 0; i < nearestPoints.size(); i++) {
+                if(nearestPoints.get(i) == null) {
+                    continue;
+                }
+
+                Matrix4d matrixPoint = pointToMatrix(relativeCoordinate(nearestPoints.get(i), mainCenter));
+                Matrix4d matrixPointCompare = pointToMatrix(relativeCoordinate(comparedPoints.get(i).getPosition(),comparedCenter));
+
+                matrixPointCompare.mul(rotationMatrix);
+                
+                matrixPoint.mulTransposeLeft(matrixPoint, matrixPointCompare);
+                matrixPointCompare.mulTransposeLeft(matrixPointCompare, matrixPointCompare);
+
+                sxUp += matrixPoint.getElement(0, 0);
+                sxDown += matrixPointCompare.getElement(0,0);
+            }
+
+            scaleFactor = sxUp / sxDown;
+
+        } // end computing scale parameter
+
+        return new IcpTransformation(translation, q, scaleFactor, meanD);
+    }
+
+    /**
+     * Apply computed transformation to compared facet.
+     *
+     * @param transformedFacet Facet to be transformed
+     * @param transformation Computed transformation.
+     */
+    private void applyTransformation(MeshFacet transformedFacet, IcpTransformation transformation) {
+        transformedFacet.getVertices().parallelStream().forEach(
+                p -> {
+                    p.setPosition(transformation.transformPoint(p.getPosition(), scale));
+                }
+        );
+    }
+
+    /**
+     * Compute center of both given objects which are represents by list of Vector3d.
+     * Return list of two centers points.
+     *
+     * @param nearestPoints list of the nearest neighbours
+     * @param comparedPoints list fo compared points
+     * @return List with two points. The first one represents center of main facet
+     * and the second one represents center of compared facet.
+     */
+    private List<Point3d> computeCenterBothFacets(List<Point3d> nearestPoints, List<MeshPoint> comparedPoints) {
+        double xN = 0;
+        double yN = 0;
+        double zN = 0;
+
+        double xC = 0;
+        double yC = 0;
+        double zC = 0;
+
+        int countOfNotNullPoints = 0;
+        List<Point3d> result = new ArrayList<>(2);
+
+        for (int i = 0; i < nearestPoints.size(); i++) {
+
+            if(nearestPoints.get(i) == null){
+                continue;
+            }
+
+            xN += nearestPoints.get(i).x;
+            yN += nearestPoints.get(i).y;
+            zN += nearestPoints.get(i).z;
+
+            xC += comparedPoints.get(i).getPosition().x;
+            yC += comparedPoints.get(i).getPosition().y;
+            zC += comparedPoints.get(i).getPosition().z;
+
+            countOfNotNullPoints ++;
+        }
+        result.add(new Point3d(xN/countOfNotNullPoints, yN/countOfNotNullPoints, zN/countOfNotNullPoints));
+        result.add(new Point3d(xC/countOfNotNullPoints, yC/countOfNotNullPoints, zC/countOfNotNullPoints));
+        return result;
+    }
+
+    /**
+     * Compute relative coordinate of given point according to given center.
+     * Relative coordinates represents distance from the center of the mesh to vertex.
+     *
+     * @param p Point of which relative coordinates we want to be computed.
+     * @param center Vector3d which represents center of object.
+     * @return Vector3d which represents coordinates of new point according to center.
+     */
+    private Point3d relativeCoordinate(Point3d p, Point3d center) {
+        return new Point3d(p.x - center.x, p.y - center.y, p.z - center.z);
+    }
+
+    /**
+     * Compute sum matrix of given point. Given point represents compared point.
+     *
+     * @param p Compared point
+     * @return Sum matrix of given point
+     */
+    private Matrix4d sumMatrixComp(Point3d p) {
+        return new Matrix4d(
+                0,   -p.x, -p.y, -p.z,
+                p.x,  0,    p.z, -p.y,
+                p.y, -p.z,  0,    p.x,
+                p.z,  p.y, -p.x,  0);
+    }
+    /**
+     * Compute sum matrix of given point. Given point is point from main facet.
+     *
+     * @param p Compared point
+     * @return Sum matrix of given point
+     */
+    private Matrix4d sumMatrixMain(Point3d p) {
+        return new Matrix4d(
+                0,   -p.x, -p.y, -p.z,
+                p.x,  0,   -p.z,  p.y,
+                p.y,  p.z,  0,   -p.x,
+                p.z, -p.y,  p.x,  0);
+    }
+
+    /**
+     * Convert point (Vector3d) to matrix(Matrix4d).
+     *
+     * @param p Point, we want to be converted.
+     * @return Matrix of point.
+     */
+    private Matrix4d pointToMatrix(Point3d p){
+        return new Matrix4d(
+                p.x, p.y, p.z, 1,
+                0,   0,   0,   0, 
+                0,   0,   0,   0,
+                0,   0,   0,   0);
+    }
+
+    
+}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/icp/NoUndersampling.java b/Comparison/src/main/java/cz/fidentis/analyst/icp/NoUndersampling.java
new file mode 100644
index 0000000000000000000000000000000000000000..c32c1109bc3c5e427ba912f61b40105ab1c89556
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/icp/NoUndersampling.java
@@ -0,0 +1,22 @@
+package cz.fidentis.analyst.icp;
+
+import cz.fidentis.analyst.mesh.core.MeshPoint;
+import java.util.List;
+
+/**
+ * No undersampling. The triangular mesh keeps unchanged.
+ * 
+ * @author Radek Oslejsek
+ */
+public class NoUndersampling extends UndersamplingStrategy {
+    
+    @Override
+    public List<MeshPoint> reduceMeshVertices(List<MeshPoint> meshPoints) {
+        return meshPoints;
+    }
+ 
+    @Override
+    public String toString() {
+        return "no undersampling";
+    }
+}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/icp/Quaternion.java b/Comparison/src/main/java/cz/fidentis/analyst/icp/Quaternion.java
new file mode 100644
index 0000000000000000000000000000000000000000..0e7c603ab5340d1dad0256d891a85a399f1893fe
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/icp/Quaternion.java
@@ -0,0 +1,110 @@
+package cz.fidentis.analyst.icp;
+
+import javax.vecmath.Matrix4d;
+import javax.vecmath.Quat4d;
+
+/**
+ * This class represents quaternions. 
+ * Primary, it fixes the error (?) in the {@code Quat4d} constructor, which normalizes
+ * the given coordinates for some reason. Moreover, this extension
+ * introduces useful methods that accelerate the ICP calculation a bit.
+ *
+ * @author Maria Kocurekova
+ */
+public final class Quaternion extends Quat4d {
+    
+    /**
+     * Builds a quaternion from its components.
+     *
+     * @param w Scalar component.
+     * @param x First vector component.
+     * @param y Second vector component.
+     * @param z Third vector component.
+     */
+    public Quaternion(double x, double y, double z, double w) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+        this.w = w;
+    }
+    
+    /**
+     * Builds a quaternion from eigenvalue decomposition.
+     * 
+     * @param ev eigenvalue decomposition.
+     */
+    public Quaternion(EigenvalueDecomposition ev) {
+        Matrix4d eigD = ev.getD();
+        Matrix4d eigM = ev.getV();
+        int max = 0;
+
+        //Finding quaternion q representing the rotation
+        // (it is the eigenvector corresponding to the largest eigenvalue of sumMatrix)
+        for (int i = 0; i < 4; i++) {
+            if (eigD.getElement(max, max) <= eigD.getElement(i, i)) {
+                max = i;
+            }
+        }
+        
+        this.x = eigM.getElement(1, max);
+        this.y = eigM.getElement(2, max);
+        this.z = eigM.getElement(3, max);
+        this.w = eigM.getElement(0, max);
+    }
+
+    /**
+     * Returns the conjugate quaternion of the instance.
+     * It method is equivalent to calling the {@link #conjugate} method, 
+     * but it is more effective and readable when the origin quaternion has to be preserved.
+     *
+     * @return the conjugate quaternion
+     */
+    public Quaternion getConjugate() {
+        return new Quaternion(-x, -y, -z, w);
+    }
+
+    /**
+     * Returns the Hamilton product of two quaternions.
+     * It is equivalent to {@code q1.mul(q2)} of {@code Quat4d}.
+     * But calling this method it is faster and more readable if the first quaternion 
+     * has to be preserved (and then cloned first).
+     *
+     * @param q1 First quaternion.
+     * @param q2 Second quaternion.
+     * @return the Hamilton product of two quaternions
+     */
+    public static Quaternion multiply(final Quaternion q1, final Quaternion q2) {
+        final double w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z;
+        final double x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y;
+        final double y = q1.w * q2.y - q1.x * q2.z + q1.y * q2.w + q1.z * q2.x;
+        final double z = q1.w * q2.z + q1.x * q2.y - q1.y * q2.x + q1.z * q2.w;
+        return new Quaternion(x, y, z, w);
+    }
+
+    /**
+     * Convert a Quaternion to a rotation matrix. 
+     * It is equivalent to but bit faster than calling 
+     * {@code new Matrix4d(quternion, new Vector3d(0,0,0), 1);}
+     *
+     * @return a rotation matrix (4x4)
+     */
+    public Matrix4d toMatrix(){
+        double xx = x * x;
+        double xy = x * y;
+        double xz = x * z;
+        double xw = x * w;
+        double yy = y * y;
+        double yz = y * z;
+        double yw = y * w;
+        double zz = z * z;
+        double zw = z * w;
+
+        return new Matrix4d(
+                1 - 2 * ( yy + zz ), 2 * ( xy + zw),      2 * ( xz - yw),      0,
+                2 * ( xy - zw ),     1 - 2 * ( xx + zz ), 2 * ( yz + xw ),     0,
+                2 * ( xz + yw ),     2 * ( yz - xw ),     1 - 2 * ( xx + yy ), 0,
+                0,                   0,                   0,                   1
+        );
+    }
+
+}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/icp/RandomStrategy.java b/Comparison/src/main/java/cz/fidentis/analyst/icp/RandomStrategy.java
new file mode 100644
index 0000000000000000000000000000000000000000..961b880770a4998e736e20c2c8d7181f1f456dd6
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/icp/RandomStrategy.java
@@ -0,0 +1,78 @@
+package cz.fidentis.analyst.icp;
+
+import cz.fidentis.analyst.mesh.core.MeshPoint;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+/**
+ * Random undersampling when the mesh vertices to be removed are selected randomly.
+ * 
+ * @author Radek Oslejsek
+ */
+public class RandomStrategy extends UndersamplingStrategy {
+    
+    /**
+     * Constructor for PERCENTAGE undersampling type.
+     * 
+     * @param perc Percentage - a value in (0.0, 1.0&gtl
+     * @throws IllegalArgumentException if the input parameter is wrong
+     */
+    public RandomStrategy(double perc) {
+        super(perc);
+    }
+    
+    /**
+     * Constructor for PERCENTAGE undersampling type.
+     * 
+     * @param max Maximal number of vertices. Must be bigger than zero
+     * @throws IllegalArgumentException if the input parameter is wrong
+     */
+    public RandomStrategy(int max) {
+        super(max);
+    }
+
+    @Override
+    public List<MeshPoint> reduceMeshVertices(List<MeshPoint> meshPoints) {
+        if (meshPoints == null) {
+            return null;
+        }
+        
+        int maxVertices = getMaxVertices(meshPoints.size());
+        
+        if (meshPoints.size() <= maxVertices) {
+            return meshPoints;
+        }
+        
+        
+        // generate randomly ordered indexes:
+        List<Integer> range = IntStream.range(0, meshPoints.size()).boxed().collect(Collectors.toCollection(ArrayList::new));
+        Collections.shuffle(range);
+        
+        if (maxVertices < meshPoints.size()/2) { // copy indices
+            MeshPoint[] array = new MeshPoint[meshPoints.size()];
+            range.stream().limit(maxVertices).forEach(
+                    i -> array[i] = meshPoints.get(i)
+            );
+            return Arrays.stream(array).filter(
+                    p -> p != null
+            ).collect(Collectors.<MeshPoint>toList());
+        } else { // remove indices
+            List<MeshPoint> copy = new ArrayList<>(meshPoints);
+            range.stream().limit(meshPoints.size()-maxVertices).forEach(
+                    i -> copy.set(i, null)
+            );
+            return copy.parallelStream().filter(
+                    p -> p != null
+            ).collect(Collectors.<MeshPoint>toList());
+        }
+    }
+    
+    @Override
+    public String toString() {
+        return "random " + super.toString();
+    }
+}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/icp/UndersampledMeshFacet.java b/Comparison/src/main/java/cz/fidentis/analyst/icp/UndersampledMeshFacet.java
new file mode 100644
index 0000000000000000000000000000000000000000..cfc107929215cadbd1788f84644b6a5f89a94894
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/icp/UndersampledMeshFacet.java
@@ -0,0 +1,161 @@
+package cz.fidentis.analyst.icp;
+
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
+import cz.fidentis.analyst.mesh.core.MeshPoint;
+import cz.fidentis.analyst.mesh.core.MeshTriangle;
+import cz.fidentis.analyst.mesh.core.TriangleFan;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import javax.vecmath.Point3d;
+
+/**
+ * Fast adapter to the MeshFacet which reduces number of vertices used for the ICP computation.
+ * The reduction is driven by the undersampling strategy. The most of the original 
+ * MeshFacet methods are not usable anymore.
+ * 
+ * @author Radek Oslejsek
+ */
+public class UndersampledMeshFacet extends MeshFacetImpl {
+    
+    private final List<MeshPoint> reducedVertices;
+    
+    /**
+     * Constructor.
+     * 
+     * @param origFacet Original facet
+     * @param strategy Undersampling strategy
+     */
+    public UndersampledMeshFacet(MeshFacet origFacet, UndersamplingStrategy strategy) {
+        if (origFacet == null) {
+            throw new IllegalArgumentException("origFacet");
+        }
+        
+        if (strategy == null) {
+            throw new IllegalArgumentException("strategy");
+        }
+        
+        this.reducedVertices = strategy.reduceMeshVertices(origFacet.getVertices());
+    }
+    
+    @Override
+    public MeshPoint getVertex(int index) {
+        return reducedVertices.get(index);
+    }
+
+    /**
+     * This method is not supported.
+     * 
+     * @param point Mesh point
+     */
+    @Override
+    public void addVertex(MeshPoint point) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getNumberOfVertices() {
+        return reducedVertices.size();
+    }
+
+    @Override
+    public List<MeshPoint> getVertices() {
+        return Collections.unmodifiableList(reducedVertices);
+    }
+
+    /**
+     * This method is not supported
+     */
+    @Override
+    public synchronized void calculateVertexNormals() {
+       throw new UnsupportedOperationException();
+    }
+    
+    /**
+     * This method is not supported
+     * @return 
+     */
+    @Override
+    public int getNumTriangles() {
+        throw new UnsupportedOperationException();
+    }
+    
+    /**
+     * This method is not supported
+     */
+    @Override
+    public List<MeshTriangle> getTriangles() {
+        throw new UnsupportedOperationException();
+    }
+    
+    /**
+     * This method is not supported
+     * @param vertexIndex
+     * @return
+     */
+    @Override
+    public List<MeshTriangle> getAdjacentTriangles(int vertexIndex) {
+        throw new UnsupportedOperationException();
+    }
+    
+    /**
+     * This method is not supported
+     * @param point
+     * @param vertexIndex
+     * @return 
+     */
+    @Override
+    public Point3d getClosestAdjacentPoint(Point3d point, int vertexIndex) {
+        throw new UnsupportedOperationException();
+    }
+    
+    /**
+     * This method is not supported
+     * @param point
+     * @param vertexIndex
+     * @return 
+     */
+    @Override
+    public double curvatureDistance(Point3d point, int vertexIndex) {
+        throw new UnsupportedOperationException();
+    }
+    
+    /**
+     * This method is not supported
+     * @return 
+     */
+    @Override
+    public Iterator<MeshTriangle> iterator() {
+        throw new UnsupportedOperationException();
+    }
+    
+    /**
+     * This method is not supported
+     * @return 
+     */
+    @Override
+    public List<Point3d> calculateVoronoiPoints() {
+        throw new UnsupportedOperationException();
+    }
+    
+    /**
+     * This method is not supported
+     * @param vertexIndex
+     * @return 
+     */
+    @Override
+    public TriangleFan getOneRingNeighborhood(int vertexIndex) {
+        throw new UnsupportedOperationException();
+    }
+    
+    /**
+     * This method is not supported
+     * @return 
+     */
+    @Override
+    public boolean simplify() {
+        throw new UnsupportedOperationException();
+    }
+    
+}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/icp/UndersamplingStrategy.java b/Comparison/src/main/java/cz/fidentis/analyst/icp/UndersamplingStrategy.java
new file mode 100644
index 0000000000000000000000000000000000000000..e0d9b0692bafee98b6ee4335d78ae0ae910d0aec
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/icp/UndersamplingStrategy.java
@@ -0,0 +1,99 @@
+package cz.fidentis.analyst.icp;
+
+import cz.fidentis.analyst.mesh.core.MeshPoint;
+import java.util.List;
+
+/**
+ * Undersampling strategies used to reduce the size of triangle meshes and then 
+ * accelerate ICP computation.
+ * 
+ * @author Radek Oslejsek
+ */
+public abstract class UndersamplingStrategy {
+    
+    /**
+     * If undersamoling is used, then this configuration parameter 
+     * encodes whether the reduction of mesh size is expressed as the percentage 
+     * of the original size (number of vertices) or as the maximal number of vertices
+     * to be used.
+     * 
+     * @author Radek Oslejsek
+     */
+    public enum UndersamplingType {
+        PERCENTAGE,
+        MAX_VERTICES
+    };
+    
+    private final UndersamplingType undersamplingType;
+    private final double undersamplingLimit;
+    
+    /** 
+     * Constructor for no undersampling.
+     */
+    public UndersamplingStrategy() {
+        this.undersamplingType = null;
+        this.undersamplingLimit = 0.0;
+    }
+    
+    /**
+     * Constructor for PERCENTAGE undersampling type.
+     * 
+     * @param perc Percentage - a value in (0.0, 1.0&gt;
+     * @throws IllegalArgumentException if the input parameter is wrong
+     */
+    public UndersamplingStrategy(double perc) {
+        if (perc <= 0.0 || perc > 1) {
+            throw new IllegalArgumentException("perc");
+        }
+        this.undersamplingType = UndersamplingType.PERCENTAGE;
+        this.undersamplingLimit = perc;
+    }
+    
+    /**
+     * Constructor for PERCENTAGE undersampling type.
+     * 
+     * @param max Maximal number of vertices. Must be bigger than zero
+     * @throws IllegalArgumentException if the input parameter is wrong
+     */
+    public UndersamplingStrategy(int max) {
+        if (max <= 0) {
+            throw new IllegalArgumentException("max");
+        }
+        this.undersamplingType = UndersamplingType.MAX_VERTICES;
+        this.undersamplingLimit = max;
+    }
+    
+    /**
+     * Reduces mesh points.
+     * 
+     * @param meshPoints Original list of mesh points
+     * @return Reduced list of mesh points or {@code null}.
+     */
+    public abstract List<MeshPoint> reduceMeshVertices(List<MeshPoint> meshPoints);
+    
+    @Override
+    public String toString() {
+        if (this.undersamplingType == UndersamplingType.PERCENTAGE) {
+            return "undersampling to " + (undersamplingLimit * 100) + "%";
+        } else {
+            return "undersampling to " + undersamplingLimit + " vertices";
+        }
+    }
+    
+    /**
+     * Returns number of vertices to be returned after undersampling.
+     * 
+     * @param origVertices Original number of vertices
+     * @return number of vertices to be returned after undersampling.
+     */
+    protected int getMaxVertices(int origVertices) {
+        switch (this.undersamplingType) {
+            case PERCENTAGE:
+                return (int) (origVertices * this.undersamplingLimit);
+            case MAX_VERTICES:
+                return Math.max((int) this.undersamplingLimit, origVertices);
+            default:
+                return 0;
+        }
+    }
+}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/ApproxSymmetryPlane.java b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/ApproxSymmetryPlane.java
index 43fbfaad022f877192ae3eeedc7d97dcdadd7f0f..53304801656eb1ac98413f70db804bebf0b34100 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/ApproxSymmetryPlane.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/ApproxSymmetryPlane.java
@@ -24,7 +24,7 @@ public class ApproxSymmetryPlane extends Plane implements Comparable<ApproxSymme
      * @param maxDist Distance limit
      * @throws UnsupportedOperationException if the symmetry plane cannot be created
      */
-    public ApproxSymmetryPlane(SignificantPoints sigPoints, Config config, int i, int j, double maxDist) throws UnsupportedOperationException {
+    public ApproxSymmetryPlane(SignificantPoints sigPoints, SymmetryConfig config, int i, int j, double maxDist) throws UnsupportedOperationException {
         if (i == j) {
             throw new UnsupportedOperationException();
         }
@@ -41,7 +41,7 @@ public class ApproxSymmetryPlane extends Plane implements Comparable<ApproxSymme
         return votes;
     }
     
-    private void setNormAndDist(SignificantPoints sigPoints, Config config, int i, int j) {
+    private void setNormAndDist(SignificantPoints sigPoints, SymmetryConfig config, int i, int j) {
         MeshFacet facetI = sigPoints.getMeshFacet(i);
         MeshFacet facetJ = sigPoints.getMeshFacet(j);
         int sigPointI = sigPoints.getVertexIndex(i);
@@ -81,7 +81,7 @@ public class ApproxSymmetryPlane extends Plane implements Comparable<ApproxSymme
      * @param config Symmetry plane configuration
      * @param maxDist Distance limit
      */
-    private void computeVotes(SignificantPoints sigPoints, Config config, double maxDist) {
+    private void computeVotes(SignificantPoints sigPoints, SymmetryConfig config, double maxDist) {
         normalize();
         Vector3d normal = getNormal();
         double d = getDistance();
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/CurvatureAlg.java b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/CurvatureAlg.java
new file mode 100644
index 0000000000000000000000000000000000000000..64eabced06338550c08014ce6b4ca0dae8b862a3
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/CurvatureAlg.java
@@ -0,0 +1,13 @@
+package cz.fidentis.analyst.symmetry;
+
+/**
+ * Curvature algorithm used for the selection of the top X significant points.
+ * 
+ * @author Radek Oslejsek
+ */
+public enum CurvatureAlg {
+    MEAN,
+    GAUSSIAN,
+    MAX,
+    MIN
+}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SignificantPoints.java b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SignificantPoints.java
index cee086f5094b1902c5fe24f9d42a58a49cab19f0..1aa8bceb697b75e943b69606835622c254c809b5 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SignificantPoints.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SignificantPoints.java
@@ -24,17 +24,6 @@ import javax.vecmath.Vector3d;
  */
 public class SignificantPoints extends MeshVisitor {
     
-    /**
-     * Curvature algorithm used for the selection of the top X significant points.
-     * @author Radek Oslejsek
-     */
-    public enum CurvatureAlg {
-        MEAN,
-        GAUSSIAN,
-        MAX,
-        MIN
-    };
-    
     private final int maxPoints;
     
     private final Curvature curvatureVisitor;
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/Config.java b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryConfig.java
similarity index 75%
rename from Comparison/src/main/java/cz/fidentis/analyst/symmetry/Config.java
rename to Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryConfig.java
index 22af1f4e0b03bba086409d3f812b48a26987ba7a..bb4d0482a5cb2cb8846951f26da5b05e156c5509 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/Config.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryConfig.java
@@ -8,13 +8,15 @@ package cz.fidentis.analyst.symmetry;
  * 
  * @author Natalia Bebjakova
  */
-public class Config {
+public class SymmetryConfig {
+    
     private static final double DEFAULT_MIN_CURV_RATIO = 0.5;
     private static final double DEFAULT_MIN_ANGLE_COS = 0.985;
     private static final double DEFAULT_MIN_NORM_ANGLE_COS = 0.985;
     private static final double DEFAULT_MAX_REL_DISTANCE = 1.0 / 100.0;
     private static final int DEFAULT_SIGNIFICANT_POINT_COUNT = 200;
     private static final boolean DEFAULT_AVERAGING = true;
+    private static final CurvatureAlg DEFAULT_CURVATURE_ALGORITHM = CurvatureAlg.GAUSSIAN;
     
     private double minCurvRatio;
     private double minAngleCos;
@@ -22,6 +24,44 @@ public class Config {
     private double maxRelDistance;
     private int significantPointCount;
     private boolean averaging;
+    private CurvatureAlg curvatureAlg;
+    
+    /**
+     * Creates configuration with default values 
+     */
+    public SymmetryConfig() {
+        minCurvRatio = DEFAULT_MIN_CURV_RATIO;
+        minAngleCos = DEFAULT_MIN_ANGLE_COS;
+        minNormAngleCos = DEFAULT_MIN_NORM_ANGLE_COS;
+        maxRelDistance = DEFAULT_MAX_REL_DISTANCE;
+        significantPointCount = DEFAULT_SIGNIFICANT_POINT_COUNT;
+        averaging = DEFAULT_AVERAGING;
+        curvatureAlg = DEFAULT_CURVATURE_ALGORITHM;
+    }
+    
+    /**
+     * Copy constructor.
+     * 
+     * @param conf Original configuration
+     */
+    public SymmetryConfig(SymmetryConfig conf) {
+        copy(conf);
+    }
+    
+    /**
+     * Copies values from another configuration object.
+     * 
+     * @param conf Another configuration
+     */
+    public void copy(SymmetryConfig conf) {
+        minCurvRatio = conf.minCurvRatio;
+        minAngleCos = conf.maxRelDistance;
+        minNormAngleCos = conf.minNormAngleCos;
+        maxRelDistance = conf.maxRelDistance;
+        significantPointCount = conf.significantPointCount;
+        averaging = conf.averaging;
+        curvatureAlg = conf.curvatureAlg;
+    }
     
     /**
      * Parameter which denotes how similar the Gaussian curvatures in the two vertices
@@ -134,25 +174,23 @@ public class Config {
     public void setAveraging(boolean averaging) {
         this.averaging = averaging;
     }
-
+    
     /**
-     * Creates new configuration with default values 
-     * 
-     * @return configuration with default values
+     * Returns curvature algorithm.
+     * @return curvature algorithm 
      */
-    public static Config getDefault() {
-        Config conf = new Config();
-
-        conf.minCurvRatio = DEFAULT_MIN_CURV_RATIO;
-        conf.minAngleCos = DEFAULT_MIN_ANGLE_COS;
-        conf.minNormAngleCos = DEFAULT_MIN_NORM_ANGLE_COS;
-        conf.maxRelDistance = DEFAULT_MAX_REL_DISTANCE;
-        conf.significantPointCount = DEFAULT_SIGNIFICANT_POINT_COUNT;
-        conf.averaging = DEFAULT_AVERAGING;
-
-        return conf;
+    public CurvatureAlg getCurvatureAlg() {
+        return this.curvatureAlg;
     }
     
+    /**
+     * Sets  curvature algorithm.
+     * @param alg curvature algorithm
+     */
+    public void setCurvatureAlg(CurvatureAlg alg) {
+        this.curvatureAlg = alg;
+    }
+
     /**
      * 
      * @return String representation of configuration
@@ -167,6 +205,7 @@ public class Config {
         str += "Max relative distance: " + maxRelDistance + "\n";
         str += "Significant points: " + significantPointCount + "\n";
         str += "Averaging: " + averaging + "\n";
+        str += "Curvature: " + curvatureAlg + "\n";
         return str;
     }
 }
\ No newline at end of file
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java
index 9ade7e71c17683bfa463bd41f83df2da288ecc39..4a2b0cc77c9a926c53f5bfd62e44bdc32100a8ad 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java
@@ -5,10 +5,8 @@ import cz.fidentis.analyst.mesh.core.CornerTableRow;
 import cz.fidentis.analyst.mesh.core.MeshFacet;
 import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
 import cz.fidentis.analyst.mesh.core.MeshPointImpl;
-import cz.fidentis.analyst.symmetry.SignificantPoints.CurvatureAlg;
 import cz.fidentis.analyst.visitors.mesh.BoundingBox;
 import cz.fidentis.analyst.visitors.mesh.BoundingBox.BBox;
-import cz.fidentis.analyst.visitors.mesh.Curvature;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Callable;
@@ -36,28 +34,24 @@ import javax.vecmath.Vector3d;
  */
 public class SymmetryEstimator extends MeshVisitor {
     
-    private final Config config;
+    private final SymmetryConfig config;
     private final SignificantPoints sigPointsVisitor;
     private final BoundingBox bbVisitor = new BoundingBox();
     
-    private CurvatureAlg curvatureAlg;
-    
     private Plane symmetryPlane;
     
     /**
      * Constructor.
      * 
      * @param config Algorithm options
-     * @param curvatureAlg Curvature algorithm used for the selection of significant points.
-     *        See {@link Curvature} for more details.
      * @throws IllegalArgumentException if some input parameter is missing
      */
-    public SymmetryEstimator(Config config, CurvatureAlg curvatureAlg) {
+    public SymmetryEstimator(SymmetryConfig config) {
         if (config == null) {
             throw new IllegalArgumentException("config");
         }
         this.config = config;
-        this.sigPointsVisitor = new SignificantPoints(curvatureAlg, config.getSignificantPointCount());
+        this.sigPointsVisitor = new SignificantPoints(config.getCurvatureAlg(), config.getSignificantPointCount());
     }
     
     @Override
@@ -78,8 +72,9 @@ public class SymmetryEstimator extends MeshVisitor {
     }
     
     /**
-     * Computes the symmetry plane concurrently. The plane is computed only once, 
-     * then the same instance is returned.
+     * Computes the symmetry plane concurrently.The plane is computed only once, then the same instance is returned.
+     * 
+     * @return Symmetry plane
      */
     public Plane getSymmetryPlane() {
         return getSymmetryPlane(true);
@@ -115,34 +110,38 @@ public class SymmetryEstimator extends MeshVisitor {
         Vector3d normal = symmetryPlane.getNormal();
         Point3d midPoint = bbox.getMidPoint();
 
-        double alpha = -((normal.x * midPoint.x) + 
-                (normal.y * midPoint.y) + (normal.z * midPoint.z) +
-                symmetryPlane.getDistance()) / (normal.dot(normal));
+        double alpha = 
+                -((normal.x * midPoint.x) + 
+                  (normal.y * midPoint.y) + 
+                  (normal.z * midPoint.z) +
+                  symmetryPlane.getDistance()) / (normal.dot(normal));
         
         Point3d midPointOnPlane = new Point3d(midPoint);
         Vector3d nn = new Vector3d(normal);
         nn.scale(alpha);
         midPointOnPlane.add(nn);
 
-        double val = normal.x * midPointOnPlane.x + normal.y *
-                midPointOnPlane.y + normal.z *
-                midPointOnPlane.z + symmetryPlane.getDistance();
+        double val = 
+                normal.x * midPointOnPlane.x + 
+                normal.y * midPointOnPlane.y + 
+                normal.z * midPointOnPlane.z + 
+                symmetryPlane.getDistance();
 
-        Vector3d a = new Vector3d();
+        Vector3d frontDir = new Vector3d();
         if (Math.abs(normal.dot(new Vector3d(0.0, 1.0, 0.0))) > Math.abs(normal.dot(new Vector3d (1.0, 0.0, 0.0)))) {
-            a.cross(normal, new Vector3d(1.0, 0.0, 0.0));
+            frontDir.cross(normal, new Vector3d(1.0, 0.0, 0.0));
         } else {
-            a.cross(normal, new Vector3d(0.0, 1.0, 0.0));
+            frontDir.cross(normal, new Vector3d(0.0, 1.0, 0.0));
         }
-        a.normalize();
+        frontDir.normalize();
 
-        Vector3d b = new Vector3d();
-        b.cross(normal,a);
-        b.normalize();
+        Vector3d upDir = new Vector3d();
+        upDir.cross(normal,frontDir);
+        upDir.normalize();
         
         double scale = bbox.getMaxPoint().x - bbox.getMinPoint().x;
         
-        return createMeshFacet(midPointOnPlane, a, b, symmetryPlane.getNormal(), scale);
+        return createMeshFacet(midPointOnPlane, frontDir, upDir, symmetryPlane.getNormal(), scale);
     }
     
     /**
@@ -231,11 +230,12 @@ public class SymmetryEstimator extends MeshVisitor {
         setSymmetryPlane(planes);
     }
     
-    protected static MeshFacet createMeshFacet(Point3d centroid, Vector3d a, Vector3d b, Vector3d normal, double scale) {
+    protected static MeshFacet createMeshFacet(Point3d centroid, Vector3d frontDir, Vector3d upDir, Vector3d normal, double scale) {
+        
         Point3d[] points = new Point3d[4];
         
-        Point3d aScaled = new Point3d(a);
-        Point3d bScaled = new Point3d(b);
+        Point3d aScaled = new Point3d(frontDir);
+        Point3d bScaled = new Point3d(upDir);
         aScaled.scale(scale);
         bScaled.scale(scale);
         
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/face/HausdorffDistancePrioritized.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/face/HausdorffDistancePrioritized.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d2ccb68250f1d628c034be348ed6529a64d7855
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/face/HausdorffDistancePrioritized.java
@@ -0,0 +1,437 @@
+package cz.fidentis.analyst.visitors.face;
+
+import cz.fidentis.analyst.face.HumanFace;
+import cz.fidentis.analyst.feature.FeaturePoint;
+import cz.fidentis.analyst.feature.FeaturePointType;
+import cz.fidentis.analyst.kdtree.KdTree;
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshModel;
+import cz.fidentis.analyst.visitors.mesh.HausdorffDistance;
+import cz.fidentis.analyst.visitors.mesh.HausdorffDistance.Strategy;
+import cz.fidentis.analyst.visitors.mesh.PrioritySphere;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.IntStream;
+import javax.vecmath.Point3d;
+
+/**
+ * Visitor for prioritized Hausdorff distance with respect to the given types of feature points.
+ * 
+ * The visitor computes the following:
+ * <ul>
+ *   <li>Hausdorff distance</li>
+ *   <li>Priorities of the faces' vertices with respect to the given types of feature
+ *       points separately</li>
+ *   <li>Priorities of the faces' vertices with respect to all the given types
+ *       of feature points merged together</li>
+ *   <li>Weighted average of Hausdorff distance of all vertices within the priority sphere
+ *       of feature points of the given types for each of the faces' mesh facets</li>
+ * </ul>
+ * This visitor is instantiated with a single k-d tree (either given as the input
+ * parameter, or automatically created from the triangular mesh).
+ * When applied to other human faces, it computes the Hausdorff distance from their mesh facets
+ * to the instantiated k-d tree.
+ * 
+ * <p>
+ * The Hausdorff distance is computed either as absolute or relative. Absolute
+ * represents Euclidean distance (all numbers are positive). On the contrary,
+ * relative distance considers orientation of the visited face's facets (determined by its normal vectors)
+ * and produces positive or negative distances depending on whether the primary
+ * mesh is "in front of" or "behind" the given vertex.
+ * </p>
+ * 
+ * <p>
+ * This visitor is thread-safe, i.e., a single instance of the visitor can be used
+ * to inspect multiple human faces simultaneously.
+ * </p>
+ * 
+ * @author Daniel Schramm
+ */
+public class HausdorffDistancePrioritized extends HumanFaceVisitor  {
+    
+    private final HausdorffDistance distanceVisitor;
+    
+    private final Map<FeaturePointType, Double> featurePointTypes;
+    
+    private final Map<HumanFace, Map<FeaturePointType, Map<MeshFacet, List<Double>>>> priorities = new HashMap<>();
+    private final Map<HumanFace, Map<FeaturePointType, Map<MeshFacet, Double>>> featurePointWeights = new HashMap<>();
+    private final Map<HumanFace, Map<MeshFacet, List<Double>>> mergedPriorities = new HashMap<>();
+    
+    /**
+     * Constructor.
+     * 
+     * @param mainFacets Facets to which distance from the visited human face's facets is to be computed.
+     * Must not be {@code null}.
+     * @param featurePoints Types of feature points according to which the Hausdorff distances will be prioritized
+     * together with the radii of priority spheres around the feature points of the corresponding type.
+     * Must not be {@code null}.
+     * @param strategy Strategy of the computation of distance
+     * @param relativeDistance If {@code true}, then the visitor calculates the relative distances with respect 
+     * to the normal vectors of source facets (normal vectors have to present),
+     * i.e., we can get negative distances.
+     * @param parallel If {@code true}, then the algorithm runs concurrently utilizing all CPU cores
+     * @throws IllegalArgumentException if some parameter is wrong
+     */
+    public HausdorffDistancePrioritized(Set<MeshFacet> mainFacets, Map<FeaturePointType, Double> featurePoints, Strategy strategy, boolean relativeDistance, boolean parallel) {
+        distanceVisitor = new HausdorffDistance(mainFacets, strategy, relativeDistance, parallel);
+        if (featurePoints == null) {
+            throw new IllegalArgumentException("featurePoints");
+        }
+        for (final Double radius: featurePoints.values()) {
+            if (radius == null || radius < 0) {
+                throw new IllegalArgumentException("featurePoints");
+            }
+        }
+        featurePointTypes = featurePoints;
+    }
+    
+    /**
+     * Constructor.
+     * 
+     * @param mainFacet Primary facet to which distance from the visited human face's facets is to be computed. Must not be {@code null}.
+     * @param featurePoints Types of feature points according to which the Hausdorff distances will be prioritized
+     * together with the radii of priority spheres around the feature points of the corresponding type.
+     * Must not be {@code null}.
+     * @param strategy Strategy of the computation of distance
+     * @param relativeDistance If {@code true}, then the visitor calculates the relative distances with respect 
+     * to the normal vectors of source facets (normal vectors have to present),
+     * i.e., we can get negative distances.
+     * @param parallel If {@code true}, then the algorithm runs concurrently utilizing all CPU cores
+     * @throws IllegalArgumentException if some parameter is wrong
+     */
+    public HausdorffDistancePrioritized(MeshFacet mainFacet, Map<FeaturePointType, Double> featurePoints, Strategy strategy, boolean relativeDistance, boolean parallel) {
+        this(new HashSet<>(Collections.singleton(mainFacet)), featurePoints, strategy, relativeDistance, parallel);
+    }
+    
+    /**
+     * Constructor.
+     * 
+     * @param mainModel The mesh model with primary facets to which distance from the visited human face's facets is to be computed.
+     * Must not be {@code null} or empty.
+     * @param featurePoints Types of feature points according to which the Hausdorff distances will be prioritized
+     * together with the radii of priority spheres around the feature points of the corresponding type.
+     * Must not be {@code null}.
+     * @param strategy Strategy of the computation of distance
+     * @param relativeDistance If {@code true}, then the visitor calculates the relative distances with respect 
+     * to the normal vectors of source facets (normal vectors have to present),
+     * i.e., we can get negative distances.
+     * @param parallel If {@code true}, then the algorithm runs concurrently utilizing all CPU cores
+     * @throws IllegalArgumentException if some parameter is wrong
+     */
+    public HausdorffDistancePrioritized(MeshModel mainModel, Map<FeaturePointType, Double> featurePoints, Strategy strategy, boolean relativeDistance, boolean parallel) {
+        this(new HashSet<>(mainModel.getFacets()), featurePoints, strategy, relativeDistance, parallel);
+    }
+    
+    /**
+     * Constructor.
+     * 
+     * @param face Human face to which distance from other human faces is to be computed. Must not be {@code null}.
+     * @param featurePoints Types of feature points according to which the Hausdorff distances will be prioritized
+     * together with the radii of priority spheres around the feature points of the corresponding type.
+     * Must not be {@code null}.
+     * @param strategy Strategy of the computation of distance
+     * @param relativeDistance If {@code true}, then the visitor calculates the relative distances with respect 
+     * to the normal vectors of source facets (normal vectors have to present),
+     * i.e., we can get negative distances.
+     * @param parallel If {@code true}, then the algorithm runs concurrently utilizing all CPU cores
+     * @throws IllegalArgumentException if some parameter is wrong
+     */
+    public HausdorffDistancePrioritized(HumanFace face, Map<FeaturePointType, Double> featurePoints, Strategy strategy, boolean relativeDistance, boolean parallel) {
+        this(face.getMeshModel(), featurePoints, strategy, relativeDistance, parallel);
+    }
+    
+    /**
+     * Constructor.
+     * 
+     * @param mainKdTree The KD tree to which distance from the visited human face's facets is to be computed.
+     * Must not be {@code null}.
+     * @param featurePoints Types of feature points according to which the Hausdorff distances will be prioritized
+     * together with the radii of priority spheres around the feature points of the corresponding type.
+     * Must not be {@code null}.
+     * @param strategy Strategy of the computation of distance
+     * @param relativeDistance If {@code true}, then the visitor calculates the relative distances with respect 
+     * to the normal vectors of source facets (normal vectors have to present),
+     * i.e., we can get negative distances.
+     * @param parallel If {@code true}, then the algorithm runs concurrently utilizing all CPU cores
+     * @throws IllegalArgumentException if some parameter is wrong
+     */
+    public HausdorffDistancePrioritized(KdTree mainKdTree, Map<FeaturePointType, Double> featurePoints, Strategy strategy, boolean relativeDistance, boolean parallel) {
+        distanceVisitor = new HausdorffDistance(mainKdTree, strategy, relativeDistance, parallel);
+        if (featurePoints == null) {
+            throw new IllegalArgumentException("featurePoints");
+        }
+        for (final Double radius: featurePoints.values()) {
+            if (radius == null || radius < 0) {
+                throw new IllegalArgumentException("featurePoints");
+            }
+        }
+        featurePointTypes = featurePoints;
+    }
+
+    /**
+     * Returns types of feature points according to which the computation of Hausdorff
+     * distance is prioritized together with the radii of priority spheres around
+     * the feature points of the corresponding type.
+     * 
+     * @return Types of feature points according to which the computation of Hausdorff
+     * distance is prioritized together with the radii of priority spheres around
+     * the feature points of the corresponding type
+     */
+    public Map<FeaturePointType, Double> getFeaturePointTypes() {
+        return Collections.unmodifiableMap(featurePointTypes);
+    }
+    
+    /**
+     * Returns Hausdorff distance of the visited faces' mesh facets to the source mesh facets. 
+     * 
+     * <p>
+     * Keys in the map contain mesh facets that were measured with the 
+     * source facets.<br>
+     * For each facet of the visited human face, a list of distances to the source 
+     * facets is stored. The order of distances corresponds to the order of vertices
+     * in the measured facet, i.e., the i-th value is the distance of the i-th vertex
+     * of the visited face's facet.
+     * </p>
+     * 
+     * @return Hausdorff distance for all points of all the visited human faces' facets
+     */
+    public Map<MeshFacet, List<Double>> getDistances() {
+        return distanceVisitor.getDistances();
+    }
+    
+    /**
+     * Returns the nearest points of the visited faces' mesh facets to the source mesh facets.
+     * 
+     * <p>
+     * Keys in the map contain mesh facets that were measured with the
+     * source facets.<br>
+     * For each facet of the visited human face, a list of the nearest points to the source
+     * facets is stored. The order of points corresponds to the order of vertices
+     * in the measured facet, i.e., the i-th point is the nearest point of the i-th vertex
+     * of the visited face's facet.
+     * </p>
+     *
+     * @return The nearest points for all points of all the visited human faces' facets
+     */
+    public Map<MeshFacet, List<Point3d>> getNearestPoints() {
+        return distanceVisitor.getNearestPoints();
+    }
+
+    /**
+     * Returns priorities of vertices of the visited faces' mesh facets with respect
+     * to the given types of feature points.
+     * Priorities are calculated for each type of feature point separately.
+     * 
+     * <p>
+     * Keys in the map contain human faces whose mesh facets were measured with the
+     * source facets.<br>
+     * For each human face, there is a map of examined types of feature points.<br>
+     * Each feature point type then stores a map of priorities of vertices
+     * of the face's mesh facets computed with respect to the face's feature point of
+     * the corresponding type.
+     * The order of priorities in the innermost map's value (list) corresponds to the order of vertices
+     * in its corresponding key (facet), i.e., the i-th value in the list is the priority of
+     * the i-th vertex of the facet.
+     * </p>
+     * 
+     * @return Priorities of vertices with respect to the given types of feature points
+     */
+    public Map<HumanFace, Map<FeaturePointType, Map<MeshFacet, List<Double>>>> getPriorities() {
+        return Collections.unmodifiableMap(priorities);
+    }
+
+    /**
+     * For all visited faces' mesh facets, the method returns the weighted average of Hausdorff distance
+     * of all vertices within the priority sphere of feature points of the given types
+     * (i.e. the sum of weighted distances of the mesh facet's vertices to the source facets
+     * divided by the sum of their priorities).
+     * The weighted average is calculated for each type of feature point separately.
+     * 
+     * <p>
+     * Keys in the map contain human faces whose mesh facets were measured with the
+     * source facets.<br>
+     * For each human face, there is a map of examined types of feature points.<br>
+     * Each feature point type then stores a map of the face's mesh facets together with
+     * the weighted average of distance of their vertices to the source facets.
+     * The weighted average of distance is calculated with respect to the face's feature point
+     * of the corresponding type.<br>
+     * <i>If there is no vertex within the priority sphere of a feature point,
+     * the value of the average weighted Hausdorff distance is {@link Double#NaN}</i>
+     * </p>
+     * 
+     * @return Weighted average of Hausdorff distance of all vertices within the priority sphere
+     *         of feature points of the given types
+     */
+    public Map<HumanFace, Map<FeaturePointType, Map<MeshFacet, Double>>> getFeaturePointWeights() {
+        return Collections.unmodifiableMap(featurePointWeights);
+    }
+
+    /**
+     * Returns priorities of vertices of the visited faces' mesh facets with respect
+     * to all the given types of feature points merged together.
+     * 
+     * <p>
+     * Keys in the map contain human faces whose mesh facets were measured with the
+     * source facets.<br>
+     * For each human face, there is a map of priorities of vertices of the visited
+     * face's mesh facets. The priorities are computed with respect to all the face's
+     * feature points of given types together.
+     * The order of priorities in the inner map's value (list) corresponds to the order of vertices
+     * in its corresponding key (facet), i.e., the i-th value in the list is the priority of
+     * the i-th vertex of the facet.
+     * </p>
+     * 
+     * @return Priorities of vertices with respect to all given types of feature
+     *         points merged together
+     */
+    public Map<HumanFace, Map<MeshFacet, List<Double>>> getMergedPriorities() {
+        return Collections.unmodifiableMap(mergedPriorities);
+    }
+
+    /**
+     * Returns {@code true} if the distance was computed as relative 
+     * (with possibly negative values). 
+     * 
+     * @return {@code true} if the distance is computed as relative, {@code false} otherwise
+     */
+    public boolean relativeDistance() {
+        return distanceVisitor.relativeDistance();
+    }
+    
+    /**
+     * Returns the strategy of the computation of distance.
+     * 
+     * @return Strategy of the computation of distance
+     */
+    public Strategy getStrategy() {
+        return distanceVisitor.getStrategy();
+    }
+    
+    /**
+     * Returns {@code true} if the distance computation is parallel.
+     * 
+     * @return {@code true} if the distance computation is parallel
+     */
+    public boolean inParallel() {
+        return distanceVisitor.inParallel();
+    }
+    
+    /**
+     * Return the KD tree to which distances are computed.
+     * 
+     * @return KD tree to which distances are computed
+     */
+    public KdTree getMainKdTree() {
+        return distanceVisitor.getMainKdTree();
+    }
+
+    @Override
+    public void visitHumanFace(HumanFace humanFace) {
+        // Compute the Hasudorff distance using the 'distanceVisitor'
+        humanFace.getMeshModel().compute(distanceVisitor, inParallel());
+
+        /*
+         * If there are no feature points to be computed
+         */
+        if (featurePointTypes.isEmpty()) {
+            final List<MeshFacet> faceFacets = humanFace.getMeshModel().getFacets();
+            final Map<MeshFacet, List<Double>> faceMergedPriorities = new HashMap<>(faceFacets.size());
+            for (final MeshFacet facet: faceFacets) {
+                faceMergedPriorities.put(facet, Collections.nCopies(facet.getNumberOfVertices(), 0d));
+            }
+
+            synchronized (this) {
+                priorities.put(humanFace, Map.of());
+                featurePointWeights.put(humanFace, Map.of());
+                mergedPriorities.put(humanFace, faceMergedPriorities);
+            }
+
+            return;
+        }
+        
+        /*
+         * Compute priorities of humanFace's vertices for each of the given feature point types
+         */
+        final Map<MeshFacet, List<Double>> hausdorffDistances = distanceVisitor.getDistances();
+        for (final Map.Entry<FeaturePointType, Double> fpType: featurePointTypes.entrySet()) {
+            final FeaturePointType featurePointType = fpType.getKey();
+            final double featurePointRadius = fpType.getValue();
+            
+            final FeaturePoint featurePoint = getFeaturePointByType(humanFace, featurePointType);
+            if (featurePoint == null) {
+                continue;
+            }
+            
+            final PrioritySphere priorityVisitor = new PrioritySphere(featurePoint.getPosition(), featurePointRadius);
+            humanFace.getMeshModel().compute(priorityVisitor, inParallel());
+
+            synchronized (this) {
+                priorities.computeIfAbsent(humanFace, face -> new HashMap<>())
+                        .computeIfAbsent(featurePointType, fPointType -> new HashMap<>())
+                        .putAll(priorityVisitor.getPriorities());
+            }
+            
+            for (final Map.Entry<MeshFacet, List<Double>> entry: priorityVisitor.getPriorities().entrySet()) {
+                final MeshFacet facet = entry.getKey();
+                final List<Double> facetPriorities = entry.getValue();
+
+                synchronized (this) {
+                    /*
+                     * Calculate the weighted average of Hausdorff distance
+                     * of all vertices within the feature point's priority sphere.
+                     */
+                    final List<Double> facetDistances = hausdorffDistances.get(facet);
+                    featurePointWeights.computeIfAbsent(humanFace, face -> new HashMap<>())
+                            .computeIfAbsent(featurePointType, fPointType -> new HashMap<>())
+                            .put(facet, IntStream.range(0, facetDistances.size())
+                                    .filter(i -> facetPriorities.get(i) > 0) // Filter out vertices that are outside of the priority sphere
+                                    .boxed()
+                                    .collect(WeightedAverageCollector.toWeightedAverage(
+                                            facetDistances::get,
+                                            facetPriorities::get
+                                    ))
+                            );
+                    
+                    /* 
+                     * Merge priorities computed for the current feature point type
+                     * with the priorities of already computed feature point types.
+                     */
+                    final List<Double> storedFacetPriorities = mergedPriorities
+                            .computeIfAbsent(humanFace, face -> new HashMap<>())
+                            .get(facet);
+                    if (storedFacetPriorities == null) { // No priorities stored for this facet yet -> there is nothing to be merged
+                        mergedPriorities.get(humanFace).put(facet, new ArrayList<>(facetPriorities));
+                        continue;
+                    }
+
+                    // Merge priorities -> take the greater value
+                    for (int i = 0; i < storedFacetPriorities.size(); i++) {
+                        storedFacetPriorities.set(i, Double.max(storedFacetPriorities.get(i), facetPriorities.get(i)));
+                    }
+                }
+            }
+        }
+    }
+    
+    /**
+     * Finds and returns a feature point of the desired type in the given human face.
+     * 
+     * @param face Face containing the desired feature point
+     * @param type Type of the feature point to be obtained
+     * @return Feature point of the desired type
+     */
+    protected FeaturePoint getFeaturePointByType(HumanFace face, FeaturePointType type) {
+        for (final FeaturePoint featurePoint: face.getFeaturePoints()) {
+            if (type.getType() == featurePoint.getFeaturePointType().getType()) {
+                return featurePoint;
+            }
+        }
+        
+        return null;
+    }
+}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/face/HumanFaceVisitor.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/face/HumanFaceVisitor.java
new file mode 100644
index 0000000000000000000000000000000000000000..28789a339a97d4e091f62ceee06c2ad67f41e2a5
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/face/HumanFaceVisitor.java
@@ -0,0 +1,42 @@
+package cz.fidentis.analyst.visitors.face;
+
+import cz.fidentis.analyst.face.HumanFace;
+
+/**
+ * A functor. When instantiated, it can be gradually applied to multiple faces.
+ * It inspects the state of the human face one by one, and (cumulatively) computes results.
+ * <p>
+ * Implement this interface whenever you want to define new algorithm over a human face.
+ * </p>
+ * <p>
+ * If the visitor is thread-safe, then a single instance of the visitor
+ * can visit concurrently (and asynchronously) multiple faces. Otherwise, 
+ * the parallel inspection is still possible, but a new instance of the visitor 
+ * has to be used for each human face.
+ * </p>
+ *
+ * @author Daniel Schramm
+ */
+public abstract class HumanFaceVisitor {
+    
+    /**
+     * Returns {@code true} if the implementation is thread-safe and then
+     * <b>a single visitor instance</b> can be applied to multiple faces simultaneously.
+     * <p>
+     * Thread-safe implementation means that any read or write from/to the visitor's 
+     * state is protected by {@code synchronized}.
+     * </p>
+     * 
+     * @return {@code true} if the implementation is thread-safe.
+     */
+    public boolean isThreadSafe() {
+        return true;
+    }
+    
+    /**
+     * The main inspection method to be implemented by specific visitors.
+     * 
+     * @param humanFace Face to be visited
+     */
+    public abstract void visitHumanFace(HumanFace humanFace);
+}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/face/WeightedAverageCollector.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/face/WeightedAverageCollector.java
new file mode 100644
index 0000000000000000000000000000000000000000..1ad08cd93a043d476c5e6f6101f8cca9d4c2317c
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/face/WeightedAverageCollector.java
@@ -0,0 +1,152 @@
+package cz.fidentis.analyst.visitors.face;
+
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.function.ToDoubleFunction;
+import java.util.stream.Collector;
+
+/**
+ * A collector for calculation of the weighted average, suitable for use in Java 8 streams.
+ *
+ * <p>
+ * A mutable reduction operation that accumulates input elements into a mutable
+ * result container, transforming the accumulated result into a final
+ * representation after all input elements have been processed.
+ * </p>
+ * 
+ * @author Daniel Schramm
+ * @param <T> Data type of the stream elements
+ */
+public class WeightedAverageCollector<T> implements Collector<T, IntemediateResults, Double> {
+
+    private final ToDoubleFunction<? super T> valueFunction;
+    private final ToDoubleFunction<? super T> weightFunction;
+    
+    /**
+     * Constructor.
+     * 
+     * @param valueFunction Function returning the value for a given stream element
+     * @param weightFunction Function returning the weight for a given stream element
+     */
+    public WeightedAverageCollector(
+            ToDoubleFunction<? super T> valueFunction,
+            ToDoubleFunction<? super T> weightFunction) {
+        this.valueFunction = valueFunction;
+        this.weightFunction = weightFunction;
+    }
+    
+    /**
+     * Returns a {@link Collector} interface object used to compute the weighted average.
+     * 
+     * @param <T> Data type of the stream elements
+     * @param valueFunction Function returning the value for a given stream element
+     * @param weightFunction Function returning the weight for a given stream element
+     * @return A Collector interface object used to compute the weighted average
+     */
+    public static <T> Collector<T, ?, Double> toWeightedAverage(
+            ToDoubleFunction<? super T> valueFunction,
+            ToDoubleFunction<? super T> weightFunction) {
+        return new WeightedAverageCollector<>(valueFunction, weightFunction);
+    }
+    
+    /**
+     * A function that creates and returns a new mutable result container.
+     *
+     * @return A function which returns a new, mutable result container
+     */
+    @Override
+    public Supplier<IntemediateResults> supplier() {
+        return IntemediateResults::new;
+    }
+    
+    /**
+     * A function that folds a value into a mutable result container.
+     *
+     * @return A function which folds a value into a mutable result container
+     */
+    @Override
+    public BiConsumer<IntemediateResults, T> accumulator() {
+        return (iResult, streamElement) -> {
+            iResult.addWeightedValSum(valueFunction.applyAsDouble(streamElement)
+                    * weightFunction.applyAsDouble(streamElement));
+            iResult.addWeightSum(weightFunction.applyAsDouble(streamElement));
+        };
+    }
+    
+    /**
+     * A function that accepts two partial results and merges them. The
+     * combiner function may fold state from one argument into the other and
+     * return that, or may return a new result container.
+     *
+     * @return A function which combines two partial results into a combined
+     *         result
+     */
+    @Override
+    public BinaryOperator<IntemediateResults> combiner() {
+        return (iResult1, iResult2) -> {
+            iResult1.addWeightedValSum(iResult2.getWeightedValSum());
+            iResult1.addWeightSum(iResult2.getWeightSum());
+            
+            return iResult1;
+        };
+    }
+    
+    /**
+     * Perform the final transformation from the intermediate accumulation type
+     * {@link IntemediateResults} to the final result type {@link Double}.
+     *
+     * <p>
+     * If the characteristic {@code IDENTITY_FINISH} is
+     * set, this function may be presumed to be an identity transform with an
+     * unchecked cast from {@link IntemediateResults} to {@link Double}.
+     * </p>
+     *
+     * @return A function which transforms the intermediate result to the final
+     *         result
+     */
+    @Override
+    public Function<IntemediateResults, Double> finisher() {
+        return iResult -> iResult.getWeightedValSum() / iResult.getWeightSum();
+    }
+    
+    /**
+     * Returns a {@code Set} of {@code Collector.Characteristics} indicating
+     * the characteristics of this Collector.
+     *
+     * @return An immutable set of collector characteristics
+     */
+    @Override
+    public Set<Characteristics> characteristics() {
+        return Set.of(Characteristics.UNORDERED);
+    }
+}
+
+/**
+ * A helper class which stores intermediate results
+ * for the {@link WeightedAverageCollector} class.
+ * 
+ * @author Daniel Schramm
+ */
+class IntemediateResults {
+    private double weightedValSum = 0;
+    private double weightSum = 0;
+
+    public double getWeightedValSum() {
+        return weightedValSum;
+    }
+
+    public double getWeightSum() {
+        return weightSum;
+    }
+
+    public void addWeightedValSum(double weightedValSum) {
+        this.weightedValSum += weightedValSum;
+    }
+
+    public void addWeightSum(double weightSum) {
+        this.weightSum += weightSum;
+    }
+}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/face/package-info.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/face/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..2b05c0785db08f5f2926faad96809006428d5763
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/face/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * Visitors used to explore the human face (i.e., implementing the 
+ * {@link cz.fidentis.analyst.visitors.face.HumanFaceVisitor}).
+ */
+package cz.fidentis.analyst.visitors.face;
\ No newline at end of file
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/KdTreeApproxDistanceToTriangles.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/KdTreeApproxDistanceToTriangles.java
index dad64d39c857534ef702ac825ed04273858bb40c..a1539dd4b459dd1128ae7bf2e08498eac7754ff1 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/KdTreeApproxDistanceToTriangles.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/KdTreeApproxDistanceToTriangles.java
@@ -94,8 +94,8 @@ public class KdTreeApproxDistanceToTriangles extends KdTreeVisitor implements Di
                         distance = dist;
                         nearestPoints.clear();                    
                     }
-                    nearestPoints.putIfAbsent(facet, new ArrayList<>());
-                    nearestPoints.get(facet).add(projection);
+                    nearestPoints.computeIfAbsent(facet, meshFacet -> new ArrayList<>())
+                        .add(projection);
                 }
             }
         }
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/KdTreeClosestNode.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/KdTreeClosestNode.java
index 861debeb9fdfa809f6e54f47596d5fd8aa81ca67..f5ccb8fbcac9d844b060c118ff1fe9eba99a2c16 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/KdTreeClosestNode.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/KdTreeClosestNode.java
@@ -64,6 +64,14 @@ public class KdTreeClosestNode extends KdTreeVisitor {
     public double getDistance() {
         return distance;
     }
+    
+    /**
+     * Returns the 3D point to which the closest points of inspected kd-tree has been searched.
+     * @return the 3D point to which the closest points of inspected kd-tree has been searched.
+     */
+    public Point3d getReferencePoint() {
+        return point3d;
+    }
 
     @Override
     public void visitKdTree(KdTree kdTree) {
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/KdTreeDistance.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/KdTreeDistance.java
index dd67d0a407ad61d8cf76ced19b6a2eaaecbefb32..ab48a42c6dd51c7ff161eba8501109b2d189ff77 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/KdTreeDistance.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/KdTreeDistance.java
@@ -25,7 +25,7 @@ public class KdTreeDistance extends KdTreeVisitor implements Distance {
     /**
      * Constructor.
      * @param point A 3D point from which distance is computed. Must not be {@code null}
-     * @throws {@code IllegalArgumentException} if some parameter is wrong
+     * @throws IllegalArgumentException if some parameter is wrong
      */
     public KdTreeDistance(Point3d point) {
         if (point == null) {
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/KdTreeDistanceToVertices.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/KdTreeDistanceToVertices.java
index c421c48eaa9a6540f99838502fe361b2b317547a..2f8594cba8b8eac151483250077c634ddd230cdc 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/KdTreeDistanceToVertices.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/KdTreeDistanceToVertices.java
@@ -76,8 +76,8 @@ public class KdTreeDistanceToVertices extends KdTreeVisitor implements DistanceW
                 for (Entry<MeshFacet, Integer> entry: node.getFacets().entrySet()) {
                     MeshFacet facet = entry.getKey();
                     MeshPoint point = facet.getVertex(entry.getValue());
-                    nearestPoints.putIfAbsent(facet, new ArrayList<>());
-                    nearestPoints.get(facet).add(point.getPosition());
+                    nearestPoints.computeIfAbsent(facet, meshFacet -> new ArrayList<>())
+                        .add(point.getPosition());
                 }
             }
         }
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistance.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistance.java
index 05f9e6b35370b9ecb6ab845c4cf5444b0dd2233f..eb224fb618a16bca82ae38b30f3be019f00ac0a3 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistance.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistance.java
@@ -39,7 +39,7 @@ import javax.vecmath.Point3d;
  * to inspect multiple meshes simultaneously. 
  * </p>
  * <p>
- * The distance is computer either as absolute or relative. Absolute
+ * The distance is computed either as absolute or relative. Absolute
  * represents Euclidean distance (all numbers are positive). On the contrary, 
  * relative distance considers orientation of the visited mesh (determined by its normal vectors)
  * and produces positive or negative distances depending on whether the primary
@@ -221,7 +221,8 @@ public class HausdorffDistance extends MeshVisitor  {
     }
     
     /**
-     * Returns Hausdorff distance of mesh facets to the source mesh facets. 
+     * Returns Hausdorff distance of mesh facets to the source mesh facets.
+     * 
      * Keys in the map contain mesh facets that were measured with the 
      * source facets. For each measured facet, a list of distances to the source 
      * facets is stored. The order of distances corresponds to the order of vertices
@@ -236,6 +237,7 @@ public class HausdorffDistance extends MeshVisitor  {
 
     /**
      * Returns the nearest points of mesh facets to the source mesh facets.
+     * 
      * Keys in the map contain mesh facets that were measured with the
      * source facets. For each measured facet, a list of the nearest points to the source
      * facets is stored. The order of  points corresponds to the order of vertices
@@ -247,6 +249,7 @@ public class HausdorffDistance extends MeshVisitor  {
     public Map<MeshFacet, List<Point3d>> getNearestPoints() {
         return Collections.unmodifiableMap(nearestPoints);
     }
+
     /**
      * Returns {@code true} if the distance was computed as relative 
      * (with possibly negative values). 
@@ -263,6 +266,7 @@ public class HausdorffDistance extends MeshVisitor  {
     
     /**
      * Returns {@code true} if the distance computation is parallel.
+     * 
      * @return {@code true} if the distance computation is parallel.
      */
     public boolean inParallel() {
@@ -355,12 +359,12 @@ public class HausdorffDistance extends MeshVisitor  {
         if (relativeDist) { // compute sign for relative distance
             Vector3d aux = new Vector3d(closestV);
             aux.sub(point.getPosition());
-            sign = (int) Math.signum(aux.dot(point.getNormal()));
-        } 
+            sign = aux.dot(point.getNormal()) < 0 ? -1 : 1;
+        }
         
         distances.get(facet).add(sign * dist);
         if (nearestPoints.containsKey(facet)) { // only strategies with the closest points are stored in the map
-            nearestPoints.get(facet).add(closestV); 
+            nearestPoints.get(facet).add(closestV);
         }
     }
     
@@ -369,7 +373,7 @@ public class HausdorffDistance extends MeshVisitor  {
      * @return the only one existing closest vertex or {@code null}
      */
     protected Point3d getClosestVertex(DistanceWithNearestPoints vis) {
-        if (vis.getNearestPoints().size() != 1) { 
+        if (vis.getNearestPoints().size() != 1) {
             return null; // somethig is wrong because there should be only my inspected facet
         }
         
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/MeshApproxDistanceToTriangles.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/MeshApproxDistanceToTriangles.java
index 343d9d5dc2fbe419dbaf082725e555f37627f615..6d7fa32e8e536b873bc32a5681fa9bb1c36e8352 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/MeshApproxDistanceToTriangles.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/MeshApproxDistanceToTriangles.java
@@ -101,8 +101,8 @@ public class MeshApproxDistanceToTriangles extends MeshVisitor implements Distan
                     distance = dist;
                     nearestPoints.clear();                    
                 }
-                nearestPoints.putIfAbsent(facet, new ArrayList<>());
-                nearestPoints.get(facet).add(projection);
+                nearestPoints.computeIfAbsent(facet, meshFacet -> new ArrayList<>())
+                        .add(projection);
             }
         }
     }
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/MeshDistanceToTriangles.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/MeshDistanceToTriangles.java
index e806c2980e863f2b6343fc4b605290b4432a6686..fa54f1db8df8de39ea4a916f89c2aa18dbf4beff 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/MeshDistanceToTriangles.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/MeshDistanceToTriangles.java
@@ -65,8 +65,8 @@ public class MeshDistanceToTriangles extends MeshVisitor implements DistanceWith
                     distance = dist;
                     nearestPoints.clear();                    
                 }
-                nearestPoints.putIfAbsent(facet, new ArrayList<>());
-                nearestPoints.get(facet).add(projection);
+                nearestPoints.computeIfAbsent(facet, meshFacet -> new ArrayList<>())
+                        .add(projection);
             }
         }
     }
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/MeshDistanceToVertices.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/MeshDistanceToVertices.java
index 9520075a811a8b26f7bb4fdede76473d8f5d1fa8..cb4f174b0c25709398b8331439ce0e6aa82d2237 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/MeshDistanceToVertices.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/MeshDistanceToVertices.java
@@ -67,8 +67,8 @@ public class MeshDistanceToVertices extends MeshVisitor implements DistanceWithN
                     distance = dist;
                     nearestPoints.clear();                    
                 }
-                nearestPoints.putIfAbsent(facet, new ArrayList<>());
-                nearestPoints.get(facet).add(pointOnSurface);
+                nearestPoints.computeIfAbsent(facet, meshFacet -> new ArrayList<>())
+                        .add(pointOnSurface);
             }
         }
     }
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/PrioritySphere.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/PrioritySphere.java
new file mode 100644
index 0000000000000000000000000000000000000000..31c3b647c80261ce3c453b14a8ec3e7e9622493c
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/PrioritySphere.java
@@ -0,0 +1,92 @@
+package cz.fidentis.analyst.visitors.mesh;
+
+import cz.fidentis.analyst.mesh.MeshVisitor;
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshPoint;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.vecmath.Point3d;
+
+/**
+ * This visitor computes priorities of vertices of a mesh facet according to their absolute distance from
+ * the given {@link PrioritySphere#sphereCenterPosition} point.
+ * <ul>
+ *   <li>1 is maximal priority; 0 is minimal priority</li>
+ *   <li>The closer a vertex is to {@link PrioritySphere#sphereCenterPosition},
+ *       the higher its priority is.</li>
+ *   <li>Vertices that are further than {@link PrioritySphere#sphereRadius}
+ *       from {@link PrioritySphere#sphereCenterPosition} have priority equal to 0.</li>
+ * </ul>
+ * <p>
+ *   The visitor returns all mesh facets together with priorities of all their vertices.
+ * </p>
+ * <p>
+ *   This visitor is thread-safe.
+ * </p>
+ * 
+ * @author Daniel Schramm
+ */
+public class PrioritySphere extends MeshVisitor  {
+    
+    private final Point3d sphereCenterPosition;
+    private final double sphereRadius;
+    
+    private final Map<MeshFacet, List<Double>> priorities = new HashMap<>();
+
+    /**
+     * Constructor.
+     * 
+     * @param sphereCenterPosition Position of the center of the sphere in which
+     *                             the priorities will be calculated
+     * @param sphereRadius Radius of the sphere (must be greater than or equal to 0)
+     */
+    public PrioritySphere(Point3d sphereCenterPosition, double sphereRadius) {
+        if (sphereCenterPosition == null) {
+            throw new IllegalArgumentException("sphereCenterPosition");
+        }
+        this.sphereCenterPosition = sphereCenterPosition;
+        if (sphereRadius < 0) {
+            throw new IllegalArgumentException("sphereRadius");
+        }
+        this.sphereRadius = sphereRadius;
+    }
+
+    /**
+     * Returns a map of visited mesh facets together with the list of priorities of their vertices.
+     * 
+     * The order of priorities corresponds to the order of vertices
+     * in the visited facet, i.e., the i-th priority is a priority of the i-th vertex
+     * of the visited facet.
+     * 
+     * @return map of visited mesh facets and priorities of their vertices
+     */
+    public Map<MeshFacet, List<Double>> getPriorities() {
+        return Collections.unmodifiableMap(priorities);
+    }
+
+    @Override
+    public void visitMeshFacet(MeshFacet facet) {
+        final List<MeshPoint> vertices = facet.getVertices();
+        
+        final List<Double> prioritiesList = new ArrayList<>(vertices.size());
+        
+        for (int i = 0; i < vertices.size(); i++) { // for each vertex of visited facet
+            final double distance = sphereCenterPosition.distance(vertices.get(i).getPosition());
+            final double priority;
+            if (distance > sphereRadius) {
+                priority = 0;
+            } else {
+                priority = 1 - distance / sphereRadius;
+            }
+            
+            prioritiesList.add(priority);
+        }
+        
+        synchronized(this) {
+            priorities.put(facet, prioritiesList);
+        }
+    }
+}
diff --git a/Comparison/src/test/java/cz/fidentis/analyst/visitors/face/HausdorffDistancePrioritizedTest.java b/Comparison/src/test/java/cz/fidentis/analyst/visitors/face/HausdorffDistancePrioritizedTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9706a4224d06ac9bbda21e6f68e9c8f354b82f85
--- /dev/null
+++ b/Comparison/src/test/java/cz/fidentis/analyst/visitors/face/HausdorffDistancePrioritizedTest.java
@@ -0,0 +1,516 @@
+package cz.fidentis.analyst.visitors.face;
+
+import cz.fidentis.analyst.face.HumanFace;
+import cz.fidentis.analyst.feature.FeaturePoint;
+import cz.fidentis.analyst.feature.FeaturePointType;
+import cz.fidentis.analyst.mesh.core.CornerTableRow;
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
+import cz.fidentis.analyst.mesh.core.MeshModel;
+import cz.fidentis.analyst.mesh.core.MeshPointImpl;
+import static cz.fidentis.analyst.visitors.mesh.HausdorffDistance.Strategy.POINT_TO_POINT;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import javax.vecmath.Point3d;
+import javax.vecmath.Vector3d;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import org.junit.jupiter.api.Test;
+
+public class HausdorffDistancePrioritizedTest {
+    
+    private static final double DELTA = 1e-15;
+    
+    private final File boy = new File("src/test/resources/cz/fidentis/analyst/average_boy_17-20.obj");
+    
+    private static final int VERTICES_NUM = 12;
+    
+    private final MeshFacet facet1 = getTrivialFacet(VERTICES_NUM, 0.1, 0, 0, 0);
+    private final MeshFacet facet2 = getTrivialFacet(VERTICES_NUM, -0.1, 0, 0, 0);
+    private final MeshFacet facet3 = getTrivialFacet(VERTICES_NUM, 0, 0.1, 0, 0);
+    private final MeshFacet facet4 = getTrivialFacet(VERTICES_NUM, 0, -0.1, 0, 0);
+    private final MeshFacet facet5 = getTrivialFacet(VERTICES_NUM, 0, 0, 0.1, 0);
+    private final MeshFacet facet6 = getTrivialFacet(VERTICES_NUM, 0, 0, -0.1, 0);
+    private final List<MeshFacet> facets = List.of(facet1, facet2, facet3, facet4, facet5, facet6);
+    
+    private final List<MeshFacet> facets2 = List.of(getTrivialFacet(1, 0, 0, 0, 0));
+    
+    private final List<Double> prioritiesListFP1 = List.of(1d, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0d, 0d);
+    private final double weightedDistanceFP1 = 0 + 0.09 + 0.16 + 0.21 + 0.24 + 0.25 + 0.24 + 0.21 + 0.16 + 0.09 + 0 + 0;
+    private final double averageWeightedDistanceFP1 = weightedDistanceFP1 / prioritiesListFP1.stream()
+            .mapToDouble(Double::doubleValue)
+            .sum();
+    
+    private final Point3d featurePoint1 = new Point3d(0, 0, 0);
+    private final FeaturePointType fpType1 = new FeaturePointType(0, null, null, null);
+    private final Map<MeshFacet, List<Double>> expectedPrioritiesMapFP1 = Map.of(facet1, prioritiesListFP1,
+            facet2, prioritiesListFP1,
+            facet3, prioritiesListFP1,
+            facet4, prioritiesListFP1,
+            facet5, prioritiesListFP1,
+            facet6, prioritiesListFP1);
+    private final Map<MeshFacet, Double> expectedWeightedDistancesMapFP1 = Map.of(facet1, averageWeightedDistanceFP1,
+            facet2, averageWeightedDistanceFP1,
+            facet3, averageWeightedDistanceFP1,
+            facet4, averageWeightedDistanceFP1,
+            facet5, -averageWeightedDistanceFP1,
+            facet6, averageWeightedDistanceFP1);
+    private final Map<MeshFacet, Double> expectedAbsoluteWeightedDistancesMapFP1 = expectedWeightedDistancesMapFP1
+            .entrySet()
+            .stream()
+            .collect(Collectors.toMap(entry -> entry.getKey(), entry -> Math.abs(entry.getValue())));
+    
+    private MeshFacet getTrivialFacet(int count, double xSpace, double ySpace, double zSpace, int offset) {
+        final MeshFacet facet = new MeshFacetImpl();
+        for (int i = offset; i < count + offset; i++) {
+            facet.addVertex(new MeshPointImpl(new Point3d(xSpace * i, ySpace * i, zSpace * i),
+                    new Vector3d(0, 0, 1),
+                    new Vector3d()));
+            facet.getCornerTable().addRow(new CornerTableRow(i - offset, -1));
+        }
+
+        return facet;
+    }
+    
+    private HumanFace getHumanFace(List<MeshFacet> facets,
+            List<Point3d> featurePoints,
+            List<FeaturePointType> featurePointTypes) throws IOException {
+        
+        assertEquals(featurePoints.size(), featurePointTypes.size());
+        
+        final HumanFace face = new HumanFace(boy);
+        
+        final MeshModel model = new MeshModel();
+        for (final MeshFacet facet: facets) {
+            model.addFacet(facet);
+        }
+        face.setMeshModel(model);
+        
+        final List<FeaturePoint> featurePointsList = new ArrayList<>();
+        for (int i = 0; i < featurePoints.size(); i++) {
+            final Point3d fpCoordinates = featurePoints.get(i);
+            featurePointsList.add(new FeaturePoint(
+                    fpCoordinates.x,
+                    fpCoordinates.y,
+                    fpCoordinates.z,
+                    featurePointTypes.get(i)));
+        }
+        face.setFeaturePoints(featurePointsList);
+        
+        return face;
+    }
+    
+    private static Map<FeaturePointType, Double> zipListsToMap(List<FeaturePointType> fpTypes, List<Double> fpRadii) {
+        assertEquals(fpTypes.size(), fpRadii.size());
+        return IntStream.range(0, fpTypes.size())
+                .boxed()
+                .collect(Collectors.toMap(fpTypes::get, fpRadii::get));
+    }
+    
+    protected void performTest(HumanFace face,
+            Map<FeaturePointType, Map<MeshFacet, List<Double>>> expectedPriorities,
+            Map<FeaturePointType, Map<MeshFacet, Double>> expectedFeaturePointWeights,
+            Map<MeshFacet, List<Double>> expectedMergedPriorities,
+            HausdorffDistancePrioritized visitor) {
+        
+        final Set<FeaturePointType> featurePointTypes = visitor.getFeaturePointTypes().keySet();
+        final List<FeaturePoint> faceFeaturePoints = face.getFeaturePoints();
+        featurePointTypes.forEach(fpType -> assertTrue(faceFeaturePoints.stream()
+                .anyMatch(fPoint -> fPoint.getFeaturePointType().equals(fpType))));
+                
+        face.accept(visitor);
+        
+        final List<MeshFacet> faceFacets = face.getMeshModel().getFacets();
+        
+        // ---------------------------------------------------------------------
+        // Test priorities
+        // ---------------------------------------------------------------------
+        final Map<HumanFace, Map<FeaturePointType, Map<MeshFacet, List<Double>>>> priorities =
+                visitor.getPriorities();
+        assertTrue(priorities.containsKey(face));
+        final Map<FeaturePointType, Map<MeshFacet, List<Double>>> facePriorities =
+                priorities.get(face);
+        assertEquals(featurePointTypes.size(), facePriorities.size());
+        
+        for (final FeaturePointType fpType: featurePointTypes) {
+            assertTrue(facePriorities.containsKey(fpType));
+            
+            final Map<MeshFacet, List<Double>> facePrioritiesMap = facePriorities.get(fpType);
+            final Map<MeshFacet, List<Double>> expectedPrioritiesMap = expectedPriorities.get(fpType);
+            assertEquals(faceFacets.size(), facePrioritiesMap.size());
+            
+            for (final MeshFacet facet: faceFacets) {
+                assertTrue(facePrioritiesMap.containsKey(facet));
+                
+                final List<Double> facePrioritiesList = facePrioritiesMap.get(facet);
+                final List<Double> expectedPrioritiesList = expectedPrioritiesMap.get(facet);
+                assertEquals(expectedPrioritiesList.size(), facePrioritiesList.size());
+                
+                for (int i = 0; i < expectedPrioritiesList.size(); i++) {
+                    assertEquals(expectedPrioritiesList.get(i), facePrioritiesList.get(i), DELTA);
+                }
+            }
+        }
+        
+        // ---------------------------------------------------------------------
+        // Test feature point weights
+        // ---------------------------------------------------------------------
+        final Map<HumanFace, Map<FeaturePointType, Map<MeshFacet, Double>>> featurePointWeights =
+                visitor.getFeaturePointWeights();
+        assertTrue(featurePointWeights.containsKey(face));
+        final Map<FeaturePointType, Map<MeshFacet, Double>> faceFeaturePointWeights =
+                featurePointWeights.get(face);
+        assertEquals(featurePointTypes.size(), faceFeaturePointWeights.size());
+        
+        for (final FeaturePointType fpType: featurePointTypes) {
+            assertTrue(faceFeaturePointWeights.containsKey(fpType));
+            
+            final Map<MeshFacet, Double> faceFPWeightsMap = faceFeaturePointWeights.get(fpType);
+            final Map<MeshFacet, Double> expectedFPWeightsMap = expectedFeaturePointWeights.get(fpType);
+            assertEquals(faceFacets.size(), faceFPWeightsMap.size());
+            
+            for (final MeshFacet facet: faceFacets) {
+                assertTrue(faceFPWeightsMap.containsKey(facet));
+                
+                final double expectedWeightedDistance = expectedFPWeightsMap.get(facet);
+                final double actualWeightedDistance = faceFPWeightsMap.get(facet);
+                assertEquals(expectedWeightedDistance, actualWeightedDistance, DELTA);
+            }
+        }
+        
+        // ---------------------------------------------------------------------
+        // Test merged priorities
+        // ---------------------------------------------------------------------
+        final Map<HumanFace, Map<MeshFacet, List<Double>>> mergedPriorities =
+                visitor.getMergedPriorities();
+        assertTrue(mergedPriorities.containsKey(face));
+        final Map<MeshFacet, List<Double>> faceMergedPriorities =
+                mergedPriorities.get(face);
+        assertEquals(faceFacets.size(), faceMergedPriorities.size());
+        
+        for (final MeshFacet facet: faceFacets) {
+            assertTrue(faceMergedPriorities.containsKey(facet));
+            
+            final List<Double> faceMergedPrioritiesList = faceMergedPriorities.get(facet);
+            final List<Double> expectedMergedPrioritiesList = expectedMergedPriorities.get(facet);
+            assertEquals(expectedMergedPrioritiesList.size(), faceMergedPrioritiesList.size());
+            
+            for (int i = 0; i < expectedMergedPrioritiesList.size(); i++) {
+                assertEquals(expectedMergedPrioritiesList.get(i), faceMergedPrioritiesList.get(i), DELTA);
+            }
+        }
+    }
+    
+    @Test
+    public void singleFeaturePointTest() throws IOException {
+        final List<Point3d> featurePoints = List.of(featurePoint1);
+        final List<FeaturePointType> fpTypes = List.of(fpType1);
+        final Map<FeaturePointType, Double> featurePointTypes = zipListsToMap(fpTypes, List.of(1d));
+        
+        final HumanFace face = getHumanFace(facets, featurePoints, fpTypes);
+        
+        final Map<FeaturePointType, Map<MeshFacet, List<Double>>> expectedPriorities = Map.of(fpType1, expectedPrioritiesMapFP1);
+        final Map<FeaturePointType, Map<MeshFacet, Double>> expectedFeaturePointsWeights = Map.of(fpType1, expectedWeightedDistancesMapFP1);
+        
+        final Map<MeshFacet, List<Double>> expectedMergedPrioritiesMap = new HashMap<>();
+        for (final MeshFacet facet: facets) {
+            expectedMergedPrioritiesMap.put(facet, prioritiesListFP1);
+        }
+        
+        final HausdorffDistancePrioritized visitor = new HausdorffDistancePrioritized(getHumanFace(facets2, List.of(), List.of()),
+                featurePointTypes,
+                POINT_TO_POINT,
+                true,
+                false);
+        
+        performTest(face, expectedPriorities, expectedFeaturePointsWeights, expectedMergedPrioritiesMap, visitor);
+    }
+    
+    @Test
+    public void twoFeaturePointsNoFacetIntersecTest() throws IOException {
+        final List<Point3d> featurePoints = List.of(featurePoint1, new Point3d(3, 0, 0));
+        final FeaturePointType fpType2 = new FeaturePointType(1, null, null, null);
+        final List<FeaturePointType> fpTypes = List.of(fpType1, fpType2);
+        final Map<FeaturePointType, Double> featurePointTypes = zipListsToMap(fpTypes, List.of(1d, 1d));
+        
+        final HumanFace face = getHumanFace(facets, featurePoints, fpTypes);
+        
+        final Map<MeshFacet, List<Double>> expectedPrioritiesMapFP2 = new HashMap<>();
+        for (final MeshFacet facet: facets) {
+            expectedPrioritiesMapFP2.put(facet, Collections.nCopies(VERTICES_NUM, 0d));
+        }
+        final Map<FeaturePointType, Map<MeshFacet, List<Double>>> expectedPriorities = Map.of(fpType1, expectedPrioritiesMapFP1,
+                fpType2, expectedPrioritiesMapFP2);
+        
+        final Map<MeshFacet, Double> expectedWeightedDistancesMapFP2 = new HashMap<>();
+        for (final MeshFacet facet: facets) {
+            expectedWeightedDistancesMapFP2.put(facet, Double.NaN);
+        }
+        final Map<FeaturePointType, Map<MeshFacet, Double>> expectedFeaturePointsWeights = Map.of(fpType1, expectedAbsoluteWeightedDistancesMapFP1,
+                fpType2, expectedWeightedDistancesMapFP2);
+        
+        final Map<MeshFacet, List<Double>> expectedMergedPrioritiesMap = new HashMap<>();
+        for (final MeshFacet facet: facets) {
+            expectedMergedPrioritiesMap.put(facet, prioritiesListFP1);
+        }
+        
+        final HausdorffDistancePrioritized visitor = new HausdorffDistancePrioritized(getHumanFace(facets2, List.of(), List.of()),
+                featurePointTypes,
+                POINT_TO_POINT,
+                false,
+                false);
+        
+        performTest(face, expectedPriorities, expectedFeaturePointsWeights, expectedMergedPrioritiesMap, visitor);
+    }
+    
+    @Test
+    public void twoFeaturePointsSingleFacetIntersecTest() throws IOException {
+        final List<Point3d> featurePoints = List.of(featurePoint1, new Point3d(1, 0, 0));
+        final FeaturePointType fpType2 = new FeaturePointType(1, null, null, null);
+        final List<FeaturePointType> fpTypes = List.of(fpType1, fpType2);
+        final Map<FeaturePointType, Double> featurePointTypes = zipListsToMap(fpTypes, List.of(1d, 1d));
+        
+        final HumanFace face = getHumanFace(facets, featurePoints, fpTypes);
+        
+        final Map<MeshFacet, List<Double>> expectedPrioritiesMapFP2 = new HashMap<>();
+        for (final MeshFacet facet: facets) {
+            expectedPrioritiesMapFP2.put(facet, Collections.nCopies(VERTICES_NUM, 0d));
+        }
+        final List<Double> prioritiesList = List.of(0d, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1d, 0.9);
+        expectedPrioritiesMapFP2.put(facet1, prioritiesList);
+        final Map<FeaturePointType, Map<MeshFacet, List<Double>>> expectedPriorities = Map.of(fpType1, expectedPrioritiesMapFP1,
+                fpType2, expectedPrioritiesMapFP2);
+        
+        final Map<MeshFacet, Double> expectedWeightedDistancesMapFP2 = new HashMap<>();
+        for (final MeshFacet facet: facets) {
+            expectedWeightedDistancesMapFP2.put(facet, Double.NaN);
+        }
+        expectedWeightedDistancesMapFP2.put(
+                facet1,
+                (0 + 0.01 + 0.04 + 0.09 + 0.16 + 0.25 + 0.36 + 0.49 + 0.64 + 0.81 + 1 + 0.99) / prioritiesList.stream()
+                        .mapToDouble(Double::doubleValue)
+                        .sum()
+        );
+        final Map<FeaturePointType, Map<MeshFacet, Double>> expectedFeaturePointsWeights = Map.of(fpType1, expectedWeightedDistancesMapFP1,
+                fpType2, expectedWeightedDistancesMapFP2);
+        
+        final Map<MeshFacet, List<Double>> expectedMergedPrioritiesMap = new HashMap<>();
+        for (final MeshFacet facet: facets) {
+            expectedMergedPrioritiesMap.put(facet, prioritiesListFP1);
+        }
+        expectedMergedPrioritiesMap.put(facet1, List.of(1d, 0.9, 0.8, 0.7, 0.6, 0.5, 0.6, 0.7, 0.8, 0.9, 1d, 0.9));
+        
+        final HausdorffDistancePrioritized visitor = new HausdorffDistancePrioritized(getHumanFace(facets2, List.of(), List.of()),
+                featurePointTypes,
+                POINT_TO_POINT,
+                true,
+                false);
+        
+        performTest(face, expectedPriorities, expectedFeaturePointsWeights, expectedMergedPrioritiesMap, visitor);
+    }
+    
+    @Test
+    public void fourFeaturePointsSingleFacetIntersecTest() throws IOException {
+        final List<Point3d> featurePoints = List.of(featurePoint1, new Point3d(1, 0, 0), new Point3d(0, 1, 0), new Point3d(0, 0, 1));
+        final FeaturePointType fpType2 = new FeaturePointType(1, null, null, null);
+        final FeaturePointType fpType3 = new FeaturePointType(2, null, null, null);
+        final FeaturePointType fpType4 = new FeaturePointType(3, null, null, null);
+        final List<FeaturePointType> fpTypes = List.of(fpType1, fpType2, fpType3, fpType4);
+        final Map<FeaturePointType, Double> featurePointTypes = zipListsToMap(fpTypes, List.of(1d, 1d, 1d, 1d));
+        
+        final HumanFace face = getHumanFace(facets, featurePoints, fpTypes);
+        
+        final Map<MeshFacet, List<Double>> expectedPrioritiesMapFP2 = new HashMap<>();
+        final Map<MeshFacet, List<Double>> expectedPrioritiesMapFP3 = new HashMap<>();
+        final Map<MeshFacet, List<Double>> expectedPrioritiesMapFP4 = new HashMap<>();
+        final List<Double> allZeroList = Collections.nCopies(VERTICES_NUM, 0d);
+        for (final MeshFacet facet: facets) {
+            expectedPrioritiesMapFP2.put(facet, allZeroList);
+            expectedPrioritiesMapFP3.put(facet, allZeroList);
+            expectedPrioritiesMapFP4.put(facet, allZeroList);
+        }
+        final List<Double> prioritiesList = List.of(0d, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1d, 0.9);
+        expectedPrioritiesMapFP2.put(facet1, prioritiesList);
+        expectedPrioritiesMapFP3.put(facet3, prioritiesList);
+        expectedPrioritiesMapFP4.put(facet5, prioritiesList);
+        final Map<FeaturePointType, Map<MeshFacet, List<Double>>> expectedPriorities = Map.of(fpType1, expectedPrioritiesMapFP1,
+                fpType2, expectedPrioritiesMapFP2,
+                fpType3, expectedPrioritiesMapFP3,
+                fpType4, expectedPrioritiesMapFP4);
+        
+        final Map<MeshFacet, Double> expectedWeightedDistancesMapFP2 = new HashMap<>();
+        final Map<MeshFacet, Double> expectedWeightedDistancesMapFP3 = new HashMap<>();
+        final Map<MeshFacet, Double> expectedWeightedDistancesMapFP4 = new HashMap<>();
+        for (final MeshFacet facet: facets) {
+            expectedWeightedDistancesMapFP2.put(facet, Double.NaN);
+            expectedWeightedDistancesMapFP3.put(facet, Double.NaN);
+            expectedWeightedDistancesMapFP4.put(facet, Double.NaN);
+        }
+        final double weightedDistance = (0 + 0.01 + 0.04 + 0.09 + 0.16 + 0.25 + 0.36 + 0.49 + 0.64 + 0.81 + 1 + 0.99) / prioritiesList.stream()
+                .mapToDouble(Double::doubleValue)
+                .sum();
+        expectedWeightedDistancesMapFP2.put(facet1, weightedDistance);
+        expectedWeightedDistancesMapFP3.put(facet3, weightedDistance);
+        expectedWeightedDistancesMapFP4.put(facet5, -weightedDistance);
+        final Map<FeaturePointType, Map<MeshFacet, Double>> expectedFeaturePointsWeights = Map.of(fpType1, expectedWeightedDistancesMapFP1,
+                fpType2, expectedWeightedDistancesMapFP2,
+                fpType3, expectedWeightedDistancesMapFP3,
+                fpType4, expectedWeightedDistancesMapFP4);
+        
+        final Map<MeshFacet, List<Double>> expectedMergedPrioritiesMap = new HashMap<>();
+        for (final MeshFacet facet: facets) {
+            expectedMergedPrioritiesMap.put(facet, prioritiesListFP1);
+        }
+        final List<Double> mergedPriorities = List.of(1d, 0.9, 0.8, 0.7, 0.6, 0.5, 0.6, 0.7, 0.8, 0.9, 1d, 0.9);
+        expectedMergedPrioritiesMap.put(facet1, mergedPriorities);
+        expectedMergedPrioritiesMap.put(facet3, mergedPriorities);
+        expectedMergedPrioritiesMap.put(facet5, mergedPriorities);
+        
+        final HausdorffDistancePrioritized visitor = new HausdorffDistancePrioritized(getHumanFace(facets2, List.of(), List.of()),
+                featurePointTypes,
+                POINT_TO_POINT,
+                true,
+                false);
+        
+        performTest(face, expectedPriorities, expectedFeaturePointsWeights, expectedMergedPrioritiesMap, visitor);
+    }
+    
+    @Test
+    public void threeFeaturePointsMultiFacetIntersecTest() throws IOException {
+        final List<Point3d> featurePoints = List.of(featurePoint1, new Point3d(0.999, 0.999, 0), new Point3d(0.999, -0.999, 0));
+        final FeaturePointType fpType2 = new FeaturePointType(1, null, null, null);
+        final FeaturePointType fpType3 = new FeaturePointType(2, null, null, null);
+        final List<FeaturePointType> fpTypes = List.of(fpType1, fpType2, fpType3);
+        final Map<FeaturePointType, Double> featurePointTypes = zipListsToMap(fpTypes, List.of(1d, 1d, 1d));
+        
+        final HumanFace face = getHumanFace(facets, featurePoints, fpTypes);
+        
+        final Map<MeshFacet, List<Double>> expectedPrioritiesMapFP2 = new HashMap<>();
+        final Map<MeshFacet, List<Double>> expectedPrioritiesMapFP3 = new HashMap<>();
+        final List<Double> allZeroList = Collections.nCopies(VERTICES_NUM, 0d);
+        for (final MeshFacet facet: facets) {
+            expectedPrioritiesMapFP2.put(facet, allZeroList);
+            expectedPrioritiesMapFP3.put(facet, allZeroList);
+        }
+        
+        final double vertexDistance = Math.sqrt(Math.pow(0.999 - 1, 2) + Math.pow(0.999 - 0, 2) + Math.pow(0 - 0, 2));
+        final double vertexPriority = 1 - vertexDistance / 1;
+        
+        final List<Double> prioritiesList = List.of(0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, vertexPriority, 0d);
+        expectedPrioritiesMapFP2.put(facet1, prioritiesList);
+        expectedPrioritiesMapFP2.put(facet3, prioritiesList);
+        expectedPrioritiesMapFP3.put(facet1, prioritiesList);
+        expectedPrioritiesMapFP3.put(facet4, prioritiesList);
+        final Map<FeaturePointType, Map<MeshFacet, List<Double>>> expectedPriorities = Map.of(fpType1, expectedPrioritiesMapFP1,
+                fpType2, expectedPrioritiesMapFP2,
+                fpType3, expectedPrioritiesMapFP3);
+        
+        final Map<MeshFacet, Double> expectedWeightedDistancesMapFP2 = new HashMap<>();
+        final Map<MeshFacet, Double> expectedWeightedDistancesMapFP3 = new HashMap<>();
+        for (final MeshFacet facet: facets) {
+            expectedWeightedDistancesMapFP2.put(facet, Double.NaN);
+            expectedWeightedDistancesMapFP3.put(facet, Double.NaN);
+        }
+        final double weightedDistance = (0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 * vertexPriority + 0) / prioritiesList.stream()
+                .mapToDouble(Double::doubleValue)
+                .sum();
+        expectedWeightedDistancesMapFP2.put(facet1, weightedDistance);
+        expectedWeightedDistancesMapFP2.put(facet3, weightedDistance);
+        expectedWeightedDistancesMapFP3.put(facet1, weightedDistance);
+        expectedWeightedDistancesMapFP3.put(facet4, weightedDistance);
+        final Map<FeaturePointType, Map<MeshFacet, Double>> expectedFeaturePointsWeights = Map.of(fpType1, expectedWeightedDistancesMapFP1,
+                fpType2, expectedWeightedDistancesMapFP2,
+                fpType3, expectedWeightedDistancesMapFP3);
+        
+        final Map<MeshFacet, List<Double>> expectedMergedPrioritiesMap = new HashMap<>();
+        for (final MeshFacet facet: facets) {
+            expectedMergedPrioritiesMap.put(facet, prioritiesListFP1);
+        }
+        final List<Double> mergedPriorities = List.of(1d, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, vertexPriority, 0d);
+        expectedMergedPrioritiesMap.put(facet1, mergedPriorities);
+        expectedMergedPrioritiesMap.put(facet3, mergedPriorities);
+        expectedMergedPrioritiesMap.put(facet4, mergedPriorities);
+        
+        final HausdorffDistancePrioritized visitor = new HausdorffDistancePrioritized(getHumanFace(facets2, List.of(), List.of()),
+                featurePointTypes,
+                POINT_TO_POINT,
+                true,
+                false);
+        
+        performTest(face, expectedPriorities, expectedFeaturePointsWeights, expectedMergedPrioritiesMap, visitor);
+    }
+    
+    @Test
+    public void fourFeaturePointsSingleFacetIntersecParallelTest() throws IOException {
+        final List<Point3d> featurePoints = List.of(featurePoint1, new Point3d(1, 0, 0), new Point3d(0, 1, 0), new Point3d(0, 0, 1));
+        final FeaturePointType fpType2 = new FeaturePointType(1, null, null, null);
+        final FeaturePointType fpType3 = new FeaturePointType(2, null, null, null);
+        final FeaturePointType fpType4 = new FeaturePointType(3, null, null, null);
+        final List<FeaturePointType> fpTypes = List.of(fpType1, fpType2, fpType3, fpType4);
+        final Map<FeaturePointType, Double> featurePointTypes = zipListsToMap(fpTypes, List.of(1d, 1d, 1d, 1d));
+        
+        final HumanFace face = getHumanFace(facets, featurePoints, fpTypes);
+        
+        final Map<MeshFacet, List<Double>> expectedPrioritiesMapFP2 = new HashMap<>();
+        final Map<MeshFacet, List<Double>> expectedPrioritiesMapFP3 = new HashMap<>();
+        final Map<MeshFacet, List<Double>> expectedPrioritiesMapFP4 = new HashMap<>();
+        final List<Double> allZeroList = Collections.nCopies(VERTICES_NUM, 0d);
+        for (final MeshFacet facet: facets) {
+            expectedPrioritiesMapFP2.put(facet, allZeroList);
+            expectedPrioritiesMapFP3.put(facet, allZeroList);
+            expectedPrioritiesMapFP4.put(facet, allZeroList);
+        }
+        final List<Double> prioritiesList = List.of(0d, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1d, 0.9);
+        expectedPrioritiesMapFP2.put(facet1, prioritiesList);
+        expectedPrioritiesMapFP3.put(facet3, prioritiesList);
+        expectedPrioritiesMapFP4.put(facet5, prioritiesList);
+        final Map<FeaturePointType, Map<MeshFacet, List<Double>>> expectedPriorities = Map.of(fpType1, expectedPrioritiesMapFP1,
+                fpType2, expectedPrioritiesMapFP2,
+                fpType3, expectedPrioritiesMapFP3,
+                fpType4, expectedPrioritiesMapFP4);
+        
+        final Map<MeshFacet, Double> expectedWeightedDistancesMapFP2 = new HashMap<>();
+        final Map<MeshFacet, Double> expectedWeightedDistancesMapFP3 = new HashMap<>();
+        final Map<MeshFacet, Double> expectedWeightedDistancesMapFP4 = new HashMap<>();
+        for (final MeshFacet facet: facets) {
+            expectedWeightedDistancesMapFP2.put(facet, Double.NaN);
+            expectedWeightedDistancesMapFP3.put(facet, Double.NaN);
+            expectedWeightedDistancesMapFP4.put(facet, Double.NaN);
+        }
+        final double weightedDistance = (0 + 0.01 + 0.04 + 0.09 + 0.16 + 0.25 + 0.36 + 0.49 + 0.64 + 0.81 + 1 + 0.99) / prioritiesList.stream()
+                .mapToDouble(Double::doubleValue)
+                .sum();
+        expectedWeightedDistancesMapFP2.put(facet1, weightedDistance);
+        expectedWeightedDistancesMapFP3.put(facet3, weightedDistance);
+        expectedWeightedDistancesMapFP4.put(facet5, -weightedDistance);
+        final Map<FeaturePointType, Map<MeshFacet, Double>> expectedFeaturePointsWeights = Map.of(fpType1, expectedWeightedDistancesMapFP1,
+                fpType2, expectedWeightedDistancesMapFP2,
+                fpType3, expectedWeightedDistancesMapFP3,
+                fpType4, expectedWeightedDistancesMapFP4);
+        
+        final Map<MeshFacet, List<Double>> expectedMergedPrioritiesMap = new HashMap<>();
+        for (final MeshFacet facet: facets) {
+            expectedMergedPrioritiesMap.put(facet, prioritiesListFP1);
+        }
+        final List<Double> mergedPriorities = List.of(1d, 0.9, 0.8, 0.7, 0.6, 0.5, 0.6, 0.7, 0.8, 0.9, 1d, 0.9);
+        expectedMergedPrioritiesMap.put(facet1, mergedPriorities);
+        expectedMergedPrioritiesMap.put(facet3, mergedPriorities);
+        expectedMergedPrioritiesMap.put(facet5, mergedPriorities);
+        
+        final HausdorffDistancePrioritized visitor = new HausdorffDistancePrioritized(getHumanFace(facets2, List.of(), List.of()),
+                featurePointTypes,
+                POINT_TO_POINT,
+                true,
+                true);
+        
+        performTest(face, expectedPriorities, expectedFeaturePointsWeights, expectedMergedPrioritiesMap, visitor);
+    }
+}
diff --git a/Comparison/src/test/java/cz/fidentis/analyst/visitors/kdtree/KdTreeApproxDistToTriTest.java b/Comparison/src/test/java/cz/fidentis/analyst/visitors/kdtree/KdTreeApproxDistToTriTest.java
index 9980ec45e3a5edafde31945ed15b4bffdb796ce8..1151119ee965afe396dcb75cc6e3bc92bc6a18b6 100644
--- a/Comparison/src/test/java/cz/fidentis/analyst/visitors/kdtree/KdTreeApproxDistToTriTest.java
+++ b/Comparison/src/test/java/cz/fidentis/analyst/visitors/kdtree/KdTreeApproxDistToTriTest.java
@@ -1,18 +1,10 @@
 package cz.fidentis.analyst.visitors.kdtree;
 
 import cz.fidentis.analyst.kdtree.KdTree;
-import cz.fidentis.analyst.kdtree.KdTreeVisitor;
 import cz.fidentis.analyst.mesh.core.CornerTableRow;
 import cz.fidentis.analyst.mesh.core.MeshFacet;
 import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
-import cz.fidentis.analyst.mesh.core.MeshPoint;
 import cz.fidentis.analyst.mesh.core.MeshPointImpl;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
 import javax.vecmath.Point3d;
 import javax.vecmath.Vector3d;
 import static org.junit.jupiter.api.Assertions.assertEquals;
diff --git a/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/PrioritySphereTest.java b/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/PrioritySphereTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..4ecf0d7f24a10d35ef8797e2720996fa00f0973e
--- /dev/null
+++ b/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/PrioritySphereTest.java
@@ -0,0 +1,123 @@
+package cz.fidentis.analyst.visitors.mesh;
+
+import cz.fidentis.analyst.mesh.core.CornerTableRow;
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
+import cz.fidentis.analyst.mesh.core.MeshModel;
+import cz.fidentis.analyst.mesh.core.MeshPointImpl;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.DoubleStream;
+import javax.vecmath.Point3d;
+import javax.vecmath.Vector3d;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import org.junit.jupiter.api.Test;
+
+public class PrioritySphereTest {
+    
+    private static final double DELTA = 1e-15;
+    
+    protected MeshFacet getTrivialFacet(int count, double xSpace, double ySpace, double zSpace, int offset) {
+        final MeshFacet facet = new MeshFacetImpl();
+        for (int i = offset; i < count + offset; i++) {
+            facet.addVertex(new MeshPointImpl(new Point3d(xSpace * i, ySpace * i, zSpace * i),
+                    new Vector3d(0, 0, 1),
+                    new Vector3d()));
+            facet.getCornerTable().addRow(new CornerTableRow(i - offset, -1));
+        }
+
+        return facet;
+    }
+    
+    protected void performTest(Map<MeshFacet, List<Double>> facetsWithExpectedPriorities,
+            PrioritySphere visitor,
+            boolean concurrently) {
+
+        final Set<MeshFacet> facets = facetsWithExpectedPriorities.keySet();
+        
+        MeshModel model = new MeshModel();
+//        model.addFacets(new HashSet<>(facets));
+        for (final MeshFacet facet: facets) {
+            model.addFacet(facet);
+        }
+        
+        model.compute(visitor, concurrently);
+        
+        final Map<MeshFacet, List<Double>> priorities = visitor.getPriorities();
+        assertEquals(facetsWithExpectedPriorities.size(), priorities.size());
+        
+        for (final MeshFacet facet: facets) {
+            assertTrue(priorities.containsKey(facet));
+            
+            final List<Double> expectedPriorities = facetsWithExpectedPriorities.get(facet);
+            final List<Double> actualPriorities = priorities.get(facet);
+            assertEquals(expectedPriorities.size(), actualPriorities.size());
+            
+            for (int i = 0; i < expectedPriorities.size(); i++) {
+                assertEquals(expectedPriorities.get(i), actualPriorities.get(i), DELTA);
+            }
+        }
+    }
+    
+    @Test
+    public void variousPrioritiesTest() {
+        final List<Double> priorities = List.of(1d, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0d, 0d);
+        final Map<MeshFacet, List<Double>> expected = new HashMap<>();
+        expected.put(getTrivialFacet(12, 1, 0, 0, 0), priorities);
+        expected.put(getTrivialFacet(12, -1, 0, 0, 0), priorities);
+        expected.put(getTrivialFacet(12, 0, 1, 0, 0), priorities);
+        expected.put(getTrivialFacet(12, 0, -1, 0, 0), priorities);
+        expected.put(getTrivialFacet(12, 0, 0, 1, 0), priorities);
+        expected.put(getTrivialFacet(12, 0, 0, -1, 0), priorities);
+        
+        final PrioritySphere visitor = new PrioritySphere(new Point3d(0, 0, 0), 10);
+        
+        performTest(expected, visitor, false);
+    }
+    
+    @Test
+    public void allZeroPrioritiesTest() {
+        final Map<MeshFacet, List<Double>> expected = new HashMap<>();
+        expected.put(getTrivialFacet(1, 3, 0, 0, 1), List.of(0d));
+        expected.put(getTrivialFacet(5, 0, 3, 0, 1), List.of(0d, 0d, 0d, 0d, 0d));
+        expected.put(getTrivialFacet(3, -3, -3, -3, 1), List.of(0d, 0d, 0d));
+        
+        final PrioritySphere visitor = new PrioritySphere(new Point3d(0, 0, 0), 3);
+        
+        performTest(expected, visitor, false);
+    }
+    
+    @Test
+    public void noZeroPriorityTest() {
+        final Map<MeshFacet, List<Double>> expected = new HashMap<>();
+        expected.put(getTrivialFacet(1, 10, 0, 0, 1), List.of(0.9));
+        expected.put(getTrivialFacet(5, 0, -20, 0, 0), List.of(1d, 0.8, 0.6, 0.4, 0.2));
+        expected.put(getTrivialFacet(100, 0, 0, -1, 0), DoubleStream.iterate(1, d -> d > 0d, d -> d - 0.01)
+                .boxed()
+                .collect(Collectors.toList()));
+        
+        final PrioritySphere visitor = new PrioritySphere(new Point3d(0, 0, 0), 100);
+        
+        performTest(expected, visitor, false);
+    }
+    
+    @Test
+    public void concurrencyTest() {
+        final List<Double> priorities = List.of(1d, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0d, 0d);
+        final Map<MeshFacet, List<Double>> expected = new HashMap<>();
+        expected.put(getTrivialFacet(12, 1, 0, 0, 0), priorities);
+        expected.put(getTrivialFacet(12, -1, 0, 0, 0), priorities);
+        expected.put(getTrivialFacet(12, 0, 1, 0, 0), priorities);
+        expected.put(getTrivialFacet(12, 0, -1, 0, 0), priorities);
+        expected.put(getTrivialFacet(12, 0, 0, 1, 0), priorities);
+        expected.put(getTrivialFacet(12, 0, 0, -1, 0), priorities);
+        
+        final PrioritySphere visitor = new PrioritySphere(new Point3d(0, 0, 0), 10);
+        
+        performTest(expected, visitor, true);
+    }
+}
diff --git a/GUI/pom.xml b/GUI/pom.xml
index ec98cb3bbcd037dceaeaef3087a9155125d14a74..fb40f611a7f0d5353f2c5c2a594e45dc574c071b 100644
--- a/GUI/pom.xml
+++ b/GUI/pom.xml
@@ -4,7 +4,7 @@
     <parent>
         <groupId>cz.fidentis</groupId>
         <artifactId>FIDENTIS-Analyst-parent</artifactId>
-        <version>2.1.4</version>
+        <version>2021.10</version>
     </parent>
     <artifactId>GUI</artifactId>
     <packaging>nbm</packaging>
@@ -76,6 +76,17 @@
             <artifactId>org-openide-modules</artifactId>
             <version>${netbeans.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.netbeans.api</groupId>
+            <artifactId>org-openide-filesystems-nb</artifactId>
+            <version>${netbeans.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.netbeans.api</groupId>
+            <artifactId>org-netbeans-modules-options-api</artifactId>
+            <version>${netbeans.version}</version>
+            <type>jar</type>
+        </dependency>
         <dependency>
             <groupId>org.jogamp.gluegen</groupId>
             <artifactId>gluegen-rt-main</artifactId>
diff --git a/GUI/src/main/java/cz/fidentis/analyst/canvas/Canvas.java b/GUI/src/main/java/cz/fidentis/analyst/canvas/Canvas.java
new file mode 100644
index 0000000000000000000000000000000000000000..ff729528a902657c1baaf1e22ff3b2fc6e7cf357
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/canvas/Canvas.java
@@ -0,0 +1,202 @@
+package cz.fidentis.analyst.canvas;
+
+import com.jogamp.opengl.GLCapabilities;
+import com.jogamp.opengl.GLProfile;
+import com.jogamp.opengl.awt.GLCanvas;
+import cz.fidentis.analyst.face.HumanFace;
+import cz.fidentis.analyst.scene.Camera;
+import cz.fidentis.analyst.scene.Scene;
+import cz.fidentis.analyst.scene.SceneRenderer;
+import java.awt.BorderLayout;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+
+import javax.swing.JLayeredPane;
+import javax.swing.JPanel;
+
+/**
+ * OpenGL canvas.
+ * 
+ * @author Natalia Bebjakova 
+ * @author Radek Oslejsek
+ */
+public class Canvas extends JPanel {
+
+    // Scene components:
+    private Scene scene;
+    private final SceneRenderer sceneRenderer;
+    private final Camera camera = new Camera();
+    
+    // Listeners:
+    private final CanvasListener listener;
+    private final MouseRotationListener manipulator;
+    
+    // GUI elements:
+    private JLayeredPane layeredPane;
+    private JPanel canvasPanel;
+    private ControlButtons controlButtonsPanel;
+    private GLCanvas glCanvas;
+    
+    
+    /**
+     * Constructor.
+     */
+    public Canvas() {
+        sceneRenderer = new SceneRenderer();
+        listener = new CanvasListener(this);
+        manipulator = new MouseRotationListener(this);
+        
+        initComponents();
+    }
+    
+    /**
+     * Initializes the scene for a single face. Can be called only once.
+     * 
+     * @param face Human face
+     * @throws UnsupportedOperationException the the scene is already initiated
+     * @throws IllegalArgumentException if the face is missing
+     */
+    public void initScene(HumanFace face) {
+        if (scene != null) {
+            throw new UnsupportedOperationException("Scene already exists");
+        }
+        this.scene = new Scene(face);
+    }
+    
+    /**
+     * Initializes the scene for the 1:1 comparison. Can be called only once.
+     * 
+     * @param primary Primary face
+     * @param secondary Secondary face
+     * @throws UnsupportedOperationException the the scene is already initiated
+     * @throws IllegalArgumentException if some face is missing
+     */
+    public void initScene(HumanFace primary, HumanFace secondary) {
+        if (scene != null) {
+            throw new UnsupportedOperationException("Scene already exists");
+        }
+        this.scene = new Scene(primary, secondary);
+    }
+   
+    /**
+     * Returns the scene
+     * @return the scene
+     */
+    public SceneRenderer getSceneRenderer() {
+        return sceneRenderer;
+    }
+    
+    /**
+     * Renders the scene.
+     */
+    public void renderScene() {
+        glCanvas.display();
+    }
+    
+    /**
+     * Returns the scene. 
+     * 
+     * @return the scene.
+     */
+    public Scene getScene() {
+        return scene;
+    }
+    
+    /**
+     * Returns camera. 
+     * 
+     * @return camera
+     */
+    public Camera getCamera() {
+        return camera;
+    }
+    
+    /**
+     * Returns the underlying OpenGL canvas.
+     * 
+     * @return the underlying OpenGL canvas.
+     */
+    public GLCanvas getGLCanvas() {
+        return this.glCanvas;
+    }
+
+    
+    /**
+     * Sets background color
+     * 
+     * @param dark If {@code true}, then dark background is set
+     */
+    public void setDarkBackground(boolean dark) {
+        if (dark) {
+            canvasPanel.setBackground(SceneRenderer.DARK_BACKGROUND);
+            sceneRenderer.setDarkBackground();
+        } else {
+            canvasPanel.setBackground(SceneRenderer.BRIGHT_BACKGROUND);
+            sceneRenderer.setBrightBackground();
+        }
+    }
+    
+    private ControlButtons getButtonsPanel(Canvas canvas) {
+        ControlButtonsAction controlButtonsListener = new ControlButtonsAction(canvas);
+        ControlButtons ret = new ControlButtons(controlButtonsListener);
+        ret.setOpaque(false);
+        ret.setBounds(20, 20, ControlButtons.SIZE.width, ControlButtons.SIZE.height);
+        return ret;
+    }
+    
+    private void initComponents() {
+        setLayout(new BorderLayout());
+
+        initGLCanvas();
+        canvasPanel = new JPanel();
+        canvasPanel.setLayout(new BorderLayout());
+        canvasPanel.add(glCanvas);
+        
+        controlButtonsPanel = getButtonsPanel(this);
+        
+        layeredPane = new JLayeredPane();
+        layeredPane.add(canvasPanel, 1);
+        layeredPane.add(controlButtonsPanel, 0);
+        add(layeredPane, BorderLayout.CENTER);
+        
+        setDarkBackground(true);
+        
+        addComponentListener(new ComponentAdapter() {
+            @Override
+            public void componentResized(ComponentEvent e) {
+                canvasPanel.setBounds(0, 0, layeredPane.getWidth(), layeredPane.getHeight());
+                glCanvas.setBounds(layeredPane.getX(), layeredPane.getY(), layeredPane.getWidth(), layeredPane.getHeight());
+                /*
+                OutputWindow.print("Canvas resized event:  ");
+                OutputWindow.print("- Canvas: " + getWidth() + "x" + getHeight());
+                OutputWindow.print("- Layered Pane: " + layeredPane.getWidth() + "x" + layeredPane.getHeight());
+                OutputWindow.print("- Canvas Panel: " + canvasPanel.getWidth() + "x" + canvasPanel.getHeight());
+                OutputWindow.print("- GL Canvas: " + glCanvas.getWidth() + "x" + glCanvas.getHeight());
+                OutputWindow.print("- Parent1: " + getParent().getWidth() + "x" + getParent().getHeight());
+                OutputWindow.print("- Parent2: " + getParent().getParent().getWidth() + "x" + getParent().getParent().getHeight());
+                OutputWindow.print("- Parent3: " + getParent().getParent().getParent().getWidth() + "x" + getParent().getParent().getParent().getHeight());
+                */
+            }
+        });
+    }
+    
+    private void initGLCanvas() {
+        // gl version 2 is used
+        GLCapabilities capabilities = new GLCapabilities(GLProfile.get(GLProfile.GL2));
+        capabilities.setDoubleBuffered(true);
+       
+        // creates new glCanvas panel for displaying model
+        glCanvas = new GLCanvas(capabilities);
+        glCanvas.setVisible(true);     
+        
+        // enables glCanvas to react to events
+        glCanvas.requestFocusInWindow();        
+        //glCanvas.setSize(getWidth() - getInsets().left - getInsets().right, getHeight() - getInsets().top - getInsets().bottom);
+
+        glCanvas.addGLEventListener(listener);
+        glCanvas.addMouseListener(manipulator);
+        glCanvas.addMouseMotionListener(manipulator);
+        glCanvas.addMouseWheelListener(manipulator);        
+    }
+    
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/canvas/CanvasListener.java b/GUI/src/main/java/cz/fidentis/analyst/canvas/CanvasListener.java
similarity index 78%
rename from GUI/src/main/java/cz/fidentis/analyst/gui/canvas/CanvasListener.java
rename to GUI/src/main/java/cz/fidentis/analyst/canvas/CanvasListener.java
index d8fbc1c9236e321ea829072988895a53fda7e7ca..d99a737131edc12be52c93ab9c50c1b342e6a4d7 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/canvas/CanvasListener.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/canvas/CanvasListener.java
@@ -1,4 +1,4 @@
-package cz.fidentis.analyst.gui.canvas;
+package cz.fidentis.analyst.canvas;
 
 import com.jogamp.opengl.GLAutoDrawable;
 import com.jogamp.opengl.GLEventListener;
@@ -38,13 +38,15 @@ public class CanvasListener implements GLEventListener {
 
     @Override
     public void display(GLAutoDrawable glad) {
-        //System.out.println("CanvasListener.display " + this.toString());
-        canvas.getSceneRenderer().renderScene(canvas.getCamera(), canvas.getScene().getDrawables());
+        canvas.getSceneRenderer().renderScene(canvas.getCamera(), canvas.getScene().getAllDrawables());
+        //OutputWindow.print("3D canvas has been rendered, window size " 
+        //        + canvas.getWidth() + "x" + canvas.getHeight()
+        //        +", GL canvas size " + canvas.getGLCanvas().getWidth() + "x" + canvas.getGLCanvas().getHeight()
+        //);
     }
 
     @Override
     public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) {
-        //System.out.println("CanvasListener.reshape");
         canvas.getSceneRenderer().setViewport(x, y, width, height);
     }
     
diff --git a/GUI/src/main/java/cz/fidentis/analyst/canvas/ControlButtons.java b/GUI/src/main/java/cz/fidentis/analyst/canvas/ControlButtons.java
new file mode 100644
index 0000000000000000000000000000000000000000..eef8a830a104bc41972855a7288809c39e61c471
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/canvas/ControlButtons.java
@@ -0,0 +1,152 @@
+package cz.fidentis.analyst.canvas;
+
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+/**
+ * The control panel inside the canvas.
+ * 
+ * @author Radek Oslejsek
+ */
+public class ControlButtons extends JPanel {
+    
+    public static final Dimension SIZE = new Dimension(90,120);
+    
+    /**
+     * Constructor.
+     * 
+     * @param actionListener Action listener
+     */
+    public ControlButtons(ActionListener actionListener) {
+        setLayout(new GridBagLayout());
+        setPreferredSize(SIZE);
+        setMaximumSize(SIZE);
+        setMinimumSize(SIZE);
+        
+        setListner(
+                addButton(1, 0, "upButton.png"), 
+                actionListener, 
+                ControlButtonsAction.ACTION_COMMAND_UP_PRESSED, 
+                ControlButtonsAction.ACTION_COMMAND_UP_RELEASED
+        );
+        
+        setListner(
+                addButton(0, 1, "leftButton.png"), 
+                actionListener, 
+                ControlButtonsAction.ACTION_COMMAND_LEFT_PRESSED, 
+                ControlButtonsAction.ACTION_COMMAND_LEFT_RELEASED
+        );
+        
+        addButton(1, 1, "resetButton.png").addMouseListener(new MouseAdapter() {
+            @Override
+            public void mouseClicked(MouseEvent evt) {
+                actionListener.actionPerformed(new ActionEvent(
+                        evt.getSource(), 
+                        ActionEvent.ACTION_PERFORMED, 
+                        ControlButtonsAction.ACTION_COMMAND_RESET)
+                );
+            }
+        });
+
+        setListner(
+                addButton(2, 1, "rightButton.png"), 
+                actionListener, 
+                ControlButtonsAction.ACTION_COMMAND_RIGHT_PRESSED, 
+                ControlButtonsAction.ACTION_COMMAND_RIGHT_RELEASED
+        );
+        
+        setListner(
+                addButton(1, 2, "downButton.png"), 
+                actionListener, 
+                ControlButtonsAction.ACTION_COMMAND_DOWN_PRESSED, 
+                ControlButtonsAction.ACTION_COMMAND_DOWN_RELEASED
+        );
+        
+        setListner(
+                addButton(0, 3, "plus.png"), 
+                actionListener, 
+                ControlButtonsAction.ACTION_COMMAND_PLUS_PRESSED, 
+                ControlButtonsAction.ACTION_COMMAND_PLUS_RELEASED
+        );
+
+        setListner(
+                addButton(2, 3, "minus.png"), 
+                actionListener, 
+                ControlButtonsAction.ACTION_COMMAND_MINUS_PRESSED, 
+                ControlButtonsAction.ACTION_COMMAND_MINUS_RELEASED
+        );
+        
+        addBackgroundCross();
+    }
+    
+    private void setListner(JButton button, ActionListener actionListener, String commandPressed, String commandReleased) {
+        button.addMouseListener(new MouseAdapter() {
+            @Override
+            public void mousePressed(MouseEvent evt) {
+                actionListener.actionPerformed(new ActionEvent(
+                        evt.getSource(), 
+                        ActionEvent.ACTION_PERFORMED, 
+                        commandPressed)
+                );
+            }
+            @Override
+            public void mouseReleased(MouseEvent evt) {
+                actionListener.actionPerformed(new ActionEvent(
+                        evt.getSource(), 
+                        ActionEvent.ACTION_PERFORMED, 
+                        commandReleased)
+                );
+            }                
+        });
+
+    }
+    
+    private void addBackgroundCross() {
+        GridBagConstraints c = new GridBagConstraints();
+        c.gridwidth = 3;
+        c.gridheight = 3;
+        c.gridx = 0;
+        c.gridy = 0;
+        c.anchor = GridBagConstraints.CENTER;
+        c.fill = GridBagConstraints.NONE;
+        
+        JLabel label = new JLabel();
+        label.setIcon(new ImageIcon(getClass().getResource("/navigBackground.png")));
+        label.setBorder(BorderFactory.createEmptyBorder());
+        add(label, c);
+    }
+
+    private JButton addButton(int x, int y, String icon) {
+        GridBagConstraints c = new GridBagConstraints();
+        c.gridwidth = 1;
+        c.gridheight = 1;
+        c.gridx = x;
+        c.gridy = y;
+        c.anchor = GridBagConstraints.CENTER;
+        c.fill = GridBagConstraints.NONE;
+        c.insets = new Insets(0,0,0,0);
+        
+        JButton button = new JButton();
+        button.setIcon(new ImageIcon(getClass().getResource("/" + icon)));
+        button.setContentAreaFilled(false);
+        button.setBorderPainted(false);
+        button.setFocusPainted(false);
+        button.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
+        button.setCursor(new Cursor(Cursor.HAND_CURSOR));
+        
+        add(button, c);
+        return button;
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/canvas/ControlButtonsAction.java b/GUI/src/main/java/cz/fidentis/analyst/canvas/ControlButtonsAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..1c3d14abfa84dbf68c34f92dd3f9c00c8a818108
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/canvas/ControlButtonsAction.java
@@ -0,0 +1,84 @@
+package cz.fidentis.analyst.canvas;
+
+import java.awt.event.ActionEvent;
+import javax.swing.AbstractAction;
+
+/**
+ * Action listener for {@link ControlButtons}.
+ * 
+ * @author Radek Oslejsek
+ */
+public class ControlButtonsAction extends AbstractAction {
+    
+    public static final String ACTION_COMMAND_LEFT_PRESSED = "rotate left pressed";
+    public static final String ACTION_COMMAND_LEFT_RELEASED = "rotate left released";
+    public static final String ACTION_COMMAND_RIGHT_PRESSED = "rotate right pressed";
+    public static final String ACTION_COMMAND_RIGHT_RELEASED = "rotate right released";
+    public static final String ACTION_COMMAND_UP_PRESSED = "rotate up pressed";
+    public static final String ACTION_COMMAND_UP_RELEASED = "rotate up released";
+    public static final String ACTION_COMMAND_DOWN_PRESSED = "rotate down pressed";
+    public static final String ACTION_COMMAND_DOWN_RELEASED = "rotate down released";
+    public static final String ACTION_COMMAND_PLUS_PRESSED = "zoom in pressed";
+    public static final String ACTION_COMMAND_PLUS_RELEASED = "zoom in released";
+    public static final String ACTION_COMMAND_MINUS_PRESSED = "zoom out pressed";
+    public static final String ACTION_COMMAND_MINUS_RELEASED = "zoom out released";
+    public static final String ACTION_COMMAND_RESET = "reset";
+    
+    private final RotationAnimator animator;
+    private final Canvas canvas;
+
+    /**
+     * Constructor. 
+     * 
+     * @param canvas OpenGL canvas
+     * @throws IllegalArgumentException if some param is missing
+     */
+    public ControlButtonsAction(Canvas canvas) {
+        if (canvas == null) {
+            throw new IllegalArgumentException("canvas");
+        }
+        this.canvas = canvas;
+        this.animator = new RotationAnimator(canvas.getGLCanvas());
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        String command = e.getActionCommand();
+        
+        switch (command) {
+            case ACTION_COMMAND_LEFT_PRESSED:
+                animator.startAnimation(Direction.ROTATE_LEFT, canvas.getCamera());
+                break;
+            case ACTION_COMMAND_RIGHT_PRESSED:
+                animator.startAnimation(Direction.ROTATE_RIGHT, canvas.getCamera());
+                break;
+            case ACTION_COMMAND_UP_PRESSED:
+                animator.startAnimation(Direction.ROTATE_UP, canvas.getCamera());
+                break;
+            case ACTION_COMMAND_DOWN_PRESSED:
+                animator.startAnimation(Direction.ROTATE_DOWN, canvas.getCamera());
+                break;
+            case ACTION_COMMAND_RESET:
+                canvas.getCamera().initLocation();
+                canvas.renderScene();
+                break;
+            case ACTION_COMMAND_PLUS_PRESSED:
+                animator.startAnimation(Direction.ZOOM_IN, canvas.getCamera());
+                break;
+            case ACTION_COMMAND_MINUS_PRESSED:
+                animator.startAnimation(Direction.ZOOM_OUT, canvas.getCamera());
+                break;
+            case ACTION_COMMAND_LEFT_RELEASED:
+            case ACTION_COMMAND_RIGHT_RELEASED:
+            case ACTION_COMMAND_UP_RELEASED:
+            case ACTION_COMMAND_DOWN_RELEASED:
+            case ACTION_COMMAND_PLUS_RELEASED:
+            case ACTION_COMMAND_MINUS_RELEASED:
+                animator.stopAnimation(canvas.getCamera());
+                break;
+            default:
+                // do nothing
+        }
+    }
+    
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/canvas/Direction.java b/GUI/src/main/java/cz/fidentis/analyst/canvas/Direction.java
new file mode 100644
index 0000000000000000000000000000000000000000..04a8348e70dc6dc4491860d9b1f5d392b816e36e
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/canvas/Direction.java
@@ -0,0 +1,28 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package cz.fidentis.analyst.canvas;
+
+/**
+ *
+ * @author Richard Pajersky
+ */
+public enum Direction {
+        ROTATE_LEFT,
+        ROTATE_RIGHT,
+        ROTATE_UP,
+        ROTATE_DOWN,
+        ROTATE_IN,
+        ROTATE_OUT,
+        ZOOM_IN,
+        ZOOM_OUT,
+        TRANSLATE_LEFT,
+        TRANSLATE_RIGHT,
+        TRANSLATE_UP,
+        TRANSLATE_DOWN,
+        TRANSLATE_IN,
+        TRANSLATE_OUT,
+        NONE
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/canvas/MouseRotationListener.java b/GUI/src/main/java/cz/fidentis/analyst/canvas/MouseRotationListener.java
similarity index 85%
rename from GUI/src/main/java/cz/fidentis/analyst/gui/canvas/MouseRotationListener.java
rename to GUI/src/main/java/cz/fidentis/analyst/canvas/MouseRotationListener.java
index 162bd0d981b6171c1100e40be9308fb96e2abc58..a1800faed3997784b4edf99d243c6777cbdb30f9 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/canvas/MouseRotationListener.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/canvas/MouseRotationListener.java
@@ -1,4 +1,4 @@
-package cz.fidentis.analyst.gui.canvas;
+package cz.fidentis.analyst.canvas;
 
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
@@ -38,11 +38,10 @@ public class MouseRotationListener extends MouseAdapter {
      * Left mouse button dragging rotates
      * Right mouse button dragging moves
      * Middle mouse button dragging resets rotation and zoom
+     * @param evt Mouse position info
      */
     @Override
     public void mouseDragged(MouseEvent evt) {
-        //JOptionPane.showMessageDialog(null, evt.getButton());
-
         if (SwingUtilities.isLeftMouseButton(evt)) {
             double rotateX = -(lastY - evt.getY()) * rotationSpeed;
             double rotateY = +(lastX - evt.getX()) * rotationSpeed;
@@ -68,6 +67,7 @@ public class MouseRotationListener extends MouseAdapter {
 
     /**
      * Actualize mouse movement
+     * @param e Mouse position info
      */
     @Override
     public void mouseMoved(MouseEvent e) {
@@ -77,6 +77,7 @@ public class MouseRotationListener extends MouseAdapter {
 
     /**
      * Zoom in or out based on mouse wheel movement
+     * @param evt Mouse wheel info
      */
     @Override
     public void mouseWheelMoved(MouseWheelEvent evt) {
@@ -90,6 +91,7 @@ public class MouseRotationListener extends MouseAdapter {
     
     /**
      * Middle mouse button click resets rotation and zoom
+     * @param evt Mouse position info
      */
     @Override
     public void mouseClicked(MouseEvent evt) {
@@ -99,18 +101,32 @@ public class MouseRotationListener extends MouseAdapter {
         }
     }
     
+    /**
+     * @return Rotation speed
+     */
     public static double getRotationSpeed() {
         return rotationSpeed;
     }
 
+    /**
+     * Sets rotation speed
+     * @param rotationSpeed 
+     */
     public static void setRotationSpeed(double rotationSpeed) {
         MouseRotationListener.rotationSpeed = rotationSpeed;
     }
 
+    /**
+     * @return Move speed
+     */
     public static double getMoveSpeed() {
         return moveSpeed;
     }
 
+    /**
+     * Sets move speed
+     * @param moveSpeed 
+     */
     public static void setMoveSpeed(double moveSpeed) {
         MouseRotationListener.moveSpeed = moveSpeed;
     }
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/canvas/RotationAnimator.java b/GUI/src/main/java/cz/fidentis/analyst/canvas/RotationAnimator.java
similarity index 84%
rename from GUI/src/main/java/cz/fidentis/analyst/gui/canvas/RotationAnimator.java
rename to GUI/src/main/java/cz/fidentis/analyst/canvas/RotationAnimator.java
index 59a26240dee7168ac92d46d54cf0f041695e29dd..1928b4347dd2d1eca876f47f2d8efe28cc87c559 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/canvas/RotationAnimator.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/canvas/RotationAnimator.java
@@ -1,8 +1,8 @@
-package cz.fidentis.analyst.gui.canvas;
+package cz.fidentis.analyst.canvas;
 
 import com.jogamp.opengl.awt.GLCanvas;
 import com.jogamp.opengl.util.FPSAnimator;
-import cz.fidentis.analyst.gui.scene.Camera;
+import cz.fidentis.analyst.scene.Camera;
 import java.util.Timer;
 import java.util.TimerTask;
 
@@ -15,22 +15,6 @@ import java.util.TimerTask;
  */
 public class RotationAnimator {
     
-    /**
-     * @author Radek Oslejsek
-     */
-    public enum Direction {
-        ROTATE_LEFT,
-        ROTATE_RIGHT,
-        ROTATE_UP,
-        ROTATE_DOWN,
-        ZOOM_IN,
-        ZOOM_OUT,
-        NONE
-    }
-    
-    private final Camera camera;
-        
-    
     /**
      * Frequency of the rotation or zoom animations
      */
@@ -54,17 +38,16 @@ public class RotationAnimator {
      * Constructor.
      * 
      * @param glCanvas OpenGL canvas
-     * @param camera Camera
      * @throws IllegalArgumentException if some argument is missing
      */
-    public RotationAnimator(GLCanvas glCanvas, Camera camera) {
+    public RotationAnimator(GLCanvas glCanvas) {
         if (glCanvas == null) {
             throw new IllegalArgumentException("glCanvas is null");
         }
-        if (camera == null) {
-            throw new IllegalArgumentException("camera is null");
-        }
-        this.camera = camera;
+        //if (camera == null) {
+        //    throw new IllegalArgumentException("camera is null");
+        //}
+        //this.camera = camera;
         this.animator = new FPSAnimator(glCanvas, FPS, true);
     }
     
@@ -74,7 +57,7 @@ public class RotationAnimator {
      * @param dir Animation direction
      * @throws UnsupportedOperationException if there is unfinished animation
      */
-    public void startAnimation(Direction dir) {
+    public void startAnimation(Direction dir, Camera camera) {
         if (this.direction != Direction.NONE) {
             throw new UnsupportedOperationException(); // this should no happen
         }
@@ -117,7 +100,7 @@ public class RotationAnimator {
     /**
      * Stops the animation.
      */
-    public void stopAnimation() {
+    public void stopAnimation(Camera camera) {
         timer.cancel();
         if ((System.currentTimeMillis() - startClickTime) < 500) {
             switch (direction) {
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/ControlPanel.java b/GUI/src/main/java/cz/fidentis/analyst/core/ControlPanel.java
new file mode 100644
index 0000000000000000000000000000000000000000..65eab763b3aafd2d5caa29bde27cd0b710aeaf65
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/core/ControlPanel.java
@@ -0,0 +1,86 @@
+package cz.fidentis.analyst.core;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import javax.swing.AbstractAction;
+import javax.swing.ImageIcon;
+import javax.swing.JPanel;
+
+/**
+ * An abstract class for control panels that can be docked in the {@link TopControlPanel}.
+ * 
+ * @author Radek Oslejsek
+ */
+public abstract class ControlPanel extends JPanel {
+    
+    public static final int CONTROL_PANEL_WIDTH = 600;
+    
+    /*
+     * Handled actions
+     */
+    public static final String ACTION_COMMAND_SHOW_HIDE_PANEL = "show-hide control panel";
+    
+    /**
+     * Returns panel's icon.
+     * 
+     * @return panel's icon
+     */
+    public abstract ImageIcon getIcon();
+    
+    /**
+     * Registers action listeners that are invoked when an extrinsic state 
+     * of the control panel is changed.
+     * 
+     * @param action Action listener
+     */
+    //public void addActionListener(ActionListener action) {
+        
+    //}
+    
+    /**
+     * Creates and returns action listener that can be connected with a low-level 
+     * GUI element (e.g., a button). Action event of the low-level element is then
+     * re-directed to the given {@code ControlPanelAction} as given command.
+     * 
+     * @param action An instance of the {@link ControlPanelAction}
+     * @param command Control panel command
+     * @return Action listener
+     */
+    protected final ActionListener createListener(ActionListener action, String command) {
+        return new AbstractAction() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                action.actionPerformed(new ActionEvent(
+                        e.getSource(), 
+                        ActionEvent.ACTION_PERFORMED, 
+                        command)
+                ); 
+            }  
+        };
+    }
+    
+    /**
+     * Creates and returns action listener that can be connected with a low-level 
+     * GUI element (e.g., a button). Action event of the low-level element is then
+     * re-directed to the given {@code ControlPanelAction} as given command.
+     * The listener may also carry additional data as a payload.
+     * 
+     * @param action An instance of the {@link ControlPanelAction}
+     * @param command Control panel command
+     * @param data Payload data of the action listener
+     * @return Action listener
+     */
+    protected final ActionListener createListener(ActionListener action, String command, Object data) {
+        return new AbstractAction() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                action.actionPerformed(new LoadedActionEvent(
+                        e.getSource(), 
+                        ActionEvent.ACTION_PERFORMED, 
+                        command,
+                        data)
+                ); 
+            }  
+        };
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/ControlPanelAction.java b/GUI/src/main/java/cz/fidentis/analyst/core/ControlPanelAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..045fcfbec9be0971d9d19a788fc132f4975011cd
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/core/ControlPanelAction.java
@@ -0,0 +1,93 @@
+package cz.fidentis.analyst.core;
+
+import cz.fidentis.analyst.canvas.Canvas;
+import cz.fidentis.analyst.scene.DrawableFace;
+import cz.fidentis.analyst.scene.DrawableFeaturePoints;
+import cz.fidentis.analyst.scene.Scene;
+import java.awt.event.ActionEvent;
+import javax.swing.AbstractAction;
+import javax.swing.JTabbedPane;
+import javax.swing.JToggleButton;
+
+/**
+ * Default action listener used to connect specific control panel with the rest of
+ * the analytical tab, i.e. canvas and toolbar(s)
+ * 
+ * @author Radek Oslejsek
+ */
+public abstract class ControlPanelAction extends AbstractAction {
+    
+    /*
+     * Top component - the space delimited for placing control panels
+     */
+    private final JTabbedPane topControlPanel;
+    
+    /**
+     * Canvas component
+     */
+    private final Canvas canvas;
+    
+    /**
+     * Constructor. 
+     * 
+     * @param canvas OpenGL canvas
+     * @param topControlPanel Top component for placing control panels
+     * @throws IllegalArgumentException if some param is missing
+     */
+    public ControlPanelAction(Canvas canvas, JTabbedPane topControlPanel) {
+        if (canvas == null) {
+            throw new IllegalArgumentException("canvas");
+        }
+        if (topControlPanel == null) {
+            throw new IllegalArgumentException("topControlPanel");
+        }
+        this.canvas = canvas;
+        this.topControlPanel = topControlPanel;
+    }
+    
+    @Override
+    public abstract void actionPerformed(ActionEvent ae);
+    
+    protected Canvas getCanvas() {
+        return canvas;
+    }
+    
+    /**
+     * The generic code for showing/hiding the control panel
+     * 
+     * @param ae Action event
+     */
+    protected void hideShowPanelActionPerformed(ActionEvent ae, ControlPanel controlPanel) {
+        if (((JToggleButton) ae.getSource()).isSelected()) {
+            topControlPanel.addTab(controlPanel.getName(), controlPanel.getIcon(), controlPanel);
+            topControlPanel.setSelectedComponent(controlPanel); // focus
+        } else {
+            topControlPanel.remove(controlPanel);
+        }
+    }
+    
+    protected Scene getScene() {
+        return canvas.getScene();
+    }
+    
+    protected DrawableFace getPrimaryDrawableFace() {
+        return (canvas.getScene() != null) ? canvas.getScene().getDrawableFace(0) : null;
+    }
+    
+    protected DrawableFace getSecondaryDrawableFace() {
+        return (canvas.getScene() != null) ? canvas.getScene().getDrawableFace(1) : null;
+    }
+    
+    protected DrawableFeaturePoints getPrimaryFeaturePoints() {
+        return (canvas.getScene() != null) ? canvas.getScene().getDrawableFeaturePoints(0) : null;
+    }
+    
+    protected DrawableFeaturePoints getSecondaryFeaturePoints() {
+        return (canvas.getScene() != null) ? canvas.getScene().getDrawableFeaturePoints(1) : null;
+    }
+
+    protected void renderScene() {
+        canvas.renderScene();
+    }
+    
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/ControlPanelBuilder.java b/GUI/src/main/java/cz/fidentis/analyst/core/ControlPanelBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..c06df4d81c9834cda84942f620767527715b4fa3
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/core/ControlPanelBuilder.java
@@ -0,0 +1,732 @@
+package cz.fidentis.analyst.core;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.math.RoundingMode;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import javax.swing.AbstractAction;
+import javax.swing.Box;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JFormattedTextField;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSlider;
+import javax.swing.JTextField;
+import javax.swing.event.ChangeEvent;
+import javax.swing.text.NumberFormatter;
+
+/**
+ * Builder for control panels. Layout is based on GridBagLayout. 
+ * 
+ * @author Radek Oslejsek
+ * @author Daniel Schramm
+ */
+public class ControlPanelBuilder {
+    
+    public static final Font CAPTION_FONT = new Font("Arial", 1, 18);
+    public static final Insets CAPTION_PADDING = new Insets(20, 0, 20, 0);  // top, left, bottom, right
+    public static final ImageIcon HELP_ICON = new ImageIcon(ControlPanelBuilder.class.getResource("/info.png"));
+    public static final Font OPTION_TEXT_FONT = new Font("Arial", 1, 14);
+    public static final Color OPTION_TEXT_COLOR = new Color(20, 114, 105);
+    public static final int OPTION_TEXT_WIDTH = 20; // number of cells
+    public static final int SLIDER_WIDTH = 20; // number of cells
+    public static final int BUTTON_WIDTH = 12; // number of cells
+    
+    public static final int NUMBER_OF_FRACTION_DIGITS = 3;
+    
+    public static final String TEXT_FIELD_BUTTON_PRESSED_PLUS = "plus-pressed";
+    public static final String TEXT_FIELD_BUTTON_PRESSED_MINUS = "minus-pressed";
+    
+    private static final double PERCENTAGE_VALUE_MINIMUM = 0.0;
+    private static final double PERCENTAGE_VALUE_MAXIMUM = 1.0;
+    
+    private JPanel controlPanel;
+    private int row = 0;
+    private int col = 0;
+    
+    /**
+     * Constructor.
+     * 
+     * @param controlPanel Control panel to which the GUI elements are inserted.
+     */
+    public ControlPanelBuilder(JPanel controlPanel) {
+        if (controlPanel == null) {
+            throw new IllegalArgumentException("controlPanel");
+        }
+        this.controlPanel = controlPanel;
+        GridBagLayout layout = new GridBagLayout();
+        this.controlPanel.setLayout(layout);
+    }
+    
+    /**
+     * Helper method that parses and returns integer from the input field taking
+     * Locale into consideration.
+     * 
+     * @param inputField The input field
+     * @return Integer or 0
+     */
+    public static int parseLocaleInt(JTextField inputField) {
+        NumberFormat format = NumberFormat.getInstance(Locale.getDefault());
+        try {
+            Number number = format.parse(inputField.getText());
+            return number.intValue();
+        } catch (ParseException ex) {
+            return 0;
+        }
+    }
+    
+    /**
+     * Helper method that parses and returns floating point number from the input field 
+     * taking Locale into consideration.
+     * 
+     * @param inputField The input field
+     * @return Double or 0.0
+     */
+    public static double parseLocaleDouble(JTextField inputField) {
+        NumberFormat format = NumberFormat.getInstance(Locale.getDefault());
+        try {
+            Number number = format.parse(inputField.getText());
+            return number.doubleValue();
+        } catch (ParseException ex) {
+            return 0;
+        }
+    }
+    
+    /**
+     * Converts number into the text taking into account Locale.
+     * 
+     * @param value Number
+     * @return Text representation of given number
+     */
+    public static String intToStringLocale(int value) {
+        return ""+value;
+    }
+    
+    /**
+     * Converts number into the text taking into account Locale.
+     * 
+     * @param value Number
+     * @return Text representation of given number
+     */
+    public static String doubleToStringLocale(double value) {
+        NumberFormat formatter = DecimalFormat.getInstance(Locale.getDefault());
+        formatter.setMinimumFractionDigits(1);
+        formatter.setMaximumFractionDigits(NUMBER_OF_FRACTION_DIGITS);
+        formatter.setRoundingMode(RoundingMode.HALF_UP);
+        return formatter.format(value);
+    }
+    
+    /**
+     * Adds a line with caption.
+     * 
+     * @param caption Caption text.
+     * @return This new GUI object
+     */
+    public JLabel addCaptionLine(String caption) {
+        GridBagConstraints c = new GridBagConstraints();
+        c.insets = CAPTION_PADDING; 
+        
+        JLabel label = addLabelLineCustom(caption, c);
+        label.setFont(CAPTION_FONT);
+        
+        //addLine();
+        return label;
+    }
+    
+    /**
+     * Adds a line with a plain text label.
+     * 
+     * @param text Text of the label
+     * @return This new GUI object
+     */
+    public JLabel addLabelLine(String text) {
+        return addLabelLineCustom(text, new GridBagConstraints());
+    }
+    
+    /**
+     * Adds a line with a plain text label whose appearance can be further
+     * customized by {@code constraints}.
+     * 
+     * @param text Text of the label
+     * @param constraints {@code GridBagConstraints} to customize the label
+     * @return This new GUI object
+     */
+    private JLabel addLabelLineCustom(String text, GridBagConstraints constraints) {
+        constraints.gridwidth = GridBagConstraints.REMAINDER;
+        constraints.gridx = col;
+        constraints.gridy = row;
+        constraints.anchor = GridBagConstraints.LINE_START;
+        constraints.fill = GridBagConstraints.NONE;
+        
+        JLabel label = new JLabel(text);
+        controlPanel.add(label, constraints);
+        
+        return label;
+    }
+    
+    /**
+     * Adds a line with slider option.
+     * 
+     * @param helpAction Action listener invoked when the help icon is clicked.
+     *                   If {@code null}, then no help is shown.
+     * @param text Option text.
+     * @param sliderMax Max value of the slider (and the value field).
+     *                  If {@code -1}, then percentage slider is shown with 100 as the max. value.
+     * @param inputAction Action listener invoked when the value is changed.
+     * @return Text field associated with the slider
+     */
+    public JTextField addSliderOptionLine(ActionListener helpAction, String text, int sliderMax, ActionListener inputAction) {
+        if (helpAction != null) {
+            addOptionHelpIcon(helpAction);
+        } else {
+            col++;
+        }
+        addOptionText((text == null) ? "" : text);
+        
+        return addSliderWithVal(sliderMax, inputAction);
+    }
+    
+    /**
+     * Adds a line with slider with buttons option.
+     * 
+     * @param helpAction Action listener invoked when the help icon is clicked.
+     *                   If {@code null}, then no help is shown.
+     * @param text Option text.
+     * @param sliderMax Max value of the slider (and the value field).
+     *                  If {@code -1}, then percentage slider is shown with 100 as the max. value.
+     * @param stepSize Size of an increment/decrement of the slider value on a plus/minus button click.
+     *                 If the {@code stepSize} is negative, the step size will be set to 1
+     *                 (or 1 % in case of a percentage slider).
+     * @param inputAction Action listener invoked when the value is changed.
+     * @return Text field associated with the slider
+     */
+    public JTextField addSliderButtonedOptionLine(ActionListener helpAction, String text, int sliderMax, double stepSize, ActionListener inputAction) {
+        if (helpAction != null) {
+            addOptionHelpIcon(helpAction);
+        } else {
+            col++;
+        }
+        addOptionText((text == null) ? "" : text);
+        
+        return addSliderButtonedWithVal(sliderMax, stepSize, inputAction);
+    }
+    
+    /**
+     * Adds a line with a checkbox option.
+     * 
+     * @param helpAction Action listener invoked when the help icon is clicked.
+     *                   If {@code null}, then no help is shown.
+     * @param text Option text.
+     * @param selected Initial state of the checkbox.
+     * @param checkBoxAction Action listener invoked when the check box is clicked.
+     * @return Created checkbox
+     */
+    public JCheckBox addCheckBoxOptionLine(ActionListener helpAction, String text, boolean selected, ActionListener checkBoxAction) {
+        if (helpAction != null) {
+            addOptionHelpIcon(helpAction);
+        } else {
+            col++;
+        }
+        addOptionText((text == null) ? "" : text);
+        JCheckBox cb = addCheckBox(selected, checkBoxAction);
+        //addLine();
+        return cb;
+    }
+
+    /**
+     * Moves the builder to the new line. Methods with "Line" suffix add new line automatically.
+     * 
+     * @return This builder
+     */
+    public ControlPanelBuilder addLine() {
+        row++;
+        col = 0; 
+        return this;
+    }
+    
+    /**
+     * Adds a button section at the bottom of the control panel.
+     * 
+     * @param buttons Labels.
+     * @param actions Action listener invoked when the corresponding button is clicked.
+     * @return List of new buttons
+     * @throws IllegalArgumentException if the size of the two lists is different
+     */
+    public List<JButton> addButtons(List<String> buttons, List<ActionListener> actions) {
+        if (buttons.size() != actions.size()) {
+            throw new IllegalArgumentException();
+        }
+        
+        GridBagConstraints c = new GridBagConstraints();
+        c.insets = new Insets(2, 0, 40, 0); // small external space on top and bottom
+        c.weighty = 1.0;   //request any extra vertical space
+        c.anchor = GridBagConstraints.PAGE_END;
+        c.gridwidth = BUTTON_WIDTH;
+        
+        List<JButton> retButtons = new ArrayList<>();
+        for (int i = 0; i < buttons.size(); i++) {
+            JButton button = addButtonCustom(buttons.get(i), actions.get(i), c);
+            retButtons.add(button);
+        }
+
+        return retButtons;
+    }
+    
+    /**
+     * Adds a simple button.
+     * 
+     * @param caption Label
+     * @param action Action listener invoked when the corresponding button is clicked
+     * @return This new GUI object
+     */
+    public JButton addButton(String caption, ActionListener action) {
+        final GridBagConstraints c = new GridBagConstraints();
+        c.anchor = GridBagConstraints.LINE_START;
+        c.gridwidth = BUTTON_WIDTH;
+        
+        return addButtonCustom(caption, action, c);
+    }
+
+    /**
+     * Adds a simple button whose appearance can be further customized by {@code constraints}.
+     * 
+     * @param caption Label
+     * @param action Action listener invoked when the corresponding button is clicked
+     * @param constraints {@code GridBagConstraints} to customize the button
+     * @return This new GUI object
+     */
+    private JButton addButtonCustom(String caption, ActionListener action, GridBagConstraints constraints) {
+        JButton button = new JButton();
+        button.setText(caption);
+        button.addActionListener(action);
+        
+        constraints.gridy = row;
+        constraints.gridx = col;
+        col += constraints.gridwidth;
+        constraints.fill = GridBagConstraints.NONE;
+        controlPanel.add(button, constraints);
+        
+        return button;
+    }
+    
+    /**
+     * Adds a combo box.
+     * 
+     * @param items Items
+     * @param action Action listener invoked when some item is selected
+     * @return This new GUI object
+     */
+    public JComboBox addComboBox(List<String> items, ActionListener action) {
+        GridBagConstraints c = new GridBagConstraints();
+        c.insets = new Insets(0, 25, 0, 0);
+        c.gridwidth = OPTION_TEXT_WIDTH;
+        c.gridy = row;
+        c.gridx = col;
+        col += OPTION_TEXT_WIDTH;
+        c.anchor = GridBagConstraints.CENTER;
+        c.fill = GridBagConstraints.NONE;
+        
+        JComboBox cbox = new JComboBox(items.toArray(String[]::new));
+        cbox.addActionListener(action);
+        controlPanel.add(cbox, c);
+        
+        return cbox;
+    }
+    
+    /**
+     * Adds a horizontal strut that moves upper lines to the top of the panel.
+     */
+    public void addVerticalStrut() {
+        GridBagConstraints c = new GridBagConstraints();
+        c.weighty = 1.0;
+        c.gridwidth = 1;
+        c.gridy = row;
+        c.gridx = col++;
+        c.anchor = GridBagConstraints.CENTER;
+        c.fill = GridBagConstraints.BOTH;
+        controlPanel.add(Box.createHorizontalStrut(5), c);
+    }
+    
+    /**
+     * Adds a gap occupying given number of grid cells.
+     */
+    public void addGap() {
+        GridBagConstraints c = new GridBagConstraints();
+        c.weightx = 0.4;
+        c.gridwidth = 1;
+        c.gridy = row;
+        c.gridx = col++;
+        c.anchor = GridBagConstraints.CENTER;
+        c.fill = GridBagConstraints.HORIZONTAL;
+        controlPanel.add(Box.createVerticalStrut(5), c);
+    }
+    
+    /**
+     * Adds a check box.
+     * 
+     * @param selected Initial state
+     * @param action Action listener invoked when the checkbox is clicked.
+     * @return This new GUI object
+     */
+    public JCheckBox addCheckBox(boolean selected, ActionListener action) {
+        GridBagConstraints c = new GridBagConstraints();
+        c.insets = new Insets(0, 25, 0, 0);
+        c.gridwidth = 1;
+        c.gridx = col++;
+        c.gridy = row;
+        c.anchor = GridBagConstraints.CENTER;
+        c.fill = GridBagConstraints.NONE;
+
+        JCheckBox checkBox = new JCheckBox();
+        checkBox.setSelected(selected);
+        checkBox.addActionListener(action);
+        controlPanel.add(checkBox, c);
+
+        return checkBox;
+    }
+    
+    /**
+     * Adds a help icon.
+     * 
+     * @param action Action listener invoked when the icon is clicked.
+     * @return This new GUI object
+     */
+    public JButton addOptionHelpIcon(ActionListener action) {
+        GridBagConstraints c = new GridBagConstraints();
+        c.gridwidth = 1;
+        c.gridx = col++;
+        c.gridy = row;
+        c.anchor = GridBagConstraints.CENTER;
+        c.fill = GridBagConstraints.NONE;
+        
+        JButton button = new JButton();
+        button.setBorderPainted(false);
+        button.setFocusPainted(false);
+        button.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
+        button.addActionListener(action);
+        button.setIcon(HELP_ICON);
+        
+        controlPanel.add(button, c);
+        return button;
+    }
+    
+    /**
+     * Adds a text of the option.
+     * 
+     * @param text Text.
+     * @return This new GUI object
+     */
+    public JLabel addOptionText(String text) {
+        GridBagConstraints c = new GridBagConstraints();
+        c.gridwidth = OPTION_TEXT_WIDTH;
+        c.gridx = col;
+        col += OPTION_TEXT_WIDTH;
+        c.gridy = row;
+        c.anchor = GridBagConstraints.LINE_START;
+        c.fill = GridBagConstraints.HORIZONTAL;
+        
+        JLabel label = new JLabel();
+        label.setFont(OPTION_TEXT_FONT);
+        label.setForeground(OPTION_TEXT_COLOR);
+        label.setText(text);
+        
+        controlPanel.add(label, c);
+        return label;
+    }
+    
+    /**
+     * Adds a slider associated with a text field.
+     * 
+     * @param max Max value of the slider (and the value field).
+     *            If {@code -1}, then percentage slider is shown with 100 as the max. value.
+     * @param inputAction Action listener invoked when the value is changed.
+     * @return Text field associated with the slider
+     */
+    public JTextField addSliderWithVal(int max, ActionListener inputAction) {
+        JSlider slider = addSlider(max);
+        
+        boolean percentageSlider = max == -1;
+        IntValueRange range = percentageSlider ? null : new IntValueRange(0, max);
+        JTextField inputField = addFormattedInputField(range, inputAction);
+        
+        connectSliderWithTextField(slider, inputField, percentageSlider);
+        
+        return inputField;
+    }
+    
+    /**
+     * Adds a slider associated with a text field with buttons.
+     * 
+     * @param max Max value of the slider (and the value field).
+     *            If {@code -1}, then percentage slider is shown with 100 as the max. value.
+     * @param stepSize Size of an increment/decrement of the slider value on a plus/minus button click.
+     *                 If the {@code stepSize} is negative, the step size will be set to 1
+     *                 (or 1 % in case of a percentage slider).
+     * @param inputAction Action listener invoked when the value is changed.
+     * @return Text field associated with the slider
+     */
+    public JTextField addSliderButtonedWithVal(int max, double stepSize, ActionListener inputAction) {
+        JSlider slider = addSlider(max);
+        
+        boolean percentageSlider = max == -1;
+        IntValueRange range = percentageSlider ? null : new IntValueRange(0, max);
+        JTextField inputField = addFormattedInputFieldButtoned(range, stepSize, inputAction);
+        
+        connectSliderWithTextField(slider, inputField, percentageSlider);
+        
+        return inputField;
+    }
+    
+    /**
+     * Associates slider with the given text field and links the slider's listeners
+     * to the listeners of the text field and vice versa.
+     * 
+     * @param slider Slider to be associated with the given text field.
+     * @param inputField Text field to be associated with the given slider.
+     * @param percentage If {@code true}, the slider is treated as a percentage slider
+     *                   with 100 as the maximum value. The text field then treats
+     *                   the percentual values as <b>decimal</b> numbers from the interval [0,1].<br>
+     *                   If {@code false}, the slider works with <b>integer</b> values
+     *                   from the interval [0,{@code max}] and so does the text field.
+     */
+    private void connectSliderWithTextField(JSlider slider, JTextField inputField, boolean percentage) {
+        slider.addChangeListener((ChangeEvent ce) -> {
+            if (percentage) {
+                inputField.setText(doubleToStringLocale(slider.getValue() / 100.0));
+            } else {
+                inputField.setText(intToStringLocale(slider.getValue()));
+            }
+            inputField.postActionEvent(); // invoke textField action listener
+        });
+        slider.addMouseListener(
+                new MouseAdapter() {
+                    @Override
+                    public void mouseExited(MouseEvent e) {
+                        e.setSource(inputField);
+                        inputField.dispatchEvent(e);
+                    }
+
+                    @Override
+                    public void mouseEntered(MouseEvent e) {
+                        e.setSource(inputField);
+                        inputField.dispatchEvent(e);
+                    }
+
+                    @Override
+                    public void mouseReleased(MouseEvent e) {
+                        e.setSource(inputField);
+                        inputField.dispatchEvent(e);
+                    }
+
+                    @Override
+                    public void mousePressed(MouseEvent e) {
+                        e.setSource(inputField);
+                        inputField.dispatchEvent(e);
+                    }
+
+                    @Override
+                    public void mouseClicked(MouseEvent e) {
+                        e.setSource(inputField);
+                        inputField.dispatchEvent(e);
+                    }
+                }
+        );
+        
+        inputField.addActionListener((ActionEvent ae) -> {
+            if (percentage) { // percents in [0,1]
+                slider.setValue((int) (parseLocaleDouble(inputField) * 100));
+            } else { // integers
+                slider.setValue(parseLocaleInt(inputField));
+            }
+        });
+    }
+    
+    /**
+     * Adds a slider.
+     * 
+     * @param max Max value of the slider.
+     *            If {@code -1}, then percentage slider is shown with 100 as the max. value.
+     * @return This new GUI object
+     */
+    public JSlider addSlider(int max) {
+        GridBagConstraints c = new GridBagConstraints();
+        c.gridwidth = SLIDER_WIDTH;
+        c.gridx = col;
+        col += SLIDER_WIDTH;
+        c.gridy = row;
+        c.anchor = GridBagConstraints.CENTER;
+        c.fill = GridBagConstraints.HORIZONTAL;
+
+        JSlider slider = new JSlider();
+        
+        if (max == -1) { // percents
+            slider.setMaximum(100);
+        } else { // absolute values
+            slider.setMaximum(max);
+        }
+        
+        controlPanel.add(slider, c);
+        
+        return slider;
+    }
+    
+    /**
+     * Adds a formatted text field with buttons that accepts either integer
+     * or percentage (decimal) input values.
+     * 
+     * @param range Interval defining the range of integers that are accepted as an input value.
+     *              If {@code null}, then decimal percentage values between 0.0 and 1.0 are accepted.
+     * @param stepSize Size of an increment/decrement of the text field value on a plus/minus button click.
+     *                 If the {@code stepSize} is negative, the step size will be set to 1
+     *                 (or 1 % in case of a percentage text field).
+     * @param inputAction Action listener invoked when the value is changed.
+     * @return This new GUI object
+     */
+    public JFormattedTextField addFormattedInputFieldButtoned(IntValueRange range, double stepSize, ActionListener inputAction) {
+        GridBagConstraints c = new GridBagConstraints();
+        c.gridwidth = 1;
+        
+        c.anchor = GridBagConstraints.LINE_END;
+        JButton minusButton = addButtonCustom("-", null, c);
+        JFormattedTextField inputField = addFormattedInputField(range, inputAction);
+        c.anchor = GridBagConstraints.LINE_START;
+        JButton plusButton = addButtonCustom("+", null, c);
+        
+        double step;
+        if (range == null) { // Percents in [0, 1]
+            if (stepSize < 0.0) {
+                step = 0.01;
+            } else {
+                step = stepSize;
+            }
+        } else { // Range of integers between two given integers
+            if (stepSize < 0.0) {
+                step = 1.0;
+            } else {
+                step = Math.round(stepSize);
+            }
+        }
+
+        minusButton.addActionListener(new AbstractAction() {
+            private final double minimum = range == null ? PERCENTAGE_VALUE_MINIMUM : range.getMinimum();
+            
+            @Override
+            public void actionPerformed(ActionEvent ae) {
+                double newValue = parseLocaleDouble(inputField) - step;
+                if (newValue < minimum) {
+                    return;
+                }
+                
+                inputField.setValue(newValue);
+                for (ActionListener listener: inputField.getActionListeners()) {
+                    listener.actionPerformed(new ActionEvent(
+                            inputField,
+                            ActionEvent.ACTION_PERFORMED,
+                            TEXT_FIELD_BUTTON_PRESSED_MINUS));
+                }
+            }
+        });
+        plusButton.addActionListener(new AbstractAction() {
+            private final double maximum = range == null ? PERCENTAGE_VALUE_MAXIMUM : range.getMaximum();
+            
+            @Override
+            public void actionPerformed(ActionEvent ae) {
+                double newValue = parseLocaleDouble(inputField) + step;
+                if (newValue > maximum) {
+                    return;
+                }
+                
+                inputField.setValue(newValue);
+                for (ActionListener listener: inputField.getActionListeners()) {
+                    listener.actionPerformed(new ActionEvent(
+                            inputField,
+                            ActionEvent.ACTION_PERFORMED,
+                            TEXT_FIELD_BUTTON_PRESSED_PLUS));
+                }
+            }
+        });
+        
+        return inputField;
+    }
+    
+    /**
+     * Adds a formatted text field that accepts either integer or percentage (decimal) input values.
+     * 
+     * @param range Interval defining the range of integers that are accepted as an input value.
+     *              If {@code null}, then decimal percentage values between 0.0 and 1.0 are accepted.
+     * @param inputAction Action listener invoked when the value is changed.
+     * @return This new GUI object
+     */
+    public JFormattedTextField addFormattedInputField(IntValueRange range, ActionListener inputAction) {
+        GridBagConstraints c = new GridBagConstraints();
+        c.gridwidth = 2;
+        c.gridx = col;
+        col += 2;
+        c.gridy = row;
+        c.anchor = GridBagConstraints.CENTER;
+        c.fill = GridBagConstraints.BOTH;
+        
+        NumberFormatter formatter;
+        if (range == null) { // percents in [0,1] => use two digit double
+            NumberFormat format = DecimalFormat.getInstance(Locale.getDefault());
+            format.setMinimumFractionDigits(1);
+            format.setMaximumFractionDigits(NUMBER_OF_FRACTION_DIGITS);
+            format.setRoundingMode(RoundingMode.HALF_UP);
+            formatter = new NumberFormatter(format);
+            formatter.setValueClass(Double.class);
+            formatter.setMinimum(PERCENTAGE_VALUE_MINIMUM);
+            formatter.setMaximum(PERCENTAGE_VALUE_MAXIMUM);
+        } else {
+            NumberFormat format = NumberFormat.getInstance();
+            formatter = new NumberFormatter(format);
+            formatter.setValueClass(Integer.class);
+            formatter.setMinimum(range.getMinimum());
+            formatter.setMaximum(range.getMaximum());
+        }
+        formatter.setAllowsInvalid(false);
+        
+        JFormattedTextField input = new JFormattedTextField(formatter);
+        input.setText("0");
+        input.addActionListener(inputAction);
+        controlPanel.add(input, c);
+        
+        return input;
+    }
+    
+    /**
+     * Adds a scrollable pane that carries the given panel as its content.
+     * 
+     * @param content Panel to be made scrollable
+     * @return This new GUI object
+     */
+    public JScrollPane addScrollPane(JPanel content) {
+        JScrollPane scrollPane = new JScrollPane(content);
+        
+        GridBagConstraints c = new GridBagConstraints();
+        c.weighty = 1.0;
+        c.gridwidth = GridBagConstraints.REMAINDER;
+        c.gridy = row;
+        c.gridx = col;
+        c.anchor = GridBagConstraints.CENTER;
+        c.fill = GridBagConstraints.BOTH;
+        controlPanel.add(scrollPane, c);
+        
+        return scrollPane;
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/FaceToFaceTab.java b/GUI/src/main/java/cz/fidentis/analyst/core/FaceToFaceTab.java
new file mode 100644
index 0000000000000000000000000000000000000000..68f23c23acc5e58515f25d89171e7fb664ebc8aa
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/core/FaceToFaceTab.java
@@ -0,0 +1,90 @@
+package cz.fidentis.analyst.core;
+
+import cz.fidentis.analyst.canvas.Canvas;
+import cz.fidentis.analyst.face.HumanFace;
+import cz.fidentis.analyst.toolbar.FaceToFaceToolBar;
+import cz.fidentis.analyst.toolbar.RenderingToolBar;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import javax.swing.GroupLayout;
+import javax.swing.JScrollPane;
+import javax.swing.LayoutStyle;
+import org.openide.windows.TopComponent;
+
+/**
+ * The non-singleton window/tab for the analysis of two faces.
+ *
+ * @author Radek Oslejsek
+ */
+public class FaceToFaceTab extends TopComponent {
+    
+    private final Canvas canvas ;
+    private final FaceToFaceToolBar renderingToolBar;
+    private final TopControlPanel controlPanel;
+    private final JScrollPane scrollPane;
+
+    /**
+     * Constructor.
+     * @param primary Primary face
+     * @param secondary Secondary face
+     * @param name Tab name
+     */
+    public FaceToFaceTab(HumanFace primary, HumanFace secondary, String name) {
+        canvas = new Canvas();
+        canvas.initScene(primary, secondary);
+        controlPanel = new TopControlPanel();
+        renderingToolBar = new FaceToFaceToolBar(canvas, controlPanel);
+        
+        scrollPane = new JScrollPane(controlPanel);
+        
+        setName(name);
+        initComponents();
+        
+        // change the height so that it corresponds to the height of the OpenGL window
+        canvas.addComponentListener(new ComponentAdapter() {
+            @Override
+            public void componentResized(ComponentEvent e) {
+                scrollPane.setSize(ControlPanel.CONTROL_PANEL_WIDTH, canvas.getHeight());
+            }
+        });
+    }
+    
+    @Override
+    public int getPersistenceType() {
+        return TopComponent.PERSISTENCE_NEVER; // TO DO: change to .PERSISTENCE_ONLY_OPENED when we can re-create the ProjectTC
+    }
+    
+    private void initComponents() {
+        GroupLayout layout = new GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+                layout.createParallelGroup(GroupLayout.Alignment.LEADING)
+                        .addGroup(layout.createSequentialGroup()
+                                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+                                .addComponent(canvas, GroupLayout.DEFAULT_SIZE, 651, Short.MAX_VALUE)
+                                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+                                .addComponent(renderingToolBar, GroupLayout.PREFERRED_SIZE, RenderingToolBar.WIDTH, GroupLayout.PREFERRED_SIZE)
+                                .addComponent(
+                                        scrollPane,
+                                        ControlPanel.CONTROL_PANEL_WIDTH, 
+                                        ControlPanel.CONTROL_PANEL_WIDTH, 
+                                        ControlPanel.CONTROL_PANEL_WIDTH
+                                )
+                        )
+        );
+        layout.setVerticalGroup(
+                layout.createParallelGroup(GroupLayout.Alignment.LEADING)
+                        .addGroup(layout.createSequentialGroup()
+                                .addGroup(layout.createBaselineGroup(true, true)
+                                        .addComponent(canvas)
+                                        .addComponent(renderingToolBar)
+                                        .addComponent(scrollPane)
+                                ))
+        );
+    }
+
+    public Canvas getCanvas() {
+        return canvas;
+    }
+    
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/IntValueRange.java b/GUI/src/main/java/cz/fidentis/analyst/core/IntValueRange.java
new file mode 100644
index 0000000000000000000000000000000000000000..fa2b52b903d45d84a3340febfeea29e8da6ec1ed
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/core/IntValueRange.java
@@ -0,0 +1,45 @@
+package cz.fidentis.analyst.core;
+
+/**
+ * Class holding the upper and lower bounds of an interval.
+ * 
+ * @author Daniel Schramm
+ */
+public class IntValueRange {
+    
+    private final int minimum, maximum;
+
+    /**
+     * Constructor.
+     * 
+     * @param minimum The lower bound of the interval
+     * @param maximum The upper bound of the interval
+     * @throws IllegalArgumentException if the {@code minimum} is greater than the {@code maximum}
+     */
+    public IntValueRange(int minimum, int maximum) {
+        if (minimum > maximum) {
+            throw new IllegalArgumentException("Minimum value must be less or equal to maximum value");
+        }
+        
+        this.minimum = minimum;
+        this.maximum = maximum;
+    }
+
+    /**
+     * Returns the lower bound of the interval.
+     * 
+     * @return Lower bound of the interval
+     */
+    public int getMinimum() {
+        return minimum;
+    }
+
+    /**
+     * Returns the upper bound of the interval.
+     * 
+     * @return Upper bound of the interval
+     */
+    public int getMaximum() {
+        return maximum;
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/LoadedActionEvent.java b/GUI/src/main/java/cz/fidentis/analyst/core/LoadedActionEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..05b7c390a07fec6f137cc08b81beb01296b9dea8
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/core/LoadedActionEvent.java
@@ -0,0 +1,81 @@
+package cz.fidentis.analyst.core;
+
+import java.awt.event.ActionEvent;
+
+/**
+ * A subclass of {@link ActionEvent} extended to carry additional data as a payload.
+ * 
+ * @author Daniel Schramm
+ */
+public class LoadedActionEvent extends ActionEvent {
+    
+    private final Object data;
+
+    /**
+     * Constructor.
+     *
+     * @param source The object that originated the event
+     * @param id An integer that identifies the event.
+     *           For information on allowable values, see the class description
+     *           for {@link ActionEvent}
+     * @param command A string that may specify a command (possibly one
+     *                of several) associated with the event
+     * @param data Payload data of the event
+     * @throws IllegalArgumentException if {@code source} is null
+     */
+    public LoadedActionEvent(Object source, int id, String command, Object data) {
+        super(source, id, command);
+        this.data = data;
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param source The object that originated the event
+     * @param id An integer that identifies the event.
+     *           For information on allowable values, see the class description
+     *           for {@link ActionEvent}
+     * @param command A string that may specify a command (possibly one
+     *                of several) associated with the event
+     * @param modifiers The modifier keys down during event (shift, ctrl, alt, meta).
+     *                  Passing negative parameter is not recommended.
+     *                  Zero value means that no modifiers were passed
+     * @param data Payload data of the event
+     * @throws IllegalArgumentException if {@code source} is null
+     */
+    public LoadedActionEvent(Object source, int id, String command, int modifiers, Object data) {
+        super(source, id, command, modifiers);
+        this.data = data;
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param source The object that originated the event
+     * @param id An integer that identifies the event.
+     *           For information on allowable values, see the class description
+     *           for {@link ActionEvent}
+     * @param command A string that may specify a command (possibly one
+     *                of several) associated with the event
+     * @param modifiers The modifier keys down during event (shift, ctrl, alt, meta).
+     *                  Passing negative parameter is not recommended.
+     *                  Zero value means that no modifiers were passed
+     * @param when A long that gives the time the event occurred.
+     *             Passing negative or zero value is not recommended
+     * @param data Payload data of the event
+     * @throws IllegalArgumentException if {@code source} is null
+     */
+    public LoadedActionEvent(Object source, int id, String command, long when, int modifiers, Object data) {
+        super(source, id, command, when, modifiers);
+        this.data = data;
+    }
+
+    /**
+     * Returns payload data of the action event.
+     * 
+     * @return Payload data of the action event
+     */
+    public Object getData() {
+        return data;
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/OutputWindow.java b/GUI/src/main/java/cz/fidentis/analyst/core/OutputWindow.java
new file mode 100644
index 0000000000000000000000000000000000000000..97821f99a03040957817f8c841b18ba6cb74a244
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/core/OutputWindow.java
@@ -0,0 +1,89 @@
+package cz.fidentis.analyst.core;
+
+import java.awt.BorderLayout;
+import java.text.SimpleDateFormat;
+import java.time.Duration;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import org.openide.windows.TopComponent;
+import org.openide.windows.WindowManager;
+
+/**
+ * Wrapper for default output window of the Java Netbeans Platform application.
+ * It enables to write debug messages into the window.
+ * 
+ * @author Radek Oslejsek
+ */
+public class OutputWindow {
+
+    private static JTextArea textArea; 
+    
+    private long lastTime = System.currentTimeMillis();
+    
+    protected OutputWindow() {
+        initTextArea();
+    }
+    
+    /**
+     * Prints the message.
+     * 
+     * @param msg Message to be printed
+     */
+    public static void print(String msg) {
+        JTextArea ta = initTextArea();
+        ta.setText(ta.getText() 
+                + new SimpleDateFormat("HH:mm:ss").format(System.currentTimeMillis())
+                + " [duration unknown]: "
+                + msg.trim() 
+                + System.lineSeparator()
+        );
+    }
+
+    /**
+     * Starts measuring of some operation. 
+     * Call {@link #printDuration(java.lang.String)} on returned OutputWindow
+     * to print the measured duration.
+     * 
+     * @return An object used to print measured duration and message
+     */
+    public static OutputWindow measureTime() {
+        OutputWindow ret = new OutputWindow();
+        ret.lastTime = System.currentTimeMillis();
+        return ret;
+    }
+    
+    /**
+     * Prints the message about an operation and the duration of the operation. 
+     * The duration is computed as the difference between current system time and 
+     * the time of calling {@link #measureTime()}. The time difference is measured in 
+     * milliseconds and printed as [+mm:ss.SSS] where mm=minutes, ss=seconds, 
+     * and SSS=milliseconds.
+     * 
+     * @param msg Message to be printed
+     */
+    public void printDuration(String msg) {
+        Duration duration = Duration.ofMillis(System.currentTimeMillis() - lastTime);
+        textArea.setText(textArea.getText() 
+                + new SimpleDateFormat("HH:mm:ss").format(System.currentTimeMillis())
+                + " [duration "
+                + String.format(
+                        "%02d:%02d.%03d", 
+                        duration.toMinutes(), 
+                        duration.toSecondsPart(),
+                        duration.toMillisPart())
+                + "]: "
+                + msg.trim() 
+                + System.lineSeparator()
+        );
+    }
+    
+    protected static JTextArea initTextArea() {
+        if (textArea == null) {
+            TopComponent outputWin = WindowManager.getDefault().findTopComponent("output");
+            textArea = new JTextArea();
+            JScrollPane sp = new JScrollPane(textArea);
+            outputWin.add(sp, BorderLayout.CENTER);
+        }
+        return textArea;
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/ProjectTopComp.form b/GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.form
similarity index 58%
rename from GUI/src/main/java/cz/fidentis/analyst/gui/ProjectTopComp.form
rename to GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.form
index 4f1add03f53bc8b2f78668a5d393fbd63d52ca33..6c7391939d67d02f634c69e19cd4cf724aad40b1 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/ProjectTopComp.form
+++ b/GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.form
@@ -21,7 +21,7 @@
 
 -->
 
-<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+<Form version="1.8" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   <AuxValues>
     <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
     <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
@@ -39,9 +39,6 @@
   <SubComponents>
     <Container class="javax.swing.JPanel" name="jPanel1">
       <Properties>
-        <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-          <Color blue="a3" green="ae" red="0" type="rgb"/>
-        </Property>
         <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
           <Dimension value="[0, 0]"/>
         </Property>
@@ -55,96 +52,28 @@
       <Layout>
         <DimensionLayout dim="0">
           <Group type="103" groupAlignment="0" attributes="0">
-              <Group type="102" alignment="0" attributes="0">
-                  <Group type="103" groupAlignment="1" max="-2" attributes="0">
-                      <Component id="jPanel4" alignment="0" max="32767" attributes="0"/>
-                      <Component id="jPanel5" alignment="0" max="32767" attributes="0"/>
+              <Group type="102" attributes="0">
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Component id="jPanel2" min="-2" max="-2" attributes="0"/>
+                      <Component id="jPanel5" min="-2" pref="783" max="-2" attributes="0"/>
                   </Group>
-                  <EmptySpace min="0" pref="450" max="32767" attributes="0"/>
+                  <EmptySpace min="0" pref="442" max="32767" attributes="0"/>
               </Group>
           </Group>
         </DimensionLayout>
         <DimensionLayout dim="1">
           <Group type="103" groupAlignment="0" attributes="0">
               <Group type="102" alignment="0" attributes="0">
-                  <Component id="jPanel4" min="-2" pref="180" max="-2" attributes="0"/>
+                  <Component id="jPanel5" min="-2" pref="56" max="-2" attributes="0"/>
                   <EmptySpace max="-2" attributes="0"/>
-                  <Component id="jPanel5" min="-2" max="-2" attributes="0"/>
-                  <EmptySpace pref="580" max="32767" attributes="0"/>
+                  <Component id="jPanel2" max="32767" attributes="0"/>
               </Group>
           </Group>
         </DimensionLayout>
       </Layout>
       <SubComponents>
-        <Container class="javax.swing.JPanel" name="jPanel4">
-          <Properties>
-            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="81" green="8a" red="2" type="rgb"/>
-            </Property>
-            <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
-              <Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
-                <EtchetBorder/>
-              </Border>
-            </Property>
-          </Properties>
-
-          <Layout class="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout">
-            <Property name="useNullLayout" type="boolean" value="false"/>
-          </Layout>
-          <SubComponents>
-            <Container class="javax.swing.JPanel" name="jPanel2">
-              <Properties>
-                <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-                  <Color blue="57" green="57" red="0" type="rgb"/>
-                </Property>
-              </Properties>
-              <Constraints>
-                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-                  <AbsoluteConstraints x="30" y="30" width="120" height="120"/>
-                </Constraint>
-              </Constraints>
-
-              <Layout>
-                <DimensionLayout dim="0">
-                  <Group type="103" groupAlignment="0" attributes="0">
-                      <Group type="102" alignment="1" attributes="0">
-                          <EmptySpace max="-2" attributes="0"/>
-                          <Component id="jLabel1" pref="100" max="32767" attributes="0"/>
-                          <EmptySpace max="-2" attributes="0"/>
-                      </Group>
-                  </Group>
-                </DimensionLayout>
-                <DimensionLayout dim="1">
-                  <Group type="103" groupAlignment="0" attributes="0">
-                      <Group type="102" alignment="1" attributes="0">
-                          <EmptySpace max="-2" attributes="0"/>
-                          <Component id="jLabel1" pref="98" max="32767" attributes="0"/>
-                          <EmptySpace max="-2" attributes="0"/>
-                      </Group>
-                  </Group>
-                </DimensionLayout>
-              </Layout>
-              <SubComponents>
-                <Component class="javax.swing.JLabel" name="jLabel1">
-                  <Properties>
-                    <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
-                      <Font name="Tahoma" size="18" style="0"/>
-                    </Property>
-                    <Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-                      <Color blue="cc" green="cc" red="cc" type="rgb"/>
-                    </Property>
-                    <Property name="horizontalAlignment" type="int" value="0"/>
-                  </Properties>
-                </Component>
-              </SubComponents>
-            </Container>
-          </SubComponents>
-        </Container>
         <Container class="javax.swing.JPanel" name="jPanel5">
           <Properties>
-            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="81" green="8a" red="2" type="rgb"/>
-            </Property>
             <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
               <Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
                 <EtchetBorder/>
@@ -160,7 +89,7 @@
                   <Font name="Tahoma" size="12" style="0"/>
                 </Property>
                 <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-                  <ResourceString bundle="cz/fidentis/analyst/gui/Bundle.properties" key="ProjectTopComp.addButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                  <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.addButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
                 </Property>
               </Properties>
               <Events>
@@ -178,7 +107,7 @@
                   <Font name="Tahoma" size="12" style="0"/>
                 </Property>
                 <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-                  <ResourceString bundle="cz/fidentis/analyst/gui/Bundle.properties" key="ProjectTopComp.removeButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                  <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.removeButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
                 </Property>
               </Properties>
               <Events>
@@ -196,9 +125,12 @@
                   <Font name="Tahoma" size="12" style="0"/>
                 </Property>
                 <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-                  <ResourceString bundle="cz/fidentis/analyst/gui/Bundle.properties" key="ProjectTopComp.selectAllButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                  <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.selectAllButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
                 </Property>
               </Properties>
+              <Events>
+                <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="selectAllButton1MouseClicked"/>
+              </Events>
               <Constraints>
                 <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
                   <GridBagConstraints gridX="2" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="22" insetsBottom="13" insetsRight="4" anchor="18" weightX="0.0" weightY="0.0"/>
@@ -211,67 +143,139 @@
                   <Font name="Tahoma" size="12" style="0"/>
                 </Property>
                 <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-                  <ResourceString bundle="cz/fidentis/analyst/gui/Bundle.properties" key="ProjectTopComp.deselectAllButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                  <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.deselectAllButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
                 </Property>
               </Properties>
+              <Events>
+                <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="deselectAllButton1MouseClicked"/>
+              </Events>
               <Constraints>
                 <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
                   <GridBagConstraints gridX="3" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="22" insetsBottom="13" insetsRight="4" anchor="18" weightX="0.0" weightY="0.0"/>
                 </Constraint>
               </Constraints>
             </Component>
-            <Component class="javax.swing.JButton" name="collapseButton1">
+            <Component class="javax.swing.JButton" name="inflateButton1">
               <Properties>
                 <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
                   <Font name="Tahoma" size="12" style="0"/>
                 </Property>
                 <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-                  <ResourceString bundle="cz/fidentis/analyst/gui/Bundle.properties" key="ProjectTopComp.collapseButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                  <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.inflateButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
                 </Property>
+                <Property name="alignmentX" type="float" value="0.5"/>
               </Properties>
+              <Events>
+                <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="inflateButton1MouseClicked"/>
+              </Events>
               <Constraints>
                 <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
                   <GridBagConstraints gridX="4" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="22" insetsBottom="13" insetsRight="4" anchor="18" weightX="0.0" weightY="0.0"/>
                 </Constraint>
               </Constraints>
             </Component>
-            <Component class="javax.swing.JButton" name="inflateButton1">
+            <Component class="javax.swing.JButton" name="oneOnOneButton1">
               <Properties>
                 <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
-                  <Font name="Tahoma" size="12" style="0"/>
+                  <Font name="Tahoma" size="12" style="1"/>
                 </Property>
                 <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-                  <ResourceString bundle="cz/fidentis/analyst/gui/Bundle.properties" key="ProjectTopComp.inflateButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                  <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.oneOnOneButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
                 </Property>
                 <Property name="alignmentX" type="float" value="0.5"/>
               </Properties>
+              <Events>
+                <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="oneOnOneButton1MouseClicked"/>
+              </Events>
               <Constraints>
                 <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
-                  <GridBagConstraints gridX="5" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="22" insetsBottom="13" insetsRight="4" anchor="18" weightX="0.0" weightY="0.0"/>
+                  <GridBagConstraints gridX="5" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="55" insetsBottom="13" insetsRight="4" anchor="18" weightX="0.0" weightY="0.0"/>
                 </Constraint>
               </Constraints>
             </Component>
-            <Component class="javax.swing.JButton" name="analyzeButton1">
+            <Component class="javax.swing.JButton" name="analyseButton1">
               <Properties>
-                <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-                  <Color blue="f0" green="f0" red="b7" type="rgb"/>
-                </Property>
                 <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
-                  <Font name="Tahoma" size="12" style="0"/>
+                  <Font name="Tahoma" size="12" style="1"/>
                 </Property>
                 <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-                  <ResourceString bundle="cz/fidentis/analyst/gui/Bundle.properties" key="ProjectTopComp.analyzeButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                  <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.analyseButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
                 </Property>
-                <Property name="alignmentX" type="float" value="0.5"/>
               </Properties>
+              <Events>
+                <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="analyseButton1MouseClicked"/>
+              </Events>
               <Constraints>
                 <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
-                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="43" insetsBottom="13" insetsRight="25" anchor="10" weightX="0.0" weightY="0.0"/>
+                  <GridBagConstraints gridX="6" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="16" insetsBottom="13" insetsRight="4" anchor="10" weightX="0.0" weightY="0.0"/>
                 </Constraint>
               </Constraints>
             </Component>
           </SubComponents>
         </Container>
+        <Container class="javax.swing.JPanel" name="jPanel2">
+
+          <Layout>
+            <DimensionLayout dim="0">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" alignment="0" attributes="0">
+                      <Component id="jScrollPane1" min="-2" pref="782" max="-2" attributes="0"/>
+                      <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
+                  </Group>
+              </Group>
+            </DimensionLayout>
+            <DimensionLayout dim="1">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Component id="jScrollPane1" alignment="0" pref="760" max="32767" attributes="0"/>
+              </Group>
+            </DimensionLayout>
+          </Layout>
+          <SubComponents>
+            <Container class="javax.swing.JScrollPane" name="jScrollPane1">
+              <AuxValues>
+                <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
+              </AuxValues>
+
+              <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+              <SubComponents>
+                <Component class="javax.swing.JTable" name="jTable1">
+                  <Properties>
+                    <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor" postCode="jTable1.getTableHeader().setOpaque(false);&#xa;jTable1.getTableHeader().setBackground(new java.awt.Color(204,204,204));&#xa;jTable1.getTableHeader().setFont(new java.awt.Font(&quot;Tahoma&quot;, 0, 18));">
+                      <Font name="Tahoma" size="18" style="0"/>
+                    </Property>
+                    <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor" postCode="//javax.swing.table.DefaultTableModel model = (javax.swing.table.DefaultTableModel)jTable1.getModel();&#xa;model = (javax.swing.table.DefaultTableModel) jTable1.getModel();&#xa;model.addTableModelListener(new TableModelListener() {&#xa;&#xa;    public void tableChanged(TableModelEvent e) {&#xa;        &#xa;        if (e.getType() == javax.swing.event.TableModelEvent.UPDATE &amp;&amp; byUser) {&#xa;            int row = e.getFirstRow();&#xa;            int col = e.getColumn();&#xa;&#xa;            if (jTable1.getValueAt(row, col) == (Object)true) {&#xa;                selectedRows.add(row);&#xa;            } else {&#xa;                selectedRows.remove((Object)row);&#xa;            }&#xa;        }&#xa;    }&#xa;});">
+                      <Connection code="new javax.swing.table.DefaultTableModel(&#xa;    new Object [][] {},&#xa;    new String [] {&quot;&quot;, &quot;Models&quot;}) {&#xa;    private Class[] types = new Class [] {&#xa;        java.lang.Boolean.class, java.lang.Object.class&#xa;    };&#xa;    private boolean[] canEdit = new boolean [] {&#xa;        true, false};&#xa;&#xa;    public Class getColumnClass(int columnIndex) {&#xa;        return types [columnIndex];}&#xa;&#xa;    public boolean isCellEditable(int rowIndex, int columnIndex) {&#xa;        return canEdit [columnIndex];&#xa;    }&#xa;    public Class[] getTypes() {&#xa;        return types;}&#xa;&#xa;    public void setTypes(Class[] types) {&#xa;        this.types = types;}&#xa;&#xa;    public boolean[] getCanEdit() {&#xa;        return canEdit;}&#xa;&#xa;    public void setCanEdit(boolean[] canEdit) {&#xa;        this.canEdit = canEdit;&#xa;    }&#xa;}" type="code"/>
+                    </Property>
+                    <Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor">
+                      <TableColumnModel selectionModel="3">
+                        <Column maxWidth="50" minWidth="-1" prefWidth="50" resizable="true">
+                          <Title editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                            <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.jTable1.columnModel.title1_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                          </Title>
+                          <Editor/>
+                          <Renderer/>
+                        </Column>
+                        <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true">
+                          <Title editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                            <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.jTable1.columnModel.title0_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                          </Title>
+                          <Editor/>
+                          <Renderer/>
+                        </Column>
+                      </TableColumnModel>
+                    </Property>
+                    <Property name="dragEnabled" type="boolean" value="true"/>
+                    <Property name="rowHeight" type="int" value="40"/>
+                    <Property name="rowSelectionAllowed" type="boolean" value="false"/>
+                    <Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor">
+                      <TableHeader reorderingAllowed="false" resizingAllowed="true"/>
+                    </Property>
+                  </Properties>
+                </Component>
+              </SubComponents>
+            </Container>
+          </SubComponents>
+        </Container>
       </SubComponents>
     </Container>
   </SubComponents>
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.java b/GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.java
new file mode 100644
index 0000000000000000000000000000000000000000..69a4278f247e92cf6c738f3436ce50f10ebea846
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.java
@@ -0,0 +1,601 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package cz.fidentis.analyst.core;
+
+import org.netbeans.api.settings.ConvertAsProperties;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.windows.TopComponent;
+import org.openide.util.NbBundle.Messages;
+import cz.fidentis.analyst.Project;
+import cz.fidentis.analyst.face.HumanFace;
+import cz.fidentis.analyst.face.HumanFaceFactory;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import javax.swing.JOptionPane;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import org.openide.filesystems.FileChooserBuilder;
+
+/**
+ * The main panel enabling analysts to select the primary and secondary faces,
+ * and to perform basic batch processing. This panel also serves as an entry
+ * point for detailed face analysis and face-to-face comparison.
+ *
+ * @author Matej Kovar
+ */
+@ConvertAsProperties(
+        dtd = "-//cz.fidentis.analyst.gui//Dashboard//EN",
+        autostore = false
+)
+@TopComponent.Description(
+        preferredID = "ProjectTopComp",
+        //iconBase="SET/PATH/TO/ICON/HERE",
+        persistenceType = TopComponent.PERSISTENCE_ALWAYS
+)
+@TopComponent.Registration(mode = "editor", openAtStartup = true)
+@ActionID(category = "Window", id = "cz.fidentis.analyst.gui.ProjectTopComp")
+@ActionReference(path = "Menu/Window" /*, position = 333 */)
+@TopComponent.OpenActionRegistration(
+        displayName = "#CTL_ProjectTopCompAction",
+        preferredID = "ProjectTopComp"
+)
+@Messages({
+    "CTL_ProjectTopCompAction=Project",
+    "CTL_ProjectTopCompTopComponent=Project",
+    "HINT_ProjectTopCompTopComponent=This is a Project window"
+})
+public final class ProjectTopComp extends TopComponent {
+
+    private final Project project;
+    private Map<HumanFace, SingleFaceTab> singleFaceTabs = new HashMap<>();
+    private Map<HumanFace, FaceToFaceTab> faceToFaceTabs = new HashMap<>();
+    private javax.swing.table.DefaultTableModel model;
+    
+    /* List of indexes of selected Rows */
+    private List<Integer> selectedRows = new ArrayList<>();
+    
+    /* Variable which helps to see whether user has clicked to checkbox or
+    clicked on selection buttons */
+    private Boolean byUser = true;
+    
+    /**
+     * Creates new ProjectTopComp, initializes new project
+     */
+    public ProjectTopComp() {
+        project = new Project();
+        initComponents();
+        setName(Bundle.CTL_ProjectTopCompTopComponent());
+        setToolTipText(Bundle.HINT_ProjectTopCompTopComponent());
+        putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
+        putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, Boolean.TRUE);
+        putClientProperty(TopComponent.PROP_UNDOCKING_DISABLED, Boolean.TRUE);
+    }
+
+    /**
+     * This method is called from within the constructor to initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is always
+     * regenerated by the Form Editor.
+     */
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+        java.awt.GridBagConstraints gridBagConstraints;
+
+        jPanel1 = new javax.swing.JPanel();
+        jPanel5 = new javax.swing.JPanel();
+        addButton1 = new javax.swing.JButton();
+        removeButton1 = new javax.swing.JButton();
+        selectAllButton1 = new javax.swing.JButton();
+        deselectAllButton1 = new javax.swing.JButton();
+        inflateButton1 = new javax.swing.JButton();
+        oneOnOneButton1 = new javax.swing.JButton();
+        analyseButton1 = new javax.swing.JButton();
+        jPanel2 = new javax.swing.JPanel();
+        jScrollPane1 = new javax.swing.JScrollPane();
+        jTable1 = new javax.swing.JTable();
+
+        setLayout(new java.awt.BorderLayout());
+
+        jPanel1.setPreferredSize(new java.awt.Dimension(0, 0));
+
+        jPanel5.setBorder(javax.swing.BorderFactory.createEtchedBorder());
+        jPanel5.setLayout(new java.awt.GridBagLayout());
+
+        addButton1.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(addButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.addButton1.text")); // NOI18N
+        addButton1.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mouseClicked(java.awt.event.MouseEvent evt) {
+                addButton1MouseClicked(evt);
+            }
+        });
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 0;
+        gridBagConstraints.gridy = 0;
+        gridBagConstraints.ipadx = 20;
+        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
+        gridBagConstraints.insets = new java.awt.Insets(16, 16, 13, 4);
+        jPanel5.add(addButton1, gridBagConstraints);
+
+        removeButton1.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(removeButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.removeButton1.text")); // NOI18N
+        removeButton1.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mouseClicked(java.awt.event.MouseEvent evt) {
+                removeButton1MouseClicked(evt);
+            }
+        });
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 1;
+        gridBagConstraints.gridy = 0;
+        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+        gridBagConstraints.insets = new java.awt.Insets(16, 22, 13, 4);
+        jPanel5.add(removeButton1, gridBagConstraints);
+
+        selectAllButton1.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(selectAllButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.selectAllButton1.text")); // NOI18N
+        selectAllButton1.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mouseClicked(java.awt.event.MouseEvent evt) {
+                selectAllButton1MouseClicked(evt);
+            }
+        });
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 2;
+        gridBagConstraints.gridy = 0;
+        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+        gridBagConstraints.insets = new java.awt.Insets(16, 22, 13, 4);
+        jPanel5.add(selectAllButton1, gridBagConstraints);
+
+        deselectAllButton1.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(deselectAllButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.deselectAllButton1.text")); // NOI18N
+        deselectAllButton1.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mouseClicked(java.awt.event.MouseEvent evt) {
+                deselectAllButton1MouseClicked(evt);
+            }
+        });
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 3;
+        gridBagConstraints.gridy = 0;
+        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+        gridBagConstraints.insets = new java.awt.Insets(16, 22, 13, 4);
+        jPanel5.add(deselectAllButton1, gridBagConstraints);
+
+        inflateButton1.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(inflateButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.inflateButton1.text")); // NOI18N
+        inflateButton1.setAlignmentX(0.5F);
+        inflateButton1.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mouseClicked(java.awt.event.MouseEvent evt) {
+                inflateButton1MouseClicked(evt);
+            }
+        });
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 4;
+        gridBagConstraints.gridy = 0;
+        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+        gridBagConstraints.insets = new java.awt.Insets(16, 22, 13, 4);
+        jPanel5.add(inflateButton1, gridBagConstraints);
+
+        oneOnOneButton1.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(oneOnOneButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.oneOnOneButton1.text")); // NOI18N
+        oneOnOneButton1.setAlignmentX(0.5F);
+        oneOnOneButton1.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mouseClicked(java.awt.event.MouseEvent evt) {
+                oneOnOneButton1MouseClicked(evt);
+            }
+        });
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 5;
+        gridBagConstraints.gridy = 0;
+        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+        gridBagConstraints.insets = new java.awt.Insets(16, 55, 13, 4);
+        jPanel5.add(oneOnOneButton1, gridBagConstraints);
+
+        analyseButton1.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(analyseButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.analyseButton1.text")); // NOI18N
+        analyseButton1.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mouseClicked(java.awt.event.MouseEvent evt) {
+                analyseButton1MouseClicked(evt);
+            }
+        });
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 6;
+        gridBagConstraints.gridy = 0;
+        gridBagConstraints.insets = new java.awt.Insets(16, 16, 13, 4);
+        jPanel5.add(analyseButton1, gridBagConstraints);
+
+        jTable1.setFont(new java.awt.Font("Tahoma", 0, 18)); // NOI18N
+        jTable1.getTableHeader().setOpaque(false);
+        jTable1.getTableHeader().setBackground(new java.awt.Color(204,204,204));
+        jTable1.getTableHeader().setFont(new java.awt.Font("Tahoma", 0, 18));
+        jTable1.setModel(new javax.swing.table.DefaultTableModel(
+            new Object [][] {},
+            new String [] {"", "Models"}) {
+            private Class[] types = new Class [] {
+                java.lang.Boolean.class, java.lang.Object.class
+            };
+            private boolean[] canEdit = new boolean [] {
+                true, false};
+
+            public Class getColumnClass(int columnIndex) {
+                return types [columnIndex];}
+
+            public boolean isCellEditable(int rowIndex, int columnIndex) {
+                return canEdit [columnIndex];
+            }
+            public Class[] getTypes() {
+                return types;}
+
+            public void setTypes(Class[] types) {
+                this.types = types;}
+
+            public boolean[] getCanEdit() {
+                return canEdit;}
+
+            public void setCanEdit(boolean[] canEdit) {
+                this.canEdit = canEdit;
+            }
+        });
+        //javax.swing.table.DefaultTableModel model = (javax.swing.table.DefaultTableModel)jTable1.getModel();
+        model = (javax.swing.table.DefaultTableModel) jTable1.getModel();
+        model.addTableModelListener(new TableModelListener() {
+
+            public void tableChanged(TableModelEvent e) {
+
+                if (e.getType() == javax.swing.event.TableModelEvent.UPDATE && byUser) {
+                    int row = e.getFirstRow();
+                    int col = e.getColumn();
+
+                    if (jTable1.getValueAt(row, col) == (Object)true) {
+                        selectedRows.add(row);
+                    } else {
+                        selectedRows.remove((Object)row);
+                    }
+                }
+            }
+        });
+        jTable1.setDragEnabled(true);
+        jTable1.setRowHeight(40);
+        jTable1.setRowSelectionAllowed(false);
+        jTable1.getTableHeader().setReorderingAllowed(false);
+        jScrollPane1.setViewportView(jTable1);
+        jTable1.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+        if (jTable1.getColumnModel().getColumnCount() > 0) {
+            jTable1.getColumnModel().getColumn(0).setPreferredWidth(50);
+            jTable1.getColumnModel().getColumn(0).setMaxWidth(50);
+            jTable1.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.jTable1.columnModel.title1_1")); // NOI18N
+            jTable1.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.jTable1.columnModel.title0_1")); // NOI18N
+        }
+
+        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
+        jPanel2.setLayout(jPanel2Layout);
+        jPanel2Layout.setHorizontalGroup(
+            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(jPanel2Layout.createSequentialGroup()
+                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 782, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addGap(0, 0, Short.MAX_VALUE))
+        );
+        jPanel2Layout.setVerticalGroup(
+            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 760, Short.MAX_VALUE)
+        );
+
+        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
+        jPanel1.setLayout(jPanel1Layout);
+        jPanel1Layout.setHorizontalGroup(
+            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(jPanel1Layout.createSequentialGroup()
+                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, 783, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addGap(0, 442, Short.MAX_VALUE))
+        );
+        jPanel1Layout.setVerticalGroup(
+            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(jPanel1Layout.createSequentialGroup()
+                .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, 56, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+
+        add(jPanel1, java.awt.BorderLayout.CENTER);
+    }// </editor-fold>//GEN-END:initComponents
+
+    /**
+     * Adds new model
+     * @param evt starts function for loading model
+     */
+    private void addButton1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_addButton1MouseClicked
+        loadModel();
+    }//GEN-LAST:event_addButton1MouseClicked
+
+    /**
+     * Removes selected models from list and project
+     * @param evt Removes selected faces
+     */
+    private void removeButton1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_removeButton1MouseClicked
+
+        Collections.sort(selectedRows, Collections.reverseOrder());
+        selectedRows.forEach(row -> {
+            HumanFace face = this.project.getFaceByName(model.getValueAt(row, 1).toString());
+            this.project.removeFace(face);
+            model.removeRow(row);
+        });
+        selectedRows.clear();
+    }//GEN-LAST:event_removeButton1MouseClicked
+    
+    /**
+     * Opens 1:1 tab with two selected faces, otherwise pops message that you
+     * should select two faces
+     * @param evt 
+     */
+    private void oneOnOneButton1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_oneOnOneButton1MouseClicked
+        //loadTwoModels();
+
+        if (selectedRows.size() == 2) {
+
+            String name1 = model.getValueAt(selectedRows.get(0), 1).toString();
+            String name2 = model.getValueAt(selectedRows.get(1), 1).toString();
+            HumanFace face1 = project.getFaceByName(name1);
+            HumanFace face2 = project.getFaceByName(name2);
+            createFaceToFaceTab(face1, face2, name1 + ":" + name2);
+        } else {
+            JOptionPane.showMessageDialog(this, "Select two models");
+        }
+    }//GEN-LAST:event_oneOnOneButton1MouseClicked
+
+    /**
+     * Selects all models from list of models
+     * @param evt 
+     */
+    private void selectAllButton1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_selectAllButton1MouseClicked
+        byUser = false;
+        for (int i = 0; i < model.getRowCount(); i++) {
+            model.setValueAt(true, i, 0);
+        }
+        selectedRows = IntStream.range(0, model.getRowCount()).boxed().collect(Collectors.toList());
+        byUser = true;
+
+    }//GEN-LAST:event_selectAllButton1MouseClicked
+
+    /**
+     * Deselects all models from list of models
+     * @param evt 
+     */
+    private void deselectAllButton1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_deselectAllButton1MouseClicked
+        byUser = false;
+        selectedRows.forEach(i -> {
+            model.setValueAt(false, i, 0);
+        });
+        selectedRows.clear();
+        byUser = true;
+    }//GEN-LAST:event_deselectAllButton1MouseClicked
+
+    /**
+     * Inflates models (selected will be deselected and vice versa)
+     * @param evt 
+     */
+    private void inflateButton1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_inflateButton1MouseClicked
+        byUser = false;
+        for (int i = 0; i < model.getRowCount(); i++) {
+            if (model.getValueAt(i, 0) == (Object) true) {
+                model.setValueAt(false, i, 0);
+            } else {
+                model.setValueAt(true, i, 0);
+            }
+        }
+
+        List<Integer> allRows = IntStream.range(0, model.getRowCount()).boxed().collect(Collectors.toList());
+        allRows.removeAll(selectedRows);
+        selectedRows = allRows;
+        byUser = true;
+    }//GEN-LAST:event_inflateButton1MouseClicked
+
+    /**
+     * Opens analysis of one selected face, otherwise pops message dialog that
+     * you should select just one face
+     * @param evt 
+     */
+    private void analyseButton1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_analyseButton1MouseClicked
+
+        if (selectedRows.size() == 1) {
+
+            String name = model.getValueAt(selectedRows.get(0), 1).toString();
+            HumanFace face = project.getFaceByName(name);
+            createSingleFaceTab(face, name);
+        } else {
+            JOptionPane.showMessageDialog(this, "Select one model");
+        }
+
+    }//GEN-LAST:event_analyseButton1MouseClicked
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JButton addButton1;
+    private javax.swing.JButton analyseButton1;
+    private javax.swing.JButton deselectAllButton1;
+    private javax.swing.JButton inflateButton1;
+    private javax.swing.JPanel jPanel1;
+    private javax.swing.JPanel jPanel2;
+    private javax.swing.JPanel jPanel5;
+    private javax.swing.JScrollPane jScrollPane1;
+    private javax.swing.JTable jTable1;
+    private javax.swing.JButton oneOnOneButton1;
+    private javax.swing.JButton removeButton1;
+    private javax.swing.JButton selectAllButton1;
+    // End of variables declaration//GEN-END:variables
+    @Override
+    public void componentOpened() {
+        // TODO add custom code on component opening
+    }
+
+    @Override
+    public void componentClosed() {
+        // TODO add custom code on component closing
+    }
+
+    void writeProperties(java.util.Properties p) {
+        // better to version settings since initial version as advocated at
+        // http://wiki.apidesign.org/wiki/PropertyFiles
+        p.setProperty("version", "1.0");
+        // TODO store your settings
+    }
+
+    void readProperties(java.util.Properties p) {
+        String version = p.getProperty("version");
+        // TODO read your settings according to their version
+    }
+
+    /**
+     * Loads model selected in file chooser by user
+     */
+    public void loadModel() {
+        File file = new FileChooserBuilder(ProjectTopComp.class)
+                .setTitle("Open human face(s)")
+                .setDefaultWorkingDirectory(new File(System.getProperty("user.home")))
+                //.setApproveText("Add")
+                .setFileFilter(new FileNameExtensionFilter("obj files (*.obj)", "obj"))
+                .setAcceptAllFileFilterUsed(true)
+                .showOpenDialog();
+
+        if (file == null) {
+            System.out.print("No file chosen.");
+        } else {
+            OutputWindow out = OutputWindow.measureTime();
+            String faceId = HumanFaceFactory.instance().loadFace(file);
+            HumanFace face = HumanFaceFactory.instance().getFace(faceId);
+            out.printDuration("Loaded model " + face.getShortName() +" with " + face.getMeshModel().getNumVertices() + " vertices");
+
+            try {
+                // simple hack:
+                Path path = Paths.get(file.getAbsolutePath());
+                Path folder = path.getParent();
+                Path filename = path.getFileName();
+                String filestr = filename.toString();
+                filestr = filestr.split("_ECA.obj")[0];
+                filestr = filestr + "_landmarks.csv";
+                face.loadFeaturePoints(folder.toString(), filestr);
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            }
+
+            String name = face.getShortName();
+            if (this.project.getFaceByName(name) == null) {
+                this.project.addFace(face);
+                model.addRow(new Object[]{false, name});
+                //createSingleFaceTab(face, name);
+            } else {
+                JOptionPane.showMessageDialog(this, "Model with this name is already loaded");
+            }
+        }
+    }
+
+    /**
+     * Load two models for 1:1 comparison
+     
+    public void loadTwoModels() {
+        
+        File file1 = new FileChooserBuilder(ProjectTopComp.class)
+                .setTitle("Open human face(s)")
+                .setDefaultWorkingDirectory(new File (System.getProperty("user.home")))
+                //.setApproveText("Add")
+                .setFileFilter(new FileNameExtensionFilter("obj files (*.obj)", "obj"))
+                .setAcceptAllFileFilterUsed(true)
+                .showOpenDialog();
+        
+        File file2 = new FileChooserBuilder(ProjectTopComp.class)
+                .setTitle("Open human face(s)")
+                .setDefaultWorkingDirectory(new File (System.getProperty("user.home")))
+                //.setApproveText("Add")
+                .setFileFilter(new FileNameExtensionFilter("obj files (*.obj)", "obj"))
+                .setAcceptAllFileFilterUsed(true)
+                .showOpenDialog();
+        
+        if (file1 == null || file2 == null) {
+            System.out.print("Missing file.");
+        } else {
+            String faceId1 = HumanFaceFactory.instance().loadFace(file1);
+            String faceId2 = HumanFaceFactory.instance().loadFace(file2);
+            HumanFace face1 = HumanFaceFactory.instance().getFace(faceId1);
+            HumanFace face2 = HumanFaceFactory.instance().getFace(faceId2);
+            
+            try {
+                // simple hack:
+                Path path = Paths.get(file1.getAbsolutePath());
+                Path folder = path.getParent();
+                Path filename = path.getFileName();
+                String filestr = filename.toString();
+                filestr = filestr.split("_ECA.obj")[0];
+                filestr = filestr + "_landmarks.csv";
+                face1.loadFeaturePoints(folder.toString(), filestr);
+            } catch(IOException ex) {
+                ex.printStackTrace();
+            }
+            
+            try {
+                // simple hack:
+                Path path = Paths.get(file2.getAbsolutePath());
+                Path folder = path.getParent();
+                Path filename = path.getFileName();
+                String filestr = filename.toString();
+                filestr = filestr.split("_ECA.obj")[0];
+                filestr = filestr + "_landmarks.csv";
+                face2.loadFeaturePoints(folder.toString(), filestr);
+            } catch(IOException ex) {
+                ex.printStackTrace();
+            }
+            
+            //this.project.setPrimaryFace(face1);
+            //this.project.addFace(face1);
+            this.project.setFaces(List.of(face1, face2));
+            createFaceToFaceTab(face1, face2, "1:1");
+
+        javax.swing.table.DefaultTableModel model = (javax.swing.table.DefaultTableModel) jTable1.getModel();
+
+        if (selectedRows.size() == 2) {
+
+            String name1 = model.getValueAt(selectedRows.get(0), 1).toString();
+            String name2 = model.getValueAt(selectedRows.get(1), 1).toString();
+            HumanFace face1 = project.getFaceByName(name1);
+            HumanFace face2 = project.getFaceByName(name2);
+            createFaceToFaceTab(face1, face2, name1 + ":" + name2);
+        } else {
+            JOptionPane.showMessageDialog(this, "Select two models");
+        }
+    }*/
+
+   /**
+    * Creates and opens tab with one face
+    * @param face which will be analyzed
+    * @param name name of the tab (name of the model)
+    */
+    private void createSingleFaceTab(HumanFace face, String name) {
+        SingleFaceTab newTab = new SingleFaceTab(face, name);
+        this.singleFaceTabs.put(face, newTab);
+        newTab.open();
+        newTab.requestActive();
+    }
+
+    /**
+     * Creates and opens tab with two faces (1:1 analysis)
+     * @param face1 which will be analyzed
+     * @param face2 which will be analyzed
+     * @param name name of the tab
+     */
+    private void createFaceToFaceTab(HumanFace face1, HumanFace face2, String name) {
+        FaceToFaceTab newTab = new FaceToFaceTab(face1, face2, name);
+        this.faceToFaceTabs.put(face1, newTab);
+        this.faceToFaceTabs.put(face2, newTab);
+        newTab.open();
+        newTab.requestActive();
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/SingleFaceTab.java b/GUI/src/main/java/cz/fidentis/analyst/core/SingleFaceTab.java
new file mode 100644
index 0000000000000000000000000000000000000000..110c601f7a893b1cafb962d0a42673bbefd2f2b8
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/core/SingleFaceTab.java
@@ -0,0 +1,88 @@
+package cz.fidentis.analyst.core;
+
+import cz.fidentis.analyst.canvas.Canvas;
+import cz.fidentis.analyst.face.HumanFace;
+import cz.fidentis.analyst.toolbar.RenderingToolBar;
+import cz.fidentis.analyst.toolbar.SingleFaceToolBar;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import javax.swing.GroupLayout;
+import javax.swing.JScrollPane;
+import javax.swing.LayoutStyle;
+import org.openide.windows.TopComponent;
+
+/**
+ * The non-singleton window/tab for detail inspection of a single face.
+ *
+ * @author Radek Oslejsek
+ */
+public final class SingleFaceTab extends TopComponent {
+    
+    private final Canvas canvas;
+    private final RenderingToolBar renderingToolBar;
+    private final TopControlPanel controlPanel;
+    private final JScrollPane scrollPane;
+    
+    /**
+     * Constructor.
+     * @param face Face
+     * @param name Tab name
+     */
+    public SingleFaceTab(HumanFace face, String name) {
+        canvas = new Canvas();
+        canvas.initScene(face);
+        controlPanel = new TopControlPanel();
+        renderingToolBar = new SingleFaceToolBar(canvas, controlPanel);
+        
+        scrollPane = new JScrollPane(controlPanel);
+        
+        setName(name);
+        initComponents();
+        
+        // change the height so that it corresponds to the height of the OpenGL window
+        canvas.addComponentListener(new ComponentAdapter() {
+            @Override
+            public void componentResized(ComponentEvent e) {
+                scrollPane.setSize(ControlPanel.CONTROL_PANEL_WIDTH, canvas.getHeight());
+            }
+        });
+    }
+    
+    @Override
+    public int getPersistenceType() {
+        return TopComponent.PERSISTENCE_NEVER; // TO DO: change to .PERSISTENCE_ONLY_OPENED when we can re-create the ProjectTC
+    }
+    
+    private void initComponents() {
+        GroupLayout layout = new GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+                layout.createParallelGroup(GroupLayout.Alignment.LEADING)
+                        .addGroup(layout.createSequentialGroup()
+                                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+                                .addComponent(canvas, GroupLayout.DEFAULT_SIZE, 651, Short.MAX_VALUE)
+                                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+                                .addComponent(renderingToolBar, GroupLayout.PREFERRED_SIZE, RenderingToolBar.WIDTH, GroupLayout.PREFERRED_SIZE)
+                                .addComponent(
+                                        scrollPane,
+                                        ControlPanel.CONTROL_PANEL_WIDTH, 
+                                        ControlPanel.CONTROL_PANEL_WIDTH, 
+                                        ControlPanel.CONTROL_PANEL_WIDTH
+                                )
+                        )
+        );
+        layout.setVerticalGroup(
+                layout.createParallelGroup(GroupLayout.Alignment.LEADING)
+                        .addGroup(layout.createSequentialGroup()
+                                .addGroup(layout.createBaselineGroup(true, true)
+                                        .addComponent(canvas)
+                                        .addComponent(renderingToolBar)
+                                        .addComponent(scrollPane)
+                                ))
+        );
+    }
+
+    public Canvas getCanvas() {
+        return canvas;
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/TopControlPanel.java b/GUI/src/main/java/cz/fidentis/analyst/core/TopControlPanel.java
new file mode 100644
index 0000000000000000000000000000000000000000..0b0a21f83136c6ff164a2105b83529e8b6eb6702
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/core/TopControlPanel.java
@@ -0,0 +1,24 @@
+package cz.fidentis.analyst.core;
+
+import java.awt.Font;
+import javax.swing.BorderFactory;
+import javax.swing.JTabbedPane;
+import javax.swing.border.TitledBorder;
+
+/**
+ * The space for control panels.
+ * 
+ * @author Radek Oslejsek
+ */
+public class TopControlPanel extends JTabbedPane {
+    
+    /**
+     * Constructor.
+     */
+    public TopControlPanel() {
+        TitledBorder border = BorderFactory.createTitledBorder("Control Panels");
+        border.setTitleFont(border.getTitleFont().deriveFont(Font.BOLD));
+        //border.setTitleColor(ControlPanelBuilder.OPTION_TEXT_COLOR);
+        //setBorder(border);
+    }    
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/curvature/CurvatureAction.java b/GUI/src/main/java/cz/fidentis/analyst/curvature/CurvatureAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..c745c98cfa174fe6a7d062a004121c18ce69c6ef
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/curvature/CurvatureAction.java
@@ -0,0 +1,94 @@
+package cz.fidentis.analyst.curvature;
+
+import cz.fidentis.analyst.canvas.Canvas;
+import cz.fidentis.analyst.core.ControlPanelAction;
+import cz.fidentis.analyst.core.OutputWindow;
+import cz.fidentis.analyst.visitors.mesh.Curvature;
+import java.awt.event.ActionEvent;
+import javax.swing.JComboBox;
+import javax.swing.JTabbedPane;
+import javax.swing.JToggleButton;
+
+/**
+ * Action listener for the curvature computation.
+ * 
+ * @author Radek Oslejsek
+ */
+public class CurvatureAction extends ControlPanelAction {
+    
+    /*
+     * Attributes handling the state
+     */
+    private Curvature visitor = null;
+    private String curvatureType = CurvaturePanel.GAUSSIAN_CURVATURE;
+    
+    private final CurvaturePanel controlPanel;
+    
+    /**
+     * Constructor.
+     * 
+     * @param canvas OpenGL canvas
+     * @param topControlPanel Top component for placing control panels
+     */
+    public CurvatureAction(Canvas canvas, JTabbedPane topControlPanel) {
+        super(canvas, topControlPanel);
+        this.controlPanel = new CurvaturePanel(this);
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent ae) {
+        String action = ae.getActionCommand();
+        
+        switch (action) {
+            case CurvaturePanel.ACTION_COMMAND_SHOW_HIDE_PANEL:
+                hideShowPanelActionPerformed(ae, this.controlPanel);
+                break;
+            case CurvaturePanel.ACTION_COMMAND_SHOW_HIDE_HEATMAP:
+                if (((JToggleButton) ae.getSource()).isSelected()) {
+                    setHeatmap();
+                    getPrimaryDrawableFace().setRenderHeatmap(true);
+                } else {
+                    getPrimaryDrawableFace().setRenderHeatmap(false);
+                }
+                break;
+            case CurvaturePanel.ACTION_COMMAND_SET_CURVATURE_TYPE:
+                this.curvatureType = (String) ((JComboBox) ae.getSource()).getSelectedItem();
+                setHeatmap();
+                break;
+            default:
+                // to nothing
+        }
+        
+        renderScene();
+    }
+    
+    protected void setHeatmap() {
+        if (visitor == null) { // compute missing curvature
+            OutputWindow out = OutputWindow.measureTime();
+            this.visitor = new Curvature();
+            getPrimaryDrawableFace().getModel().compute(visitor);
+            out.printDuration("Computation of curvature for a model with " 
+                    + getPrimaryDrawableFace().getHumanFace().getMeshModel().getNumVertices()
+                    + " vertices"
+            );
+        }
+        
+        switch (this.curvatureType) {
+            case CurvaturePanel.GAUSSIAN_CURVATURE:
+                    getPrimaryDrawableFace().setHeatMap(visitor.getGaussianCurvatures());
+                break;
+            case CurvaturePanel.MEAN_CURVATURE:
+                    getPrimaryDrawableFace().setHeatMap(visitor.getMeanCurvatures());
+                break;
+            case CurvaturePanel.MIN_CURVATURE:
+                    getPrimaryDrawableFace().setHeatMap(visitor.getMinPrincipalCurvatures());
+                break;
+            case CurvaturePanel.MAX_CURVATURE:
+                    getPrimaryDrawableFace().setHeatMap(visitor.getMaxPrincipalCurvatures());
+                break;
+            default:
+                throw new UnsupportedOperationException(curvatureType);
+        }
+        
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/curvature/CurvaturePanel.java b/GUI/src/main/java/cz/fidentis/analyst/curvature/CurvaturePanel.java
new file mode 100644
index 0000000000000000000000000000000000000000..42780c63da124e22962f3463c27789c07d8ed585
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/curvature/CurvaturePanel.java
@@ -0,0 +1,77 @@
+package cz.fidentis.analyst.curvature;
+
+import cz.fidentis.analyst.core.ControlPanel;
+import cz.fidentis.analyst.core.ControlPanelBuilder;
+import java.awt.event.ActionListener;
+import java.util.List;
+import javax.swing.ImageIcon;
+
+/**
+ * Control panel for curvature analysis.
+ * 
+ * @author Radek Oslejsek
+ */
+public class CurvaturePanel extends ControlPanel {
+    
+    /*
+     * Mandatory design elements
+     */
+    public static final String ICON = "curvature28x28.png";
+    public static final String NAME = "Curvature";
+    
+    /*
+     * External actions
+     */
+    public static final String ACTION_COMMAND_SHOW_HIDE_HEATMAP = "show-hide heatmap";
+    public static final String ACTION_COMMAND_SET_CURVATURE_TYPE = "set curvature type";
+    
+    /*
+     * Configuration of panel-specific GUI elements
+     */
+    public static final String GAUSSIAN_CURVATURE = "Gaussian";
+    public static final String MEAN_CURVATURE = "Mean";
+    public static final String MIN_CURVATURE = "Min";
+    public static final String MAX_CURVATURE = "Max";
+    
+    /**
+     * Constructor.
+     * @param action Action listener
+     */
+    public CurvaturePanel(ActionListener action) {
+        this.setName(NAME);
+        
+        ControlPanelBuilder builder = new ControlPanelBuilder(this);
+        
+        builder.addCaptionLine("Visualization options:");
+        builder.addLine();
+        
+        builder.addCheckBoxOptionLine(
+                null, 
+                "Show curvature", 
+                false,
+                createListener(action, ACTION_COMMAND_SHOW_HIDE_HEATMAP));
+        builder.addComboBox(
+                List.of(GAUSSIAN_CURVATURE, MEAN_CURVATURE, MIN_CURVATURE, MAX_CURVATURE), 
+                createListener(action, ACTION_COMMAND_SET_CURVATURE_TYPE)
+        );
+        builder.addGap();
+        builder.addLine();
+        builder.addCaptionLine("TO DO: Interactive histogram");
+        builder.addLine();
+        builder.addVerticalStrut();
+    }
+
+    @Override
+    public ImageIcon getIcon() {
+        return getStaticIcon();
+    }
+    
+    /**
+     * Static implementation of the {@link #getIcon()} method.
+     * 
+     * @return Control panel icon
+     */
+    public static ImageIcon getStaticIcon() {
+        return new ImageIcon(CurvaturePanel.class.getClassLoader().getResource("/" + ICON));
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/distance/DistanceAction.java b/GUI/src/main/java/cz/fidentis/analyst/distance/DistanceAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..0263a00518c5916bc163d1ad75fed7176ac75102
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/distance/DistanceAction.java
@@ -0,0 +1,481 @@
+package cz.fidentis.analyst.distance;
+
+import com.jogamp.opengl.GL2;
+import cz.fidentis.analyst.canvas.Canvas;
+import cz.fidentis.analyst.core.LoadedActionEvent;
+import cz.fidentis.analyst.core.ControlPanelAction;
+import cz.fidentis.analyst.core.ControlPanelBuilder;
+import cz.fidentis.analyst.core.OutputWindow;
+import cz.fidentis.analyst.feature.FeaturePoint;
+import cz.fidentis.analyst.feature.FeaturePointType;
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.scene.DrawableFeaturePoints;
+import cz.fidentis.analyst.visitors.face.HausdorffDistancePrioritized;
+import cz.fidentis.analyst.visitors.mesh.HausdorffDistance.Strategy;
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import javax.swing.JComboBox;
+import javax.swing.JTabbedPane;
+import javax.swing.JTextField;
+import javax.swing.JToggleButton;
+import javax.vecmath.Point3d;
+
+/**
+ * Action listener for computation of the Hausdorff distance.
+ * 
+ * @author Radek Oslejsek
+ * @author Daniel Schramm
+ */
+public class DistanceAction extends ControlPanelAction {
+    
+    /*
+     * Attributes handling the state
+     */
+    private HausdorffDistancePrioritized visitor = null;
+    private final Map<FeaturePointType, Double> featurePointTypes;
+    private String strategy = DistancePanel.STRATEGY_POINT_TO_POINT;
+    private boolean relativeDist = false;
+    private String heatmapDisplayed = DistancePanel.HEATMAP_HAUSDORFF_DISTANCE;
+    private boolean weightedFPsShow = true;
+    
+    private FeaturePointType hoveredFeaturePoint = null;
+    
+    private final DistancePanel controlPanel;
+    private final DrawableFeaturePoints weightedFeaturePoints;
+    
+    private static final Color WEIGHTED_FEATURE_POINT_DEFAULT_COLOR = Color.WHITE;
+    private static final Color FEATURE_POINT_HIGHLIGHT_COLOR = Color.MAGENTA;
+    private static final Color FEATURE_POINT_HOVER_COLOR = Color.CYAN;
+    
+    /**
+     * Constructor.
+     * 
+     * @param canvas OpenGL canvas
+     * @param topControlPanel Top component for placing control panels
+     */
+    public DistanceAction(Canvas canvas, JTabbedPane topControlPanel) {
+        super(canvas, topControlPanel);
+        
+        // Calculate weighted Hausdorff distance for all feature points of the secondary face
+        calculateHausdorffDistance(
+                getSecondaryFeaturePoints().getFeaturePoints()
+                        .stream()
+                        .collect(Collectors.toMap(
+                                FeaturePoint::getFeaturePointType,
+                                featurePoint -> DrawableFeaturePoints.DEFAULT_SIZE))
+        );
+        
+        this.featurePointTypes = visitor.getFeaturePointWeights()
+                .get(getSecondaryDrawableFace().getHumanFace()) // Get FP weights for the secondary face
+                .entrySet()
+                .stream()
+                .map(fpWeights -> Map.entry(
+                        fpWeights.getKey(),  // For each FP type at the secondary face...
+                        fpWeights.getValue() // ... compute average FP weight over all its facets
+                                .values()
+                                .stream()
+                                .mapToDouble(Double::doubleValue)
+                                .average()
+                                .orElse(Double.NaN)))
+                .filter(fpWeight -> !Double.isNaN(fpWeight.getValue())) // Filter out feature points with Double.NaN weight
+                .collect(Collectors.toMap(
+                        Map.Entry::getKey,
+                        fpType -> DrawableFeaturePoints.DEFAULT_SIZE));
+        this.controlPanel = new DistancePanel(this, getSecondaryFeaturePoints().getFeaturePoints(), featurePointTypes.keySet());
+        this.visitor = null;
+        
+        // Add weighted feature points to the scene
+        this.weightedFeaturePoints = new DrawableFeaturePoints(getSecondaryFeaturePoints().getFeaturePoints());
+        weightedFeaturePoints.setRenderMode(GL2.GL_LINE);
+        weightedFeaturePoints.setColor(WEIGHTED_FEATURE_POINT_DEFAULT_COLOR);
+        getCanvas().getScene().addOtherDrawable(weightedFeaturePoints);
+        
+        // Place control panel to the topControlPanel
+        topControlPanel.addTab(controlPanel.getName(), controlPanel.getIcon(), controlPanel);
+        topControlPanel.addChangeListener(e -> {
+            // If the distance panel is focused...
+            if (((JTabbedPane) e.getSource()).getSelectedComponent() instanceof DistancePanel) {
+                // ... display heatmap and feature points relevant to the Hausdorff distance
+                getCanvas().getScene().setDefaultColors();
+                weightedFeaturePoints.resetAllColorsToDefault();
+                if (weightedFPsShow) {
+                    weightedFeaturePoints.show();
+                }
+                
+                boolean secondaryFaceMoved = false;
+                final List<FeaturePoint> secondaryFPs = getSecondaryFeaturePoints().getFeaturePoints();
+                final List<FeaturePoint> weightedFPs = weightedFeaturePoints.getFeaturePoints();
+                for (int i = 0; i < secondaryFPs.size(); i++) {
+                    final FeaturePoint faceFP = secondaryFPs.get(i);
+                    final FeaturePoint weightedFP = weightedFPs.get(i);
+                    
+                    // Highlight feature point if selected
+                    if (featurePointTypes.containsKey(faceFP.getFeaturePointType())) {
+                        colorSecondaryFaceFeaturePoint(i, FEATURE_POINT_HIGHLIGHT_COLOR);
+                    }
+                    if (!faceFP.getPosition().equals(weightedFP.getPosition())) {
+                        secondaryFaceMoved = true;
+                    }
+                }
+                
+                // If the position of secondary face has been changed
+                if (secondaryFaceMoved) {
+                    visitor = null; // recompute Hausdorff distance
+                    
+                    // Relocate weighted feature points
+                    for (int i = 0; i < secondaryFPs.size(); i++) {
+                        final Point3d faceFpPos = secondaryFPs.get(i).getPosition();
+                        final Point3d weightedFpPos = weightedFPs.get(i).getPosition();
+                        
+                        weightedFpPos.x = faceFpPos.x;
+                        weightedFpPos.y = faceFpPos.y;
+                        weightedFpPos.z = faceFpPos.z;
+                    }
+                }
+                
+                updateHausdorffDistanceInformation();
+                getSecondaryDrawableFace().setRenderHeatmap(isHeatmapDisplayed());
+            } else {
+                weightedFeaturePoints.hide();
+                getSecondaryDrawableFace().clearHeatMapSaturation();
+            }
+        });
+        topControlPanel.setSelectedComponent(controlPanel); // Focus Hausdorff distance panel
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent ae) {
+        final String action = ae.getActionCommand();
+        
+        switch (action) {
+            case DistancePanel.ACTION_COMMAND_SET_DISPLAYED_HEATMAP:
+                heatmapDisplayed = (String) ((JComboBox) ae.getSource()).getSelectedItem();
+                updateHausdorffDistanceInformation();
+                getSecondaryDrawableFace().setRenderHeatmap(isHeatmapDisplayed());
+                break;
+            case DistancePanel.ACTION_COMMAND_SHOW_HIDE_WEIGHTED_FPOINTS:
+                weightedFPsShow = ((JToggleButton) ae.getSource()).isSelected();
+                if (weightedFPsShow) {
+                    weightedFeaturePoints.show();
+                } else {
+                    weightedFeaturePoints.hide();
+                }
+                break;
+            case DistancePanel.ACTION_COMMAND_SET_DISTANCE_STRATEGY:
+                strategy = (String) ((JComboBox) ae.getSource()).getSelectedItem();
+                recompute();
+                break;
+            case DistancePanel.ACTION_COMMAND_RELATIVE_ABSOLUTE_DIST:
+                this.relativeDist = ((JToggleButton) ae.getSource()).isSelected();
+                recompute();
+                break;
+            case DistancePanel.ACTION_COMMAND_FEATURE_POINT_HIGHLIGHT:
+                highlightFeaturePoint((LoadedActionEvent) ae);
+                recompute();
+                break;
+            case DistancePanel.ACTION_COMMAND_FEATURE_POINT_SELECT_ALL:
+                highlightAllFeaturePoints(true);
+                recompute();
+                break;
+            case DistancePanel.ACTION_COMMAND_FEATURE_POINT_SELECT_NONE:
+                highlightAllFeaturePoints(false);
+                recompute();
+                break;
+            case DistancePanel.ACTION_COMMAND_FEATURE_POINT_HOVER_IN:
+                hoverFeaturePoint((LoadedActionEvent) ae, true);
+                break;
+            case DistancePanel.ACTION_COMMAND_FEATURE_POINT_HOVER_OUT:
+                hoverFeaturePoint((LoadedActionEvent) ae, false);
+                break;
+            case DistancePanel.ACTION_COMMAND_FEATURE_POINT_RESIZE:
+                resizeFeaturePoint((LoadedActionEvent) ae);
+                break;
+            case DistancePanel.ACTION_COMMAND_DISTANCE_RECOMPUTE:
+                recompute();
+                break;
+            default:
+                // to nothing
+        }
+        renderScene();
+    }
+    
+    /**
+     * Recalculates the Hausdorff distance and updates all GUI elements
+     * of {@link DistancePanel}.
+     */
+    private void recompute() {
+        this.visitor = null;
+        updateHausdorffDistanceInformation();
+    }
+    
+    /**
+     * (Re)calculates the Hausdorff distance and updates the heat map of the secondary face
+     * as well as values of all appropriate GUI elements of {@link DistancePanel}.
+     */
+    private void updateHausdorffDistanceInformation() {
+        if (visitor == null) {
+            calculateHausdorffDistance(featurePointTypes);
+            
+            // Update GUI elements that display the calculated Hausdorff distance metrics
+            setFeaturePointWeigths();
+            setHausdorffDistanceStatistics();
+        }
+        
+        switch (heatmapDisplayed) {
+            case DistancePanel.HEATMAP_HAUSDORFF_DISTANCE:
+                getSecondaryDrawableFace().clearHeatMapSaturation();
+                break;
+            case DistancePanel.HEATMAP_WEIGHTED_HAUSDORFF_DISTANCE:
+                getSecondaryDrawableFace().setHeatMapSaturation(
+                        visitor.getMergedPriorities()
+                                .get(getSecondaryDrawableFace().getHumanFace())
+                );
+                break;
+            case DistancePanel.HEATMAP_HIDE:
+                return;
+            default:
+                throw new UnsupportedOperationException(heatmapDisplayed);
+        }
+        getSecondaryDrawableFace().setHeatMap(visitor.getDistances());
+    }
+    
+    /**
+     * (Re)calculates the Hausdorff distance.
+     * 
+     * @param featurePoints Types of feature points according to which the Hausdorff
+     *                      distances will be prioritized together with
+     *                      the radii of priority spheres around the feature
+     *                      points of the corresponding type.
+     *                      Must not be {@code null}.
+     */
+    private void calculateHausdorffDistance(Map<FeaturePointType, Double> featurePoints) {
+        final Strategy useStrategy;
+        switch (strategy) {
+            case DistancePanel.STRATEGY_POINT_TO_POINT:
+                useStrategy = Strategy.POINT_TO_POINT;
+                break;
+            case DistancePanel.STRATEGY_POINT_TO_TRIANGLE:
+                useStrategy = Strategy.POINT_TO_TRIANGLE_APPROXIMATE;
+                break;
+            default:
+                throw new UnsupportedOperationException(strategy);
+        }
+        
+        OutputWindow out = OutputWindow.measureTime();
+        this.visitor = new HausdorffDistancePrioritized(getPrimaryDrawableFace().getModel(),
+                featurePoints,
+                useStrategy,
+                relativeDist,
+                true);
+        getSecondaryDrawableFace().getHumanFace().accept(visitor);
+        out.printDuration("Computation of Hausdorff distance for models with " 
+                + getPrimaryDrawableFace().getHumanFace().getMeshModel().getNumVertices()
+                + "/"
+                + getSecondaryDrawableFace().getHumanFace().getMeshModel().getNumVertices()
+                + " vertices"
+        );
+    }
+    
+    /**
+     * Updates the GUI elements of {@link DistancePanel} that display
+     * the weights of feature points used to calculate the weighted Hausdorff distance.
+     */
+    private void setFeaturePointWeigths() {
+        controlPanel.updateFeaturePointWeights(
+                visitor.getFeaturePointWeights()
+                        .get(getSecondaryDrawableFace().getHumanFace()) // Get FP weights for the secondary face
+                        .entrySet()
+                        .stream()
+                        .collect(
+                                Collectors.toMap(
+                                        Map.Entry::getKey,            // For each FP type at the secondary face...
+                                        weights -> weights.getValue() // ... compute average FP weight over all its facets
+                                                .values()
+                                                .stream()
+                                                .mapToDouble(Double::doubleValue)
+                                                .average()
+                                                .orElse(Double.NaN))));
+    }
+
+    /**
+     * Updates the GUI elements of {@link DistancePanel} elements that display
+     * statistical data about the calculated Hausdorff distance.
+     */
+    private void setHausdorffDistanceStatistics() {
+        controlPanel.updateHausdorffDistanceStats(
+                visitor.getDistances()
+                        .values()
+                        .stream()
+                        .flatMap(List::stream)
+                        .mapToDouble(Double::doubleValue)
+                        .summaryStatistics(),
+                getWeightedDistance()
+                        .values()
+                        .stream()
+                        .flatMap(List::stream)
+                        .mapToDouble(Double::doubleValue)
+                        .summaryStatistics()
+        );
+    }
+    
+    /**
+     * Calculates weighted Hausdorff distance of the face.
+     * 
+     * @return weighted Hausdorff distance
+     */
+    private Map<MeshFacet, List<Double>> getWeightedDistance() {
+        final Map<MeshFacet, List<Double>> weightedDistances = new HashMap<>(visitor.getDistances());
+        final Map<MeshFacet, List<Double>> mergedPriorities = visitor.getMergedPriorities()
+                .get(getSecondaryDrawableFace().getHumanFace());
+
+        // Merge the map of distances with the map of priorities
+        for (final Map.Entry<MeshFacet, List<Double>> facetPriorities: mergedPriorities.entrySet()) {
+            weightedDistances.merge(
+                    facetPriorities.getKey(),
+                    facetPriorities.getValue(),
+                    (distancesList, prioritiesList) ->
+                            IntStream.range(0, distancesList.size())
+                                    .mapToDouble(i -> distancesList.get(i) * prioritiesList.get(i))
+                                    .boxed()
+                                    .collect(Collectors.toList()));
+        }
+
+        return weightedDistances;
+    }
+    
+    /**
+     * Returns {@code true} if the heatmap is displayed and {@code false} otherwise.
+     * 
+     * @return {@code true} if the heatmap is displayed, {@code false} otherwise
+     */
+    private boolean isHeatmapDisplayed() {
+        return !DistancePanel.HEATMAP_HIDE.equals(heatmapDisplayed);
+    }
+    
+    /**
+     * Changes the color of the secondary face's feature point at the given index
+     * and of its weighted representation when the feature point is (de)selected
+     * for the computation of the weighted Hausdorff distance.
+     * The index is received as the data payload of {@code actionEvent}.
+     * 
+     * @param actionEvent Action event with the index of the feature point as its payload data
+     */
+    private void highlightFeaturePoint(LoadedActionEvent actionEvent) {
+        final int index = (int) actionEvent.getData();
+        final FeaturePointType fpType = getTypeOfFeaturePoint(index);
+        
+        if (((JToggleButton) actionEvent.getSource()).isSelected()) {
+            colorSecondaryFaceFeaturePoint(index, FEATURE_POINT_HIGHLIGHT_COLOR);
+            featurePointTypes.put(fpType, weightedFeaturePoints.getSize(index));
+        } else {
+            resetSecondaryFaceFeaturePointColor(index);
+            featurePointTypes.remove(fpType);
+        }
+    }
+    
+    /**
+     * Changes the color of all secondary face's feature points and of their
+     * weighted representations.
+     * All feature points are also (de)selected for the computation
+     * of the weighted Hausdorff distance.
+     * 
+     * @param highlighted {@code true} if the feature points are to be highlighted,
+     *                    {@code false} otherwise
+     */
+    private void highlightAllFeaturePoints(boolean highlighted) {
+        if (highlighted) {
+            final List<FeaturePoint> featurePoints = getSecondaryFeaturePoints().getFeaturePoints();
+            for (int i = 0; i < featurePoints.size(); i++) {
+                colorSecondaryFaceFeaturePoint(i, FEATURE_POINT_HIGHLIGHT_COLOR);
+                featurePointTypes.put(
+                        featurePoints.get(i).getFeaturePointType(),
+                        weightedFeaturePoints.getSize(i)
+                );
+            }
+        } else {
+            getSecondaryFeaturePoints().resetAllColorsToDefault();
+            weightedFeaturePoints.resetAllColorsToDefault();
+            featurePointTypes.clear();
+        }
+    }
+    
+    /**
+     * Changes the color of the secondary face's feature point at the given index
+     * and of its weighted representation when the cursor hovers over the feature point's name.
+     * The index is received as the data payload of {@code actionEvent}.
+     * 
+     * @param actionEvent Action event with the index of the feature point as its payload data
+     * @param entered {@code true} if the cursor entered the feature point,
+     *                {@code false} if the cursor left the feature point
+     */
+    private void hoverFeaturePoint(LoadedActionEvent actionEvent, boolean entered) {
+        final int index = (int) actionEvent.getData();
+        
+        if (entered) { // entering a feature point
+            colorSecondaryFaceFeaturePoint(index, FEATURE_POINT_HOVER_COLOR);
+            hoveredFeaturePoint = getTypeOfFeaturePoint(index);
+        } else if (featurePointTypes.containsKey(hoveredFeaturePoint)) { // leaving highlighted FP
+            colorSecondaryFaceFeaturePoint(index, FEATURE_POINT_HIGHLIGHT_COLOR);
+        } else { // leaving ordinary FP
+            resetSecondaryFaceFeaturePointColor(index);
+        }
+    }
+
+    /**
+     * Sets the color of the secondary face's feature point at the given index
+     * and of its weighted representation.
+     * 
+     * @param index Index of the feature point
+     * @param color New color of the feature point
+     */
+    private void colorSecondaryFaceFeaturePoint(int index, Color color) {
+        getSecondaryFeaturePoints().setColor(index, color);
+        weightedFeaturePoints.setColor(index, color);
+    }
+
+    /**
+     * Resets to default the color of the secondary face's feature point at the given index
+     * and of its weighted representation.
+     * 
+     * @param index Index of the feature point
+     */
+    private void resetSecondaryFaceFeaturePointColor(final int index) {
+        getSecondaryFeaturePoints().resetColorToDefault(index);
+        weightedFeaturePoints.resetColorToDefault(index);
+    }
+
+    /**
+     * Changes the size of the secondary face's feature point at the given index.
+     * The index is received as the data payload of {@code actionEvent}.
+     * 
+     * @param actionEvent Action event with the index of the feature point as its payload data
+     */
+    private void resizeFeaturePoint(LoadedActionEvent actionEvent) {
+        final int index = (int) actionEvent.getData();
+        final double size = ControlPanelBuilder.parseLocaleDouble((JTextField) actionEvent.getSource());
+        
+        weightedFeaturePoints.setSize(index, size);
+        featurePointTypes.replace(getTypeOfFeaturePoint(index), size);
+    }
+    
+    /**
+     * Returns type of the feature point at the given index in the secondary face.
+     * 
+     * @param index Index of the feature point
+     * @return Type of the feature point or {@code null}
+     */
+    private FeaturePointType getTypeOfFeaturePoint(int index) {
+        final List<FeaturePoint> featurePoints = getSecondaryFeaturePoints().getFeaturePoints();
+        if (index < 0 || index >= featurePoints.size()) {
+            return null;
+        }
+        
+        return featurePoints.get(index)
+                .getFeaturePointType();
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/distance/DistancePanel.java b/GUI/src/main/java/cz/fidentis/analyst/distance/DistancePanel.java
new file mode 100644
index 0000000000000000000000000000000000000000..91456ffbbb89846fce0e6d227375be1e7d6ceee2
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/distance/DistancePanel.java
@@ -0,0 +1,348 @@
+package cz.fidentis.analyst.distance;
+
+import cz.fidentis.analyst.core.ControlPanel;
+import cz.fidentis.analyst.core.ControlPanelBuilder;
+import cz.fidentis.analyst.core.LoadedActionEvent;
+import cz.fidentis.analyst.core.TopControlPanel;
+import cz.fidentis.analyst.feature.FeaturePoint;
+import cz.fidentis.analyst.feature.FeaturePointType;
+import cz.fidentis.analyst.scene.DrawableFeaturePoints;
+import cz.fidentis.analyst.symmetry.SymmetryPanel;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.DoubleSummaryStatistics;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.KeyStroke;
+
+/**
+ * Control panel for Hausdorff distance.
+ * 
+ * @author Radek Oslejsek
+ * @author Daniel Schramm
+ */
+public class DistancePanel extends ControlPanel {
+    
+    /*
+     * Mandatory design elements
+     */
+    public static final String ICON = "distance28x28.png";
+    public static final String NAME = "Hausdorff distance";
+    
+    /*
+     * External actions
+     */
+    public static final String ACTION_COMMAND_SET_DISPLAYED_HEATMAP = "set displayed heatmap";
+    public static final String ACTION_COMMAND_SET_DISTANCE_STRATEGY = "set strategy";
+    public static final String ACTION_COMMAND_RELATIVE_ABSOLUTE_DIST = "switch abosulte-relative distance";
+    public static final String ACTION_COMMAND_FEATURE_POINT_HOVER_IN = "highlight hovered FP";
+    public static final String ACTION_COMMAND_FEATURE_POINT_HOVER_OUT = "set default color of hovered FP";
+    public static final String ACTION_COMMAND_FEATURE_POINT_HIGHLIGHT = "highlight feature point with color";
+    public static final String ACTION_COMMAND_FEATURE_POINT_SELECT_ALL = "select all feature points";
+    public static final String ACTION_COMMAND_FEATURE_POINT_SELECT_NONE = "deselect all feature points";
+    public static final String ACTION_COMMAND_FEATURE_POINT_RESIZE = "set size of feature point";
+    public static final String ACTION_COMMAND_DISTANCE_RECOMPUTE = "recompute the Hausdorff distance";
+    public static final String ACTION_COMMAND_SHOW_HIDE_WEIGHTED_FPOINTS = "show-hide weighted feature points";
+    
+    /*
+     * Configuration of panel-specific GUI elements
+     */
+    public static final String STRATEGY_POINT_TO_POINT = "Point to point";
+    public static final String STRATEGY_POINT_TO_TRIANGLE = "Point to triangle";
+    public static final String HEATMAP_HAUSDORFF_DISTANCE = "Hausdorff distance";
+    public static final String HEATMAP_WEIGHTED_HAUSDORFF_DISTANCE = "Weighted Hausdorff distance";
+    public static final String HEATMAP_HIDE = "None";
+    
+    private final Map<FeaturePointType, JLabel> featurePointStats;
+    private final List<JCheckBox> featurePointCheckBoxes;
+    private final JLabel avgHD, avgHDWeight, maxHD, maxHDWeight, minHD, minHDWeight;
+    
+    /**
+     * Constructor.
+     * 
+     * @param action Action listener
+     * @param featurePoints List of all feature points which can be used to calculate
+     *                      the weighted Hausdorff distance
+     * @param selectedFPs Set of feature point types which are initially selected
+     *                    to be used to calculate the weighted Hausdorff distance
+     */
+    public DistancePanel(ActionListener action, List<FeaturePoint> featurePoints, Set<FeaturePointType> selectedFPs) {
+        this.setName(NAME);
+        
+        final ControlPanelBuilder builder = new ControlPanelBuilder(this);
+        
+        builder.addCaptionLine("Computation options:");
+        builder.addLine();
+        
+        builder.addCheckBoxOptionLine(
+                null, 
+                "Relative distance", 
+                false,
+                createListener(action, ACTION_COMMAND_RELATIVE_ABSOLUTE_DIST)
+        );
+        builder.addLine();
+        
+        builder.addOptionText("Distance strategy");
+        builder.addComboBox(
+                List.of(STRATEGY_POINT_TO_POINT, STRATEGY_POINT_TO_TRIANGLE),
+                createListener(action, ACTION_COMMAND_SET_DISTANCE_STRATEGY)
+        );
+        builder.addGap();
+        builder.addLine();
+        
+        final JPanel featurePointsPanel = new JPanel();
+        final ControlPanelBuilder fpBuilder = new ControlPanelBuilder(featurePointsPanel);
+        featurePointStats = new HashMap<>(featurePoints.size());
+        featurePointCheckBoxes = new ArrayList<>(featurePoints.size());
+        for (int i = 0; i < featurePoints.size(); i++) {
+            final FeaturePoint featurePoint = featurePoints.get(i);
+            final FeaturePointType featurePointType = featurePoint.getFeaturePointType();
+            
+            final JCheckBox checkBox = fpBuilder.addCheckBox(
+                    selectedFPs.contains(featurePointType),
+                    createListener(action, ACTION_COMMAND_FEATURE_POINT_HIGHLIGHT, i)
+            );
+            checkBox.setText(featurePointType.getName());
+            final int index = i;
+            checkBox.addMouseListener(new MouseAdapter() {
+                @Override
+                public void mouseEntered(MouseEvent e) {
+                    action.actionPerformed(new LoadedActionEvent(
+                            e.getSource(),
+                            ActionEvent.ACTION_PERFORMED,
+                            ACTION_COMMAND_FEATURE_POINT_HOVER_IN,
+                            index));
+                }
+
+                @Override
+                public void mouseExited(MouseEvent e) {
+                    action.actionPerformed(new LoadedActionEvent(
+                            e.getSource(),
+                            ActionEvent.ACTION_PERFORMED,
+                            ACTION_COMMAND_FEATURE_POINT_HOVER_OUT,
+                            index));
+                }
+            });
+            featurePointCheckBoxes.add(checkBox);
+
+            final JTextField sliderInput = fpBuilder.addSliderButtonedWithVal(100, 1, null);
+            sliderInput.setText(ControlPanelBuilder.doubleToStringLocale(DrawableFeaturePoints.DEFAULT_SIZE));
+            sliderInput.postActionEvent(); // Set correct position of slider
+            sliderInput.addActionListener((ActionEvent ae) -> {
+                if (!checkBox.isSelected()) {
+                    return; // Recompute only if the feature point is selected
+                }
+                
+                if (ControlPanelBuilder.TEXT_FIELD_BUTTON_PRESSED_MINUS.equals(ae.getActionCommand())
+                        || ControlPanelBuilder.TEXT_FIELD_BUTTON_PRESSED_PLUS.equals(ae.getActionCommand())) {
+                    // Plus/minus button was pressed -> recompute
+                    action.actionPerformed(new ActionEvent(
+                            ae.getSource(),
+                            ActionEvent.ACTION_PERFORMED,
+                            ACTION_COMMAND_DISTANCE_RECOMPUTE
+                    ));
+                }
+            });
+            sliderInput.addActionListener(createListener(action, ACTION_COMMAND_FEATURE_POINT_RESIZE, i));
+            // Modify listener of the ENTER key press
+            final Object enterKeyAction = sliderInput.getInputMap()
+                    .get(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0));
+            final Action originalEnterAction = sliderInput.getActionMap()
+                    .get(enterKeyAction);
+            sliderInput.getActionMap().put(
+                    enterKeyAction,
+                    new AbstractAction() {
+                        @Override
+                        public void actionPerformed(ActionEvent e) {
+                            originalEnterAction.actionPerformed(e);
+                            if (!checkBox.isSelected()) {
+                                return; // Recompute only if the feature point is selected
+                            }
+                            
+                            action.actionPerformed(new ActionEvent(
+                                    e.getSource(),
+                                    ActionEvent.ACTION_PERFORMED,
+                                    ACTION_COMMAND_DISTANCE_RECOMPUTE
+                            ));
+                        }
+                    }
+            );
+            // Add mouse listener of the slider
+            sliderInput.addMouseListener(new MouseAdapter() {
+                private double oldValue = DrawableFeaturePoints.DEFAULT_SIZE;
+                
+                @Override
+                public void mousePressed(MouseEvent e) {
+                    oldValue = ControlPanelBuilder.parseLocaleDouble(sliderInput);
+                }
+                
+                @Override
+                public void mouseReleased(MouseEvent e) {
+                    if (!checkBox.isSelected()
+                            || oldValue == ControlPanelBuilder.parseLocaleDouble(sliderInput)) {
+                        return; // Recompute only if the feature point is selected and value changed
+                    }
+                    
+                    action.actionPerformed(new ActionEvent(
+                            e.getSource(),
+                            ActionEvent.ACTION_PERFORMED,
+                            ACTION_COMMAND_DISTANCE_RECOMPUTE)
+                    );
+                }
+            });
+            
+            fpBuilder.addGap();
+            featurePointStats.put(featurePointType, fpBuilder.addLabelLine(null));
+            fpBuilder.addGap();
+            
+            fpBuilder.addLine();
+        }
+        JScrollPane sp = builder.addScrollPane(featurePointsPanel);
+        sp.setBorder(BorderFactory.createTitledBorder("Feature points"));
+        sp.setPreferredSize(new Dimension(TopControlPanel.WIDTH, 200));
+        builder.addLine();
+        
+        builder.addButton("Select all", (ActionEvent ae) -> {
+            selectAllFeaturePoints(true);
+            action.actionPerformed(new ActionEvent(
+                    ae.getSource(),
+                    ActionEvent.ACTION_PERFORMED,
+                    ACTION_COMMAND_FEATURE_POINT_SELECT_ALL)
+            );
+        });
+        builder.addButton("Deselect all", (ActionEvent ae) -> {
+            selectAllFeaturePoints(false);
+            action.actionPerformed(new ActionEvent(
+                    ae.getSource(),
+                    ActionEvent.ACTION_PERFORMED,
+                    ACTION_COMMAND_FEATURE_POINT_SELECT_NONE)
+            );
+        });
+        builder.addLine();
+        
+        builder.addCaptionLine("Visualization options:");
+        builder.addLine();
+        builder.addCheckBoxOptionLine(
+                null,
+                "Weighted feature points",
+                true,
+                createListener(action, ACTION_COMMAND_SHOW_HIDE_WEIGHTED_FPOINTS)
+        );
+        builder.addLine();
+        
+        builder.addOptionText("Heatmap");
+        builder.addComboBox(
+                List.of(
+                        HEATMAP_HAUSDORFF_DISTANCE,
+                        HEATMAP_WEIGHTED_HAUSDORFF_DISTANCE,
+                        HEATMAP_HIDE
+                ),
+                createListener(action, ACTION_COMMAND_SET_DISPLAYED_HEATMAP)
+        );
+        builder.addGap();
+        builder.addLine();
+        
+        builder.addCaptionLine("Hausdorff distance:");
+        builder.addLine();
+        
+        builder.addOptionText("");
+        builder.addOptionText("Hausdorff dist.");
+        builder.addOptionText("Weighted H. dist.");
+        builder.addLine();
+        
+        builder.addOptionText("Average");
+        avgHD = builder.addLabelLine("");
+        builder.addGap();
+        builder.addGap();
+        avgHDWeight = builder.addLabelLine("");
+        builder.addLine();
+        builder.addOptionText("Maximum");
+        maxHD = builder.addLabelLine("");
+        builder.addGap();
+        builder.addGap();
+        maxHDWeight = builder.addLabelLine("");
+        builder.addLine();
+        builder.addOptionText("Minimum");
+        minHD = builder.addLabelLine("");
+        builder.addGap();
+        builder.addGap();
+        minHDWeight = builder.addLabelLine("");
+        builder.addLine();
+        
+        builder.addVerticalStrut();
+    }
+    
+    @Override
+    public ImageIcon getIcon() {
+        return getStaticIcon();
+    }
+    
+    /**
+     * Static implementation of the {@link #getIcon()} method.
+     * 
+     * @return Control panel icon
+     */
+    public static ImageIcon getStaticIcon() {
+        return new ImageIcon(SymmetryPanel.class.getClassLoader().getResource("/" + ICON));
+    }
+    
+    /**
+     * (De)selects all feature points for the computation of the weighted Hausdorff distance.
+     * 
+     * @param selected {@code true} if all feature point checkboxes are to be selected,
+     *                 {@code false} otherwise
+     */
+    private void selectAllFeaturePoints(boolean selected) {
+        featurePointCheckBoxes.forEach(fpCheckBox ->
+            fpCheckBox.setSelected(selected)
+        );
+    }
+    
+    /**
+     * Updates GUI elements that display statistical data about the calculated Hausdorff distance.
+     * 
+     * @param hausdorffDistance Statistical data of the ordinary Hausdorff distance
+     * @param weightedHausdorffDistance Statistical data of the weighted Hausdorff distance
+     */
+    public void updateHausdorffDistanceStats(DoubleSummaryStatistics hausdorffDistance,
+            DoubleSummaryStatistics weightedHausdorffDistance) {
+        avgHD.setText(String.format("%.4f", hausdorffDistance.getAverage()));
+        avgHDWeight.setText(String.format("%.4f", weightedHausdorffDistance.getAverage()));
+        
+        maxHD.setText(String.format("%.4f", hausdorffDistance.getMax()));
+        maxHDWeight.setText(String.format("%.4f", weightedHausdorffDistance.getMax()));
+        
+        minHD.setText(String.format("%.4f", hausdorffDistance.getMin()));
+        minHDWeight.setText(String.format("%.4f", weightedHausdorffDistance.getMin()));
+    }
+    
+    /**
+     * Updates GUI elements that display the weights of feature points
+     * used to calculate the weighted Hausdorff distance.
+     * 
+     * @param featurePointWeights Map of feature point types and their weights
+     */
+    public void updateFeaturePointWeights(Map<FeaturePointType, Double> featurePointWeights) {
+        featurePointStats.forEach((fpType, fpWeightLabel) -> {
+            final Double fpWeight = featurePointWeights.get(fpType);
+            fpWeightLabel.setText(fpWeight == null ? "" : String.format("%.3f", fpWeight));
+        });
+    }
+
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/AligmentTopComponent.form b/GUI/src/main/java/cz/fidentis/analyst/gui/AligmentTopComponent.form
deleted file mode 100644
index 26b2d319402c31ac7adb429d1757762b4598900a..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/AligmentTopComponent.form
+++ /dev/null
@@ -1,236 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<!--
-
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing,
-    software distributed under the License is distributed on an
-    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-    KIND, either express or implied.  See the License for the
-    specific language governing permissions and limitations
-    under the License.
-
--->
-
-<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
-  <Properties>
-    <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-      <Dimension value="[1200, 500]"/>
-    </Property>
-    <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-      <Dimension value="[1250, 600]"/>
-    </Property>
-  </Properties>
-  <AuxValues>
-    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
-    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
-    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
-    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
-    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
-    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
-    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
-  </AuxValues>
-
-  <Layout>
-    <DimensionLayout dim="0">
-      <Group type="103" groupAlignment="0" attributes="0">
-          <Group type="102" alignment="1" attributes="0">
-              <EmptySpace max="-2" attributes="0"/>
-              <Component id="jSplitPane1" max="-2" attributes="0"/>
-              <EmptySpace type="unrelated" max="-2" attributes="0"/>
-              <Component id="jPanel1" min="-2" max="-2" attributes="0"/>
-              <EmptySpace max="-2" attributes="0"/>
-          </Group>
-      </Group>
-    </DimensionLayout>
-    <DimensionLayout dim="1">
-      <Group type="103" groupAlignment="0" attributes="0">
-          <Group type="102" attributes="0">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <Group type="102" attributes="0">
-                      <EmptySpace max="-2" attributes="0"/>
-                      <Component id="jPanel1" pref="576" max="32767" attributes="0"/>
-                  </Group>
-                  <Component id="jSplitPane1" alignment="0" pref="589" max="32767" attributes="0"/>
-              </Group>
-              <EmptySpace max="-2" attributes="0"/>
-          </Group>
-      </Group>
-    </DimensionLayout>
-  </Layout>
-  <SubComponents>
-    <Container class="javax.swing.JPanel" name="jPanel1">
-      <Properties>
-        <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-          <Dimension value="[100, 500]"/>
-        </Property>
-        <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-          <Dimension value="[200, 600]"/>
-        </Property>
-      </Properties>
-
-      <Layout>
-        <DimensionLayout dim="0">
-          <Group type="103" groupAlignment="0" attributes="0">
-              <Group type="102" attributes="0">
-                  <Group type="103" groupAlignment="0" attributes="0">
-                      <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
-                      <Component id="jButton1" min="-2" max="-2" attributes="0"/>
-                      <Component id="primaryColorPanel" min="-2" max="-2" attributes="0"/>
-                      <Component id="jLabel2" min="-2" max="-2" attributes="0"/>
-                      <Component id="jLabel3" min="-2" max="-2" attributes="0"/>
-                      <Component id="secondaryColorPanel" min="-2" max="-2" attributes="0"/>
-                  </Group>
-                  <EmptySpace min="0" pref="88" max="32767" attributes="0"/>
-              </Group>
-          </Group>
-        </DimensionLayout>
-        <DimensionLayout dim="1">
-          <Group type="103" groupAlignment="0" attributes="0">
-              <Group type="102" alignment="0" attributes="0">
-                  <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
-                  <EmptySpace max="-2" attributes="0"/>
-                  <Component id="jButton1" min="-2" max="-2" attributes="0"/>
-                  <EmptySpace type="unrelated" max="-2" attributes="0"/>
-                  <Component id="jLabel2" min="-2" max="-2" attributes="0"/>
-                  <EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
-                  <Component id="primaryColorPanel" min="-2" max="-2" attributes="0"/>
-                  <EmptySpace max="-2" attributes="0"/>
-                  <Component id="jLabel3" min="-2" max="-2" attributes="0"/>
-                  <EmptySpace type="unrelated" max="-2" attributes="0"/>
-                  <Component id="secondaryColorPanel" min="-2" max="-2" attributes="0"/>
-                  <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
-              </Group>
-          </Group>
-        </DimensionLayout>
-      </Layout>
-      <SubComponents>
-        <Component class="javax.swing.JLabel" name="jLabel1">
-          <Properties>
-            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-              <ResourceString bundle="cz/fidentis/analyst/gui/Bundle.properties" key="AligmentTopComponent.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-            </Property>
-          </Properties>
-        </Component>
-        <Component class="javax.swing.JButton" name="jButton1">
-          <Properties>
-            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-              <ResourceString bundle="cz/fidentis/analyst/gui/Bundle.properties" key="AligmentTopComponent.jButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton1ActionPerformed"/>
-          </Events>
-        </Component>
-        <Container class="javax.swing.JPanel" name="primaryColorPanel">
-          <Properties>
-            <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-              <Dimension value="[100, 40]"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="primaryColorPanelMouseClicked"/>
-          </Events>
-
-          <Layout>
-            <DimensionLayout dim="0">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <EmptySpace min="0" pref="100" max="32767" attributes="0"/>
-              </Group>
-            </DimensionLayout>
-            <DimensionLayout dim="1">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <EmptySpace min="0" pref="40" max="32767" attributes="0"/>
-              </Group>
-            </DimensionLayout>
-          </Layout>
-        </Container>
-        <Component class="javax.swing.JLabel" name="jLabel2">
-          <Properties>
-            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-              <ResourceString bundle="cz/fidentis/analyst/gui/Bundle.properties" key="AligmentTopComponent.jLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-            </Property>
-          </Properties>
-        </Component>
-        <Component class="javax.swing.JLabel" name="jLabel3">
-          <Properties>
-            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-              <ResourceString bundle="cz/fidentis/analyst/gui/Bundle.properties" key="AligmentTopComponent.jLabel3.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-            </Property>
-          </Properties>
-        </Component>
-        <Container class="javax.swing.JPanel" name="secondaryColorPanel">
-          <Properties>
-            <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-              <Dimension value="[100, 40]"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="secondaryColorPanelMouseClicked"/>
-          </Events>
-
-          <Layout>
-            <DimensionLayout dim="0">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <EmptySpace min="0" pref="100" max="32767" attributes="0"/>
-              </Group>
-            </DimensionLayout>
-            <DimensionLayout dim="1">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <EmptySpace min="0" pref="40" max="32767" attributes="0"/>
-              </Group>
-            </DimensionLayout>
-          </Layout>
-        </Container>
-      </SubComponents>
-    </Container>
-    <Container class="javax.swing.JSplitPane" name="jSplitPane1">
-
-      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
-      <SubComponents>
-        <Component class="cz.fidentis.analyst.gui.Canvas" name="canvas1">
-          <Properties>
-            <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-              <Dimension value="[300, 0]"/>
-            </Property>
-            <Property name="name" type="java.lang.String" value="" noResource="true"/>
-            <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-              <Dimension value="[500, 0]"/>
-            </Property>
-          </Properties>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
-              <JSplitPaneConstraints position="left"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="cz.fidentis.analyst.gui.Canvas" name="canvas2">
-          <Properties>
-            <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-              <Dimension value="[300, 0]"/>
-            </Property>
-            <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-              <Dimension value="[500, 0]"/>
-            </Property>
-          </Properties>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
-              <JSplitPaneConstraints position="right"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-      </SubComponents>
-    </Container>
-  </SubComponents>
-</Form>
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/AligmentTopComponent.java b/GUI/src/main/java/cz/fidentis/analyst/gui/AligmentTopComponent.java
deleted file mode 100644
index 05d09082e3973fdfce1f242c0a0e73ce2da54478..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/AligmentTopComponent.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-package cz.fidentis.analyst.gui;
-
-import cz.fidentis.analyst.icp.Icp;
-import cz.fidentis.analyst.mesh.core.MeshFacet;
-import cz.fidentis.analyst.mesh.core.MeshModel;
-import java.awt.Color;
-import javax.swing.JColorChooser;
-import org.netbeans.api.settings.ConvertAsProperties;
-import org.openide.awt.ActionID;
-import org.openide.awt.ActionReference;
-import org.openide.windows.TopComponent;
-import org.openide.util.NbBundle.Messages;
-
-/**
- *
- * @author Richard Pajerský
- * 
- * Window for Registration
- */
-@ConvertAsProperties(
-        dtd = "-//cz.fidentis.analyst.gui//Aligment//EN",
-        autostore = false
-)
-@TopComponent.Description(
-        preferredID = "AligmentTopComponent",
-        //iconBase="SET/PATH/TO/ICON/HERE",
-        persistenceType = TopComponent.PERSISTENCE_ALWAYS
-)
-@TopComponent.Registration(mode = "editor", openAtStartup = false)
-@ActionID(category = "Window", id = "cz.fidentis.analyst.gui.AligmentTopComponent")
-@ActionReference(path = "Menu/Window" /*, position = 333 */)
-@TopComponent.OpenActionRegistration(
-        displayName = "#CTL_AligmentAction",
-        preferredID = "AligmentTopComponent"
-)
-@Messages({
-    "CTL_AligmentAction=Registration",
-    "CTL_AligmentTopComponent=Registration",
-    "HINT_AligmentTopComponent=This is a Registration window"
-})
-public final class AligmentTopComponent extends TopComponent {
-
-    private RegistrationGLEventListener regListener;
-    
-    public AligmentTopComponent() {
-        initComponents();
-        setName(Bundle.CTL_AligmentTopComponent());
-        setToolTipText(Bundle.HINT_AligmentTopComponent());
-        regListener = new RegistrationGLEventListener(canvas1, canvas2);
-        canvas1.setListener(regListener);
-        Manipulator3D manipulator = new Manipulator3D(regListener);
-        canvas1.setManipulator(manipulator);
-        primaryColorPanel.setBackground(regListener.getPrimaryColor());
-        secondaryColorPanel.setBackground(regListener.getSecondaryColor());
-    }
-
-    /**
-     * This method is called from within the constructor to initialize the form.
-     * WARNING: Do NOT modify this code. The content of this method is always
-     * regenerated by the Form Editor.
-     */
-    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
-    private void initComponents() {
-
-        jPanel1 = new javax.swing.JPanel();
-        jLabel1 = new javax.swing.JLabel();
-        jButton1 = new javax.swing.JButton();
-        primaryColorPanel = new javax.swing.JPanel();
-        jLabel2 = new javax.swing.JLabel();
-        jLabel3 = new javax.swing.JLabel();
-        secondaryColorPanel = new javax.swing.JPanel();
-        jSplitPane1 = new javax.swing.JSplitPane();
-        canvas1 = new cz.fidentis.analyst.gui.Canvas();
-        canvas2 = new cz.fidentis.analyst.gui.Canvas();
-
-        setMinimumSize(new java.awt.Dimension(1200, 500));
-        setPreferredSize(new java.awt.Dimension(1250, 600));
-
-        jPanel1.setMinimumSize(new java.awt.Dimension(100, 500));
-        jPanel1.setPreferredSize(new java.awt.Dimension(200, 600));
-
-        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(AligmentTopComponent.class, "AligmentTopComponent.jLabel1.text")); // NOI18N
-
-        org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(AligmentTopComponent.class, "AligmentTopComponent.jButton1.text")); // NOI18N
-        jButton1.addActionListener(new java.awt.event.ActionListener() {
-            public void actionPerformed(java.awt.event.ActionEvent evt) {
-                jButton1ActionPerformed(evt);
-            }
-        });
-
-        primaryColorPanel.setPreferredSize(new java.awt.Dimension(100, 40));
-        primaryColorPanel.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                primaryColorPanelMouseClicked(evt);
-            }
-        });
-
-        javax.swing.GroupLayout primaryColorPanelLayout = new javax.swing.GroupLayout(primaryColorPanel);
-        primaryColorPanel.setLayout(primaryColorPanelLayout);
-        primaryColorPanelLayout.setHorizontalGroup(
-            primaryColorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGap(0, 100, Short.MAX_VALUE)
-        );
-        primaryColorPanelLayout.setVerticalGroup(
-            primaryColorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGap(0, 40, Short.MAX_VALUE)
-        );
-
-        org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(AligmentTopComponent.class, "AligmentTopComponent.jLabel2.text")); // NOI18N
-
-        org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(AligmentTopComponent.class, "AligmentTopComponent.jLabel3.text")); // NOI18N
-
-        secondaryColorPanel.setPreferredSize(new java.awt.Dimension(100, 40));
-        secondaryColorPanel.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                secondaryColorPanelMouseClicked(evt);
-            }
-        });
-
-        javax.swing.GroupLayout secondaryColorPanelLayout = new javax.swing.GroupLayout(secondaryColorPanel);
-        secondaryColorPanel.setLayout(secondaryColorPanelLayout);
-        secondaryColorPanelLayout.setHorizontalGroup(
-            secondaryColorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGap(0, 100, Short.MAX_VALUE)
-        );
-        secondaryColorPanelLayout.setVerticalGroup(
-            secondaryColorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGap(0, 40, Short.MAX_VALUE)
-        );
-
-        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
-        jPanel1.setLayout(jPanel1Layout);
-        jPanel1Layout.setHorizontalGroup(
-            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(jPanel1Layout.createSequentialGroup()
-                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                    .addComponent(jLabel1)
-                    .addComponent(jButton1)
-                    .addComponent(primaryColorPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                    .addComponent(jLabel2)
-                    .addComponent(jLabel3)
-                    .addComponent(secondaryColorPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
-                .addGap(0, 100, Short.MAX_VALUE))
-        );
-        jPanel1Layout.setVerticalGroup(
-            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(jPanel1Layout.createSequentialGroup()
-                .addComponent(jLabel1)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                .addComponent(jButton1)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
-                .addComponent(jLabel2)
-                .addGap(5, 5, 5)
-                .addComponent(primaryColorPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                .addComponent(jLabel3)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
-                .addComponent(secondaryColorPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addGap(0, 0, Short.MAX_VALUE))
-        );
-
-        canvas1.setMinimumSize(new java.awt.Dimension(300, 0));
-        canvas1.setName(""); // NOI18N
-        canvas1.setPreferredSize(new java.awt.Dimension(500, 0));
-        jSplitPane1.setLeftComponent(canvas1);
-
-        canvas2.setMinimumSize(new java.awt.Dimension(300, 0));
-        canvas2.setPreferredSize(new java.awt.Dimension(500, 0));
-        jSplitPane1.setRightComponent(canvas2);
-
-        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
-        this.setLayout(layout);
-        layout.setHorizontalGroup(
-            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
-                .addContainerGap()
-                .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
-                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addContainerGap())
-        );
-        layout.setVerticalGroup(
-            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(layout.createSequentialGroup()
-                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                    .addGroup(layout.createSequentialGroup()
-                        .addContainerGap()
-                        .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 578, Short.MAX_VALUE))
-                    .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 589, Short.MAX_VALUE))
-                .addContainerGap())
-        );
-    }// </editor-fold>//GEN-END:initComponents
-
-    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
-        canvas1.changeModel(canvas2.getLoadedFace().getMeshModel());
-    }//GEN-LAST:event_jButton1ActionPerformed
-
-    private void primaryColorPanelMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_primaryColorPanelMouseClicked
-        Color current = primaryColorPanel.getBackground();
-        Color newColor = JColorChooser.showDialog(null, "Choose a color", current);
-        primaryColorPanel.setBackground(newColor);
-        regListener.setPrimaryColor(newColor);
-    }//GEN-LAST:event_primaryColorPanelMouseClicked
-
-    private void secondaryColorPanelMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_secondaryColorPanelMouseClicked
-        Color current = secondaryColorPanel.getBackground();
-        Color newColor = JColorChooser.showDialog(null, "Choose a color", current);
-        secondaryColorPanel.setBackground(newColor);
-        regListener.setSecondaryColor(newColor);
-    }//GEN-LAST:event_secondaryColorPanelMouseClicked
-
-    // Variables declaration - do not modify//GEN-BEGIN:variables
-    private cz.fidentis.analyst.gui.Canvas canvas1;
-    private cz.fidentis.analyst.gui.Canvas canvas2;
-    private javax.swing.JButton jButton1;
-    private javax.swing.JLabel jLabel1;
-    private javax.swing.JLabel jLabel2;
-    private javax.swing.JLabel jLabel3;
-    private javax.swing.JPanel jPanel1;
-    private javax.swing.JSplitPane jSplitPane1;
-    private javax.swing.JPanel primaryColorPanel;
-    private javax.swing.JPanel secondaryColorPanel;
-    // End of variables declaration//GEN-END:variables
-    @Override
-    public void componentOpened() {
-        // TODO add custom code on component opening
-    }
-
-    @Override
-    public void componentClosed() {
-        // TODO add custom code on component closing
-    }
-
-    void writeProperties(java.util.Properties p) {
-        // better to version settings since initial version as advocated at
-        // http://wiki.apidesign.org/wiki/PropertyFiles
-        p.setProperty("version", "1.0");
-        // TODO store your settings
-    }
-
-    void readProperties(java.util.Properties p) {
-        String version = p.getProperty("version");
-        // TODO read your settings according to their version
-    }
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/Canvas.form b/GUI/src/main/java/cz/fidentis/analyst/gui/Canvas.form
deleted file mode 100644
index d102516eb4e46619c14a2504400d662522b91d02..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/Canvas.form
+++ /dev/null
@@ -1,305 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<Form version="1.9" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
-  <Properties>
-    <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-      <Color blue="0" green="0" red="0" type="rgb"/>
-    </Property>
-  </Properties>
-  <AuxValues>
-    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
-    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
-    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
-    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
-    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
-    <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,93,0,0,1,-79"/>
-  </AuxValues>
-
-  <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
-  <SubComponents>
-    <Container class="javax.swing.JLayeredPane" name="jLayeredPane1">
-      <Properties>
-        <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-          <Color blue="28" green="28" red="28" type="rgb"/>
-        </Property>
-        <Property name="toolTipText" type="java.lang.String" value=""/>
-        <Property name="opaque" type="boolean" value="true"/>
-      </Properties>
-      <Events>
-        <EventHandler event="componentResized" listener="java.awt.event.ComponentListener" parameters="java.awt.event.ComponentEvent" handler="jLayeredPane1ComponentResized"/>
-        <EventHandler event="componentShown" listener="java.awt.event.ComponentListener" parameters="java.awt.event.ComponentEvent" handler="jLayeredPane1ComponentShown"/>
-      </Events>
-      <Constraints>
-        <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
-          <BorderConstraints direction="Center"/>
-        </Constraint>
-      </Constraints>
-
-      <Layout class="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout">
-        <Property name="useNullLayout" type="boolean" value="true"/>
-      </Layout>
-      <SubComponents>
-        <Component class="javax.swing.JLabel" name="resetButton">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/resetButton.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Reset position of model"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseMoved" listener="java.awt.event.MouseMotionListener" parameters="java.awt.event.MouseEvent" handler="resetButtonMouseMoved"/>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="resetButtonMouseClicked"/>
-            <EventHandler event="mouseExited" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="resetButtonMouseExited"/>
-          </Events>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="60" y="40" width="30" height="30"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="javax.swing.JButton" name="upNavigationButton">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/upButton.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Rotate up"/>
-            <Property name="borderPainted" type="boolean" value="false"/>
-            <Property name="contentAreaFilled" type="boolean" value="false"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="upNavigationButtonMousePressed"/>
-            <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="upNavigationButtonMouseReleased"/>
-          </Events>
-          <AuxValues>
-            <AuxValue name="JLayeredPane.layer" type="java.lang.Integer" value="200"/>
-          </AuxValues>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="60" y="10" width="30" height="30"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="javax.swing.JButton" name="leftNavigationButton">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/leftButton.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Rotate left"/>
-            <Property name="borderPainted" type="boolean" value="false"/>
-            <Property name="contentAreaFilled" type="boolean" value="false"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="leftNavigationButtonMousePressed"/>
-            <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="leftNavigationButtonMouseReleased"/>
-          </Events>
-          <AuxValues>
-            <AuxValue name="JLayeredPane.layer" type="java.lang.Integer" value="200"/>
-          </AuxValues>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="30" y="40" width="30" height="30"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="javax.swing.JButton" name="minusNavigationButton">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/minus.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Zoom out"/>
-            <Property name="borderPainted" type="boolean" value="false"/>
-            <Property name="contentAreaFilled" type="boolean" value="false"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="minusNavigationButtonMousePressed"/>
-            <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="minusNavigationButtonMouseReleased"/>
-          </Events>
-          <AuxValues>
-            <AuxValue name="JLayeredPane.layer" type="java.lang.Integer" value="200"/>
-          </AuxValues>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="90" y="90" width="30" height="30"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="javax.swing.JButton" name="downNavigationButton">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/downButton.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Rotate down"/>
-            <Property name="borderPainted" type="boolean" value="false"/>
-            <Property name="contentAreaFilled" type="boolean" value="false"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="downNavigationButtonMousePressed"/>
-            <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="downNavigationButtonMouseReleased"/>
-          </Events>
-          <AuxValues>
-            <AuxValue name="JLayeredPane.layer" type="java.lang.Integer" value="200"/>
-          </AuxValues>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="60" y="70" width="30" height="30"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="javax.swing.JButton" name="plusNavigationButton">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/plus.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Zoom in"/>
-            <Property name="borderPainted" type="boolean" value="false"/>
-            <Property name="contentAreaFilled" type="boolean" value="false"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="plusNavigationButtonMousePressed"/>
-            <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="plusNavigationButtonMouseReleased"/>
-          </Events>
-          <AuxValues>
-            <AuxValue name="JLayeredPane.layer" type="java.lang.Integer" value="200"/>
-          </AuxValues>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="30" y="90" width="30" height="30"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="javax.swing.JLabel" name="jLabel1">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/navigBackground.png"/>
-            </Property>
-          </Properties>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="30" y="10" width="90" height="90"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="javax.swing.JLabel" name="loadModelButton">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/loadCanva.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value=""/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseMoved" listener="java.awt.event.MouseMotionListener" parameters="java.awt.event.MouseEvent" handler="loadModelButtonMouseMoved"/>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="loadModelButtonMouseClicked"/>
-            <EventHandler event="mouseExited" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="loadModelButtonMouseExited"/>
-          </Events>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="200" y="100" width="210" height="220"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="javax.swing.JButton" name="rightNavigationButton1">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/rightButton.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Rotate right"/>
-            <Property name="borderPainted" type="boolean" value="false"/>
-            <Property name="contentAreaFilled" type="boolean" value="false"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="rightNavigationButton1MousePressed"/>
-            <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="rightNavigationButton1MouseReleased"/>
-          </Events>
-          <AuxValues>
-            <AuxValue name="JLayeredPane.layer" type="java.lang.Integer" value="200"/>
-          </AuxValues>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="90" y="40" width="30" height="30"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="javax.swing.JLabel" name="whiteBackroundButton">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/whiteBackroundCanvas.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="White backround"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="whiteBackroundButtonMouseClicked"/>
-          </Events>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="50" y="130" width="-1" height="-1"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="javax.swing.JLabel" name="blackBackroundButton">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/blackBackroundCanvas.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Dark background"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="blackBackroundButtonMouseClicked"/>
-          </Events>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="50" y="190" width="-1" height="-1"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Container class="javax.swing.JPanel" name="jPanel1">
-          <Properties>
-            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="0" green="0" red="0" type="rgb"/>
-            </Property>
-          </Properties>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="0" y="0" width="-1" height="-1"/>
-            </Constraint>
-          </Constraints>
-
-          <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
-        </Container>
-      </SubComponents>
-    </Container>
-  </SubComponents>
-</Form>
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/Canvas.java b/GUI/src/main/java/cz/fidentis/analyst/gui/Canvas.java
deleted file mode 100644
index 47ef0369b9ef7041b54a0b6493352a4a8f80b4f7..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/Canvas.java
+++ /dev/null
@@ -1,820 +0,0 @@
-package cz.fidentis.analyst.gui;
-
-import com.jogamp.opengl.GLCapabilities;
-import com.jogamp.opengl.GLEventListener;
-import com.jogamp.opengl.GLProfile;
-import com.jogamp.opengl.awt.GLCanvas;
-import cz.fidentis.analyst.face.HumanFace;
-import cz.fidentis.analyst.mesh.io.ModelFileFilter;
-import cz.fidentis.analyst.mesh.core.MeshModel;
-import com.jogamp.opengl.util.FPSAnimator;
-
-import java.awt.Color;
-import java.awt.Cursor;
-import java.awt.Dimension;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.Scanner;
-import java.util.Timer;
-import java.util.TimerTask;
-import javax.swing.ImageIcon;
-import javax.swing.JFileChooser;
-import javax.swing.JOptionPane;
-
-/**
- * Canvas for displaying models containing GLCanvas and navigation.
- * 
- * @author Natalia Bebjakova 
- */
-public class Canvas extends javax.swing.JPanel {
-    
-    protected GLCanvas glCanvas;
-    protected long startClickTime = 0;
-    
-    protected TimerTask task;
-    protected Timer timer;
-    
-    protected GeneralGLEventListener listener;
-     
-    /**
-     * Mouse adapter for 3D manipulation
-     */
-    protected Manipulator3D manipulator;
-
-    /**
-     * animator's target frames per second
-     */
-    private static final int FPS = 60; 
-    private final FPSAnimator animator;
-    
-    /**
-     * decides if model is displayed as wire-frame 
-     */
-    protected static boolean drawWireModel;
-
-    /**
-     * decides if the symmetryPlane is displayed
-     */
-    protected static boolean drawSymmetryPlane;
-    
-    /**
-     * original face that is loaded from file
-     */
-    protected HumanFace loadedFace;
-    
-    protected boolean loaded;   
-    
-    /**
-     * 
-     * @return true if model is loaded on canvas, false otherwise
-     */
-    public boolean isLoaded() {
-        return loaded;
-    }
-    
-    /**
-     * Creates new form Canva
-     */
-    public Canvas() {
-        initComponents();
-        
-        // gl version 2 is used
-        GLCapabilities capabilities = new GLCapabilities(GLProfile.get(GLProfile.GL2));
-        capabilities.setDoubleBuffered(true);
-       
-        // creates new glCanvas panel for displaying model
-        glCanvas = new GLCanvas(capabilities);
-        jPanel1.add(glCanvas);
-        glCanvas.setVisible(false);     
-        glCanvas.setBackground(Color.black);
-        
-        // enables glCanvas to react to events
-        glCanvas.requestFocusInWindow();        
-        glCanvas.setSize(getWidth() - getInsets().left - getInsets().right, getHeight() - getInsets().top - getInsets().bottom);
-       
-        // enables animated transition 
-        animator = new FPSAnimator(glCanvas, FPS, true);
-        animator.start();
-        listener = new GeneralGLEventListener(this);
-        
-        // enables 3D manipualtion
-        manipulator = new Manipulator3D(listener);
-        setMouseListeners();
-
-        this.validate();   
-    }
-    
-    private void removeMoseListeners() {
-        glCanvas.removeMouseListener(this.manipulator);
-        glCanvas.removeMouseMotionListener(this.manipulator);
-        glCanvas.removeMouseWheelListener(this.manipulator);
-    }
-    
-    private void setMouseListeners() {
-        glCanvas.addMouseListener(manipulator);
-        glCanvas.addMouseMotionListener(manipulator);
-        glCanvas.addMouseWheelListener(manipulator);
-    }
-    
-    /**
-     * Sets new mouse listeners for this canvas
-     * 
-     * @param manipulator new Manipulator3D, probably with different listener
-     */
-    public void setManipulator(Manipulator3D manipulator) {
-        removeMoseListeners();
-        this.manipulator = manipulator;
-        setMouseListeners();
-    }
-    
-    /**
-     * Changing the size of glCanvas
-     * 
-     * @param d New size of glCanvas
-     */
-    public void resizeCanvas(Dimension d) {
-        jPanel1.setSize(d);
-        glCanvas.setSize(d);
-        this.validate();
-        this.repaint();
-        loadModelButton.setLocation(this.getWidth() / 2 - 35, this.getHeight() / 2 - 40);
-    }
-    
-    /**
-     * 
-     * @return Original face that is loaded from file
-     */
-    public HumanFace getLoadedFace() {
-        return loadedFace;
-    }
-    
-    /**
-     * Sets GLListener of the canvas 
-     * 
-     * @param listener GLListener for manipulation with model 
-     */
-    public void setListener(GeneralGLEventListener listener) {
-        this.listener = listener;
-    }
-    
-    /**
-     * 
-     * @param drawWire Decides if model is displayed as wife-frame
-     */
-    public static void setDrawWired(boolean drawWire) {
-        drawWireModel = drawWire;
-    }
-
-    /**
-     * 
-     * @return Returns if model is displayed as wife-frame
-     */
-    public boolean getDrawWired(){
-        return drawWireModel;
-    }
-
-    /**
-     *
-     * @param drawSymmetry Decides if the symmetry plane is displayed
-     */
-    public static void setDrawSymmetryPlane(boolean drawSymmetry) {
-        drawSymmetryPlane = drawSymmetry;
-    }
-
-    /**
-     *
-     * @return Returns if the symmetry plane is displayed
-     */
-    public boolean getDrawSymmetryPlane(){
-        return drawSymmetryPlane;
-    }
-
-    /**
-     *
-     * @param v Decides if button for loading model is visible
-     */
-    public void setImportLabelVisible(Boolean v) {
-        loadModelButton.setVisible(v);
-    }
-    
-    /**
-     * Loads model selected in file chooser by user
-     */
-    public void loadModel () {
-        String[] extensions = new String[2];
-        extensions[0] = "obj";
-        extensions[1] = "OBJ";
-        
-        //enables to shows just .obj files in file chooser
-        ModelFileFilter filter = new ModelFileFilter(extensions, "*.obj");
-        JFileChooser jFileChooser1 = new JFileChooser(getPrefferedModelPath());
-        jFileChooser1.setPreferredSize(new Dimension (800,500));
-       
-        jFileChooser1.addChoosableFileFilter(filter);        
-       
-        //file chooser will appear on top of glCanvas
-        jFileChooser1.showOpenDialog(this);
-        jFileChooser1.setDialogTitle("Import obj file");
-        
-        setPrefferedModelPath(jFileChooser1.getCurrentDirectory().toString());
-        
-        File[] fileArray = new File[1];
-        //saves selected file by user as first element in array
-        fileArray[0] = jFileChooser1.getSelectedFile();
-
-        //testing getting path TODO
-        //JOptionPane.showConfirmDialog(null,
-        //        fileArray[0].getAbsoluteFile(), "", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
-
-        if (fileArray.length <= 0) {
-            System.out.print("No file chosen.");
-        } else {
-            this.addModel(fileArray[0]);
-        }       
-        glCanvas.setVisible(true);
-    }
-    
-    private void setPrefferedModelPath(String s) {
-        //TODO remove duplicate with PreferenceTopComponent
-        try {
-            FileWriter rewriter = new FileWriter("preferences.fip", false);
-            rewriter.write(s);
-            rewriter.close();
-        } catch (IOException ex) {
-            ex.printStackTrace();
-        }   
-    }
-    
-    private String getPrefferedModelPath() {
-        //TODO remove duplicate with PreferenceTopComponent
-        String data = "";
-        try {
-            File myObj = new File(/*propPath + */"preferences.fip");
-            if (myObj.length() == 0)
-                return data;
-            try (Scanner myReader = new Scanner(myObj)) {
-                data = myReader.nextLine();
-            }            
-        } catch (FileNotFoundException e) {
-            System.out.println("An error occurred.");
-            e.printStackTrace();
-        }
-        return data;
-    }
-
-    /**
-     * Loads the model in .obj format from file and adds this model to listener for displaying.
-     * If file does not contain 3D model or model is not correct, shows dialog with message
-     *
-     * @param file File from which model will be read
-     */
-    private void addModel (final File file) {
-        try {
-            loadedFace = new HumanFace(new File (file.getPath()));
-
-            if (loadedFace.getMeshModel() != null) {
-                // listener enables to manipulate and interact with model
-                listener.setCameraPosition(0, 0, 300);
-                glCanvas.addGLEventListener((GLEventListener) listener);
-                listener.setModel(loadedFace.getMeshModel());
-                listener.rotationAndSizeRestart();
-                loadModelButton.setVisible(false);
-                loaded = true;
-            }           
-        } catch (Exception e) {
-            System.out.println(e.getMessage());
-            JOptionPane.showMessageDialog(this, "File doesn't contain any model", "Model is not loaded.",
-                    0, new ImageIcon(getClass().getResource("/notLoadedModel.png")));
-            System.out.println ("File doesn't contain any model");
-            loaded = false;               
-        }
-    }
-    
-    /**
-     * reset position of the displayed model
-     */
-    public void resetPosition(){
-        listener.rotationAndSizeRestart();
-    }
-    
-    /**
-     * Changes the model to be displayed
-     * 
-     * @param model New model that will be displayed on canvas
-     */
-    public void changeModel(MeshModel model) {
-        MeshModel newModel = new MeshModel(model);
-        listener.setModel(newModel);
-    }
-    
-    /**
-     * Returns the model which is displayed on canvas
-     * 
-     * @return Model that is displayed on canvas
-     */
-    public MeshModel getModel() {
-        return listener.getModel();
-    }
-   
-    
-    /**
-     * This method is called from within the constructor to initialize the form.
-     * WARNING: Do NOT modify this code. The content of this method is always
-     * regenerated by the Form Editor.
-     * 
-     * Generated code from NetBeans
-     */
-    @SuppressWarnings("unchecked")
-    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
-    private void initComponents() {
-
-        jLayeredPane1 = new javax.swing.JLayeredPane();
-        resetButton = new javax.swing.JLabel();
-        upNavigationButton = new javax.swing.JButton();
-        leftNavigationButton = new javax.swing.JButton();
-        minusNavigationButton = new javax.swing.JButton();
-        downNavigationButton = new javax.swing.JButton();
-        plusNavigationButton = new javax.swing.JButton();
-        jLabel1 = new javax.swing.JLabel();
-        loadModelButton = new javax.swing.JLabel();
-        rightNavigationButton1 = new javax.swing.JButton();
-        whiteBackroundButton = new javax.swing.JLabel();
-        blackBackroundButton = new javax.swing.JLabel();
-        jPanel1 = new javax.swing.JPanel();
-
-        setBackground(new java.awt.Color(0, 0, 0));
-        setLayout(new java.awt.BorderLayout());
-
-        jLayeredPane1.setBackground(new java.awt.Color(40, 40, 40));
-        jLayeredPane1.setToolTipText("");
-        jLayeredPane1.setOpaque(true);
-        jLayeredPane1.addComponentListener(new java.awt.event.ComponentAdapter() {
-            public void componentResized(java.awt.event.ComponentEvent evt) {
-                jLayeredPane1ComponentResized(evt);
-            }
-            public void componentShown(java.awt.event.ComponentEvent evt) {
-                jLayeredPane1ComponentShown(evt);
-            }
-        });
-
-        resetButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resetButton.png"))); // NOI18N
-        resetButton.setToolTipText("Reset position of model");
-        resetButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        resetButton.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
-            public void mouseMoved(java.awt.event.MouseEvent evt) {
-                resetButtonMouseMoved(evt);
-            }
-        });
-        resetButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                resetButtonMouseClicked(evt);
-            }
-            public void mouseExited(java.awt.event.MouseEvent evt) {
-                resetButtonMouseExited(evt);
-            }
-        });
-        jLayeredPane1.add(resetButton);
-        resetButton.setBounds(60, 40, 30, 30);
-
-        upNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/upButton.png"))); // NOI18N
-        upNavigationButton.setToolTipText("Rotate up");
-        upNavigationButton.setBorderPainted(false);
-        upNavigationButton.setContentAreaFilled(false);
-        upNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        upNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mousePressed(java.awt.event.MouseEvent evt) {
-                upNavigationButtonMousePressed(evt);
-            }
-            public void mouseReleased(java.awt.event.MouseEvent evt) {
-                upNavigationButtonMouseReleased(evt);
-            }
-        });
-        jLayeredPane1.setLayer(upNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
-        jLayeredPane1.add(upNavigationButton);
-        upNavigationButton.setBounds(60, 10, 30, 30);
-
-        leftNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/leftButton.png"))); // NOI18N
-        leftNavigationButton.setToolTipText("Rotate left");
-        leftNavigationButton.setBorderPainted(false);
-        leftNavigationButton.setContentAreaFilled(false);
-        leftNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        leftNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mousePressed(java.awt.event.MouseEvent evt) {
-                leftNavigationButtonMousePressed(evt);
-            }
-            public void mouseReleased(java.awt.event.MouseEvent evt) {
-                leftNavigationButtonMouseReleased(evt);
-            }
-        });
-        jLayeredPane1.setLayer(leftNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
-        jLayeredPane1.add(leftNavigationButton);
-        leftNavigationButton.setBounds(30, 40, 30, 30);
-
-        minusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/minus.png"))); // NOI18N
-        minusNavigationButton.setToolTipText("Zoom out");
-        minusNavigationButton.setBorderPainted(false);
-        minusNavigationButton.setContentAreaFilled(false);
-        minusNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        minusNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mousePressed(java.awt.event.MouseEvent evt) {
-                minusNavigationButtonMousePressed(evt);
-            }
-            public void mouseReleased(java.awt.event.MouseEvent evt) {
-                minusNavigationButtonMouseReleased(evt);
-            }
-        });
-        jLayeredPane1.setLayer(minusNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
-        jLayeredPane1.add(minusNavigationButton);
-        minusNavigationButton.setBounds(90, 90, 30, 30);
-
-        downNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/downButton.png"))); // NOI18N
-        downNavigationButton.setToolTipText("Rotate down");
-        downNavigationButton.setBorderPainted(false);
-        downNavigationButton.setContentAreaFilled(false);
-        downNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        downNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mousePressed(java.awt.event.MouseEvent evt) {
-                downNavigationButtonMousePressed(evt);
-            }
-            public void mouseReleased(java.awt.event.MouseEvent evt) {
-                downNavigationButtonMouseReleased(evt);
-            }
-        });
-        jLayeredPane1.setLayer(downNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
-        jLayeredPane1.add(downNavigationButton);
-        downNavigationButton.setBounds(60, 70, 30, 30);
-
-        plusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/plus.png"))); // NOI18N
-        plusNavigationButton.setToolTipText("Zoom in");
-        plusNavigationButton.setBorderPainted(false);
-        plusNavigationButton.setContentAreaFilled(false);
-        plusNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        plusNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mousePressed(java.awt.event.MouseEvent evt) {
-                plusNavigationButtonMousePressed(evt);
-            }
-            public void mouseReleased(java.awt.event.MouseEvent evt) {
-                plusNavigationButtonMouseReleased(evt);
-            }
-        });
-        jLayeredPane1.setLayer(plusNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
-        jLayeredPane1.add(plusNavigationButton);
-        plusNavigationButton.setBounds(30, 90, 30, 30);
-
-        jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/navigBackground.png"))); // NOI18N
-        jLayeredPane1.add(jLabel1);
-        jLabel1.setBounds(30, 10, 90, 90);
-
-        loadModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/loadCanva.png"))); // NOI18N
-        loadModelButton.setToolTipText("");
-        loadModelButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        loadModelButton.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
-            public void mouseMoved(java.awt.event.MouseEvent evt) {
-                loadModelButtonMouseMoved(evt);
-            }
-        });
-        loadModelButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                loadModelButtonMouseClicked(evt);
-            }
-            public void mouseExited(java.awt.event.MouseEvent evt) {
-                loadModelButtonMouseExited(evt);
-            }
-        });
-        jLayeredPane1.add(loadModelButton);
-        loadModelButton.setBounds(200, 100, 210, 220);
-
-        rightNavigationButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/rightButton.png"))); // NOI18N
-        rightNavigationButton1.setToolTipText("Rotate right");
-        rightNavigationButton1.setBorderPainted(false);
-        rightNavigationButton1.setContentAreaFilled(false);
-        rightNavigationButton1.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        rightNavigationButton1.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mousePressed(java.awt.event.MouseEvent evt) {
-                rightNavigationButton1MousePressed(evt);
-            }
-            public void mouseReleased(java.awt.event.MouseEvent evt) {
-                rightNavigationButton1MouseReleased(evt);
-            }
-        });
-        jLayeredPane1.setLayer(rightNavigationButton1, javax.swing.JLayeredPane.MODAL_LAYER);
-        jLayeredPane1.add(rightNavigationButton1);
-        rightNavigationButton1.setBounds(90, 40, 30, 30);
-
-        whiteBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/whiteBackroundCanvas.png"))); // NOI18N
-        whiteBackroundButton.setToolTipText("White backround");
-        whiteBackroundButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        whiteBackroundButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                whiteBackroundButtonMouseClicked(evt);
-            }
-        });
-        jLayeredPane1.add(whiteBackroundButton);
-        whiteBackroundButton.setBounds(50, 130, 56, 56);
-
-        blackBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/blackBackroundCanvas.png"))); // NOI18N
-        blackBackroundButton.setToolTipText("Dark background");
-        blackBackroundButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        blackBackroundButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                blackBackroundButtonMouseClicked(evt);
-            }
-        });
-        jLayeredPane1.add(blackBackroundButton);
-        blackBackroundButton.setBounds(50, 190, 56, 56);
-
-        jPanel1.setBackground(new java.awt.Color(0, 0, 0));
-        jPanel1.setLayout(new java.awt.BorderLayout());
-        jLayeredPane1.add(jPanel1);
-        jPanel1.setBounds(0, 0, 0, 0);
-
-        add(jLayeredPane1, java.awt.BorderLayout.CENTER);
-    }// </editor-fold>//GEN-END:initComponents
-
-    /**
-     * 
-     * @param evt Resizing glCanvas cantaining components
-     */
-    private void jLayeredPane1ComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_jLayeredPane1ComponentResized
-        jPanel1.setBounds(0, 0, jLayeredPane1.getWidth(), jLayeredPane1.getHeight());
-        glCanvas.setBounds(jLayeredPane1.getX(), jLayeredPane1.getY(), jLayeredPane1.getWidth(), jLayeredPane1.getHeight());
-        loadModelButton.setLocation(this.getWidth() / 2 - 35, this.getHeight() / 2 - 40);
-    }//GEN-LAST:event_jLayeredPane1ComponentResized
-
-    /**
-     * 
-     * @param evt Showing glCanvas cantaining components
-     */
-    private void jLayeredPane1ComponentShown(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_jLayeredPane1ComponentShown
-        jPanel1.setBounds(0, 0, jLayeredPane1.getWidth(), jLayeredPane1.getHeight());
-        glCanvas.setBounds(jLayeredPane1.getX(), jLayeredPane1.getY(), jLayeredPane1.getWidth(), jLayeredPane1.getHeight());
-        loadModelButton.setLocation(this.getWidth() / 2 - 35, this.getHeight() / 2 - 40);
-    }//GEN-LAST:event_jLayeredPane1ComponentShown
-
-    /**
-     * 
-     * @param evt Enables to rotate left the model when left navigation button is pressed
-     */
-    private void leftNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftNavigationButtonMousePressed
-        timer = new Timer();
-        startClickTime = System.currentTimeMillis();
-        task = new TimerTask() {
-            @Override
-            public void run() {
-                listener.rotateLeft(2);
-            }
-        };
-        timer.schedule(task, 500, 100);
-        leftNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/leftButtonPressed.png")));
-    }//GEN-LAST:event_leftNavigationButtonMousePressed
-
-    /**
-     * 
-     * @param evt Enables to rotate up the model when up navigation button is pressed
-     */
-    private void upNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_upNavigationButtonMousePressed
-        timer = new Timer();
-        startClickTime = System.currentTimeMillis();
-        task = new TimerTask() {
-            @Override
-            public void run() {
-                listener.rotateUp(2);
-            }
-        };
-        timer.schedule(task, 500, 100);
-        upNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/upButtonPressed.png")));
-    }//GEN-LAST:event_upNavigationButtonMousePressed
-
-    /**
-     * 
-     * @param evt Enables to rotate down the model when down navigation button is pressed
-     */
-    private void downNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_downNavigationButtonMousePressed
-        timer = new Timer();
-        startClickTime = System.currentTimeMillis();
-        task = new TimerTask() {
-            @Override
-            public void run() {
-                listener.rotateDown(2);
-            }
-        };
-        timer.schedule(task, 500, 100);
-        downNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/downButtonPressed.png")));
-    }//GEN-LAST:event_downNavigationButtonMousePressed
-
-    /**
-     * 
-     * @param evt Enables to zoom in the model when plus navigation button is pressed
-     */
-    private void plusNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_plusNavigationButtonMousePressed
-        timer = new Timer();
-        startClickTime = System.currentTimeMillis();
-        task = new TimerTask() {
-            @Override
-            public void run() {
-                listener.zoomIn(3);
-            }
-        };
-        timer.schedule(task, 500, 100);
-        plusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/plusPressed.png")));
-    }//GEN-LAST:event_plusNavigationButtonMousePressed
- 
-  /**
-  * 
-  * @param evt Enables to zoom out the model when minus navigation button is pressed
-  */
-    private void minusNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_minusNavigationButtonMousePressed
-        timer = new Timer();
-        startClickTime = System.currentTimeMillis();
-        task = new TimerTask() {
-            @Override
-            public void run() {
-                listener.zoomOut(3);
-            }
-        };
-        timer.schedule(task, 500, 100);
-        minusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/minusPressed.png")));
-    }//GEN-LAST:event_minusNavigationButtonMousePressed
-
-    /**
-     * 
-     * @param evt Stops rotating left
-     */
-    private void leftNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftNavigationButtonMouseReleased
-        timer.cancel();
-        if ((System.currentTimeMillis() - startClickTime) < 500) {
-            listener.rotateLeft(22.5);
-        }
-        startClickTime = 0;
-        leftNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/leftButton.png")));
-    }//GEN-LAST:event_leftNavigationButtonMouseReleased
-
-    /**
-     * 
-     * @param evt Stops rotating up
-     */
-    private void upNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_upNavigationButtonMouseReleased
-        timer.cancel();
-        if ((System.currentTimeMillis() - startClickTime) < 500) {
-            listener.rotateUp(22.5);
-        }
-        startClickTime = 0;
-        upNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/upButton.png")));
-    }//GEN-LAST:event_upNavigationButtonMouseReleased
-
-    /**
-     * 
-     * @param evt Stops rotating down
-     */
-    private void downNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_downNavigationButtonMouseReleased
-        timer.cancel();
-        if ((System.currentTimeMillis() - startClickTime) < 500) {
-            listener.rotateDown(22.5);
-        }
-        startClickTime = 0;
-        downNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/downButton.png")));
-    }//GEN-LAST:event_downNavigationButtonMouseReleased
-
-    /**
-     * 
-     * @param evt Stops zooming in 
-     */
-    private void plusNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_plusNavigationButtonMouseReleased
-        timer.cancel();
-        if ((System.currentTimeMillis() - startClickTime) < 500) {
-            listener.zoomIn(30);
-        }
-        startClickTime = 0;
-        plusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/plus.png")));
-    }//GEN-LAST:event_plusNavigationButtonMouseReleased
-
-    /**
-     * 
-     * @param evt  Stops zooming out
-     */
-    private void minusNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_minusNavigationButtonMouseReleased
-        timer.cancel();
-        if ((System.currentTimeMillis() - startClickTime) < 500) {
-            listener.zoomOut(30);
-        }
-        startClickTime = 0;
-        minusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/minus.png")));
-    }//GEN-LAST:event_minusNavigationButtonMouseReleased
-
-    /**
-     * 
-     * @param evt Laoding the .obj file when button pressed
-     */
-    private void loadModelButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_loadModelButtonMouseClicked
-       loadModel();
-    }//GEN-LAST:event_loadModelButtonMouseClicked
-
-    /**
-     * 
-     * @param evt Design is reacting to mouse movement 
-     */
-    private void loadModelButtonMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_loadModelButtonMouseMoved
-        loadModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/loadCanvaClicked.png")));
-    }//GEN-LAST:event_loadModelButtonMouseMoved
-
-    /**
-     * 
-     * @param evt Design is reacting to mouse movement  
-     */
-    private void loadModelButtonMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_loadModelButtonMouseExited
-        loadModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/loadCanva.png")));
-    }//GEN-LAST:event_loadModelButtonMouseExited
-
-    /**
-     * 
-     * @param evt Enables to rotate down the model when down navigation button is pressed
-     */
-    private void rightNavigationButton1MousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightNavigationButton1MousePressed
-        timer = new Timer();
-        startClickTime = System.currentTimeMillis();
-        task = new TimerTask() {
-            @Override
-            public void run() {
-                listener.rotateRight(2);
-            }
-        };
-        timer.schedule(task, 500, 100);
-        rightNavigationButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/rightButtonPressed.png")));
-    }//GEN-LAST:event_rightNavigationButton1MousePressed
-
-    /**
-     * 
-     * @param evt Stops rotating right
-     */
-    private void rightNavigationButton1MouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightNavigationButton1MouseReleased
-        timer.cancel();
-        if ((System.currentTimeMillis() - startClickTime) < 500) {
-            listener.rotateRight(22.5);
-        }
-        startClickTime = 0;
-        rightNavigationButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/rightButton.png")));
-    }//GEN-LAST:event_rightNavigationButton1MouseReleased
-
-    /**
-     * 
-     * @param evt Position of model on glCanvas is set to starting position
-     */
-    private void resetButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_resetButtonMouseClicked
-        listener.rotationAndSizeRestart();
-    }//GEN-LAST:event_resetButtonMouseClicked
-
-    /**
-     * 
-     * @param evt Design is reacting to mouse movement  
-     */
-    private void resetButtonMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_resetButtonMouseMoved
-        resetButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resetButtonPressed.png")));
-        resetButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
-    }//GEN-LAST:event_resetButtonMouseMoved
-
-    /**
-     * 
-     * @param evt Design is reacting to mouse movement  
-     */
-    private void resetButtonMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_resetButtonMouseExited
-        resetButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resetButton.png")));
-    }//GEN-LAST:event_resetButtonMouseExited
-
-    /**
-     * 
-     * @param evt Changes backround of the canvas into white color
-     */
-    private void whiteBackroundButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_whiteBackroundButtonMouseClicked
-        listener.setWhiteBackround(true);
-        whiteBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/whiteBackroundCanvasPressed.png")));
-        blackBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/blackBackroundCanvas.png")));
-    }//GEN-LAST:event_whiteBackroundButtonMouseClicked
-
-    /**
-     * 
-     * @param evt Changes backround of the canvas into dark color
-     */
-    private void blackBackroundButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_blackBackroundButtonMouseClicked
-        listener.setWhiteBackround(false);
-        whiteBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/whiteBackroundCanvas.png")));
-        blackBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/blackBackroundCanvasPressed.png")));
-    }//GEN-LAST:event_blackBackroundButtonMouseClicked
-
-    // Variables declaration - do not modify//GEN-BEGIN:variables
-    private javax.swing.JLabel blackBackroundButton;
-    private javax.swing.JButton downNavigationButton;
-    private javax.swing.JLabel jLabel1;
-    private javax.swing.JLayeredPane jLayeredPane1;
-    private javax.swing.JPanel jPanel1;
-    private javax.swing.JButton leftNavigationButton;
-    private javax.swing.JLabel loadModelButton;
-    private javax.swing.JButton minusNavigationButton;
-    private javax.swing.JButton plusNavigationButton;
-    private javax.swing.JLabel resetButton;
-    private javax.swing.JButton rightNavigationButton1;
-    private javax.swing.JButton upNavigationButton;
-    private javax.swing.JLabel whiteBackroundButton;
-    // End of variables declaration//GEN-END:variables
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/CanvasTopComponent.java b/GUI/src/main/java/cz/fidentis/analyst/gui/CanvasTopComponent.java
deleted file mode 100644
index 5f08cc63a4299f64e06982d0072941e4657a3efa..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/CanvasTopComponent.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-package cz.fidentis.analyst.gui;
-
-import org.netbeans.api.settings.ConvertAsProperties;
-import org.openide.awt.ActionID;
-import org.openide.awt.ActionReference;
-import org.openide.windows.TopComponent;
-import org.openide.util.NbBundle.Messages;
-
-/**
- *
- * @author Richard Pajerský
- * 
- * Window for Canvas
- */
-@ConvertAsProperties(
-        dtd = "-//cz.fidentis.analyst.gui//Canvas//EN",
-        autostore = false
-)
-@TopComponent.Description(
-        preferredID = "CanvasTopComponent",
-        //iconBase="SET/PATH/TO/ICON/HERE",
-        persistenceType = TopComponent.PERSISTENCE_ALWAYS
-)
-@TopComponent.Registration(mode = "editor", openAtStartup = false)
-@ActionID(category = "Window", id = "cz.fidentis.analyst.gui.CanvasTopComponent")
-@ActionReference(path = "Menu/Window" /*, position = 333 */)
-@TopComponent.OpenActionRegistration(
-        displayName = "#CTL_CanvasAction",
-        preferredID = "CanvasTopComponent"
-)
-@Messages({
-    "CTL_CanvasAction=Canvas",
-    "CTL_CanvasTopComponent=Canvas",
-    "HINT_CanvasTopComponent=This is a Canvas window"
-})
-public final class CanvasTopComponent extends TopComponent {
-
-    public CanvasTopComponent() {
-        initComponents();
-        setName(Bundle.CTL_CanvasTopComponent());
-        setToolTipText(Bundle.HINT_CanvasTopComponent());
-        //putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
-        //putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, Boolean.TRUE);
-        //putClientProperty(TopComponent.PROP_UNDOCKING_DISABLED, Boolean.TRUE);
-    }
-
-    /**
-     * This method is called from within the constructor to initialize the form.
-     * WARNING: Do NOT modify this code. The content of this method is always
-     * regenerated by the Form Editor.
-     */
-    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
-    private void initComponents() {
-
-        canvas1 = new cz.fidentis.analyst.gui.Canvas();
-
-        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
-        this.setLayout(layout);
-        layout.setHorizontalGroup(
-            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGap(0, 575, Short.MAX_VALUE)
-            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                .addGroup(layout.createSequentialGroup()
-                    .addGap(0, 0, 0)
-                    .addComponent(canvas1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                    .addGap(0, 0, 0)))
-        );
-        layout.setVerticalGroup(
-            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGap(0, 411, Short.MAX_VALUE)
-            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                .addGroup(layout.createSequentialGroup()
-                    .addGap(0, 0, 0)
-                    .addComponent(canvas1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                    .addGap(0, 0, 0)))
-        );
-    }// </editor-fold>//GEN-END:initComponents
-
-    // Variables declaration - do not modify//GEN-BEGIN:variables
-    private cz.fidentis.analyst.gui.Canvas canvas1;
-    // End of variables declaration//GEN-END:variables
-    @Override
-    public void componentOpened() {
-        // TODO add custom code on component opening
-    }
-
-    @Override
-    public void componentClosed() {
-        // TODO add custom code on component closing
-    }
-
-    void writeProperties(java.util.Properties p) {
-        // better to version settings since initial version as advocated at
-        // http://wiki.apidesign.org/wiki/PropertyFiles
-        p.setProperty("version", "1.0");
-        // TODO store your settings
-    }
-
-    void readProperties(java.util.Properties p) {
-        String version = p.getProperty("version");
-        // TODO read your settings according to their version
-    }
-    
-    public cz.fidentis.analyst.gui.Canvas getCanvas() {
-        return canvas1;
-    }
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/ComparisonGLEventListener.java b/GUI/src/main/java/cz/fidentis/analyst/gui/ComparisonGLEventListener.java
deleted file mode 100644
index c1b8dbd858c2e55a25544fad029dc4d07f9a893e..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/ComparisonGLEventListener.java
+++ /dev/null
@@ -1,176 +0,0 @@
-package cz.fidentis.analyst.gui;
-
-import com.jogamp.opengl.GL;
-import com.jogamp.opengl.GL2;
-import com.jogamp.opengl.GLAutoDrawable;
-import cz.fidentis.analyst.face.HumanFace;
-import cz.fidentis.analyst.mesh.core.MeshFacet;
-import cz.fidentis.analyst.mesh.core.MeshModel;
-import cz.fidentis.analyst.visitors.mesh.HausdorffDistance;
-
-import javax.vecmath.Vector3d;
-import java.awt.*;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static com.jogamp.opengl.GL.GL_FRONT_AND_BACK;
-import static com.jogamp.opengl.GL.GL_VIEWPORT;
-import static com.jogamp.opengl.GL2GL3.GL_FILL;
-import static com.jogamp.opengl.GL2GL3.GL_LINE;
-import static com.jogamp.opengl.fixedfunc.GLMatrixFunc.GL_MODELVIEW_MATRIX;
-import static com.jogamp.opengl.fixedfunc.GLMatrixFunc.GL_PROJECTION_MATRIX;
-import javax.vecmath.Point3d;
-
-/**
- *
- *  @author Daniel Sokol
- *
- *  Rendering face with heatmap.
- */
-public class ComparisonGLEventListener extends GeneralGLEventListener {
-    boolean renderHeatmap;
-    Color minColor;
-    Color maxColor;
-    private Map<MeshFacet, List<Double>> distances = new HashMap<>();
-    private HumanFace comparedFace;
-
-
-    public ComparisonGLEventListener(Canvas canvas) {
-        super(canvas);
-    }
-
-    public void setComparedFace(HumanFace inputComparedFace) {
-        if (inputComparedFace != null) {
-            comparedFace = inputComparedFace;
-        }
-        renderHeatmap = false;
-    }
-
-    public void compare(Color minColor, Color maxColor) {
-        HausdorffDistance hVisitor = new HausdorffDistance(getModel(), HausdorffDistance.Strategy.POINT_TO_POINT, false, false);
-        comparedFace.getMeshModel().compute(hVisitor);
-        distances = hVisitor.getDistances();
-        renderHeatmap = true;
-        this.minColor = minColor;
-        this.maxColor = maxColor;
-    }
-
-    @Override
-    public void display(GLAutoDrawable glad) {
-        wireModel = glCanvas.getDrawWired(); // is wire-frame or not
-
-        if (whiteBackround) {
-            gl.glClearColor(0.9f, 0.9f, 0.9f, 0);
-        } else {
-            gl.glClearColor(0.25f, 0.25f, 0.25f, 0);
-        }
-        // background for GLCanvas
-        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
-        gl.glLoadIdentity();
-
-        // sets model to proper position
-        glu.gluLookAt(xCameraPosition, yCameraPosition, zCameraPosition, xCenter, yCenter, zCenter, xUpPosition, yUpPosition, zUpPosition);
-
-        gl.glShadeModel(GL2.GL_SMOOTH);
-        gl.glGetIntegerv(GL_VIEWPORT, viewport, 0);
-        gl.glGetFloatv(GL_MODELVIEW_MATRIX, modelViewMatrix, 0);
-        gl.glGetFloatv(GL_PROJECTION_MATRIX, projectionMatrix, 0);
-
-        //if there is any model, draw
-        if (comparedFace != null) {
-            if (renderHeatmap) {
-                drawHeatmap(comparedFace.getMeshModel());
-            } else {
-                drawWithoutTextures(comparedFace.getMeshModel());
-            }
-        } else if (getModel() != null) {
-            if (wireModel) {
-                gl.glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //drawn as wire-frame
-            } else {
-                gl.glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // drawn as full traingles
-            }
-
-            drawWithoutTextures(getModel());
-        }
-
-        gl.glFlush();
-    }
-
-    public void drawHeatmap(MeshModel model) {
-        for (int i = 0; i < model.getFacets().size(); i++) {
-            List<Double> distanceList = distances.get(model.getFacets().get(i));
-            Double minDistance = distanceList.stream().mapToDouble(Double::doubleValue).min().getAsDouble();
-            Double maxDistance = distanceList.stream().mapToDouble(Double::doubleValue).max().getAsDouble();
-            renderFaceWithHeatmap(model.getFacets().get(i), distances.get(model.getFacets().get(i)), minDistance, maxDistance);
-        }
-    }
-
-    public void renderFaceWithHeatmap(MeshFacet facet, List<Double> distancesList, Double minDistance, Double maxDistance) {
-        gl.glBegin(GL2.GL_TRIANGLES); //vertices are rendered as triangles
-
-        // get the normal and tex coords indicies for face i
-        for (int v = 0; v < facet.getCornerTable().getSize(); v++) {
-            // render the normals
-            Vector3d norm = facet.getVertices().get(facet.getCornerTable().getRow(v).getVertexIndex()).getNormal();
-            if (norm != null) {
-                gl.glNormal3d(norm.x, norm.y, norm.z);
-            }
-            // render the vertices
-            Point3d vert = facet.getVertices().get(facet.getCornerTable().getRow(v).getVertexIndex()).getPosition();
-            //get color of vertex
-            Color c = getColor(distancesList.get(facet.getCornerTable().getRow(v).getVertexIndex()), minDistance, maxDistance);
-            gl.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_DIFFUSE, c.getComponents(null), 0);
-
-            gl.glVertex3d(vert.x, vert.y, vert.z);
-        }
-        gl.glEnd();
-        gl.glPopAttrib();
-    }
-
-    Color getColor(Double currentDistance, Double minDistance, Double maxDistance) {
-        double currentParameter = ((currentDistance - minDistance) / (maxDistance - minDistance));
-
-        float[] hsb1 = Color.RGBtoHSB(minColor.getRed(), minColor.getGreen(), minColor.getBlue(), null);
-        float h1 = hsb1[0];
-        float s1 = hsb1[1];
-        float b1 = hsb1[2];
-
-        float[] hsb2 = Color.RGBtoHSB(maxColor.getRed(), maxColor.getGreen(), maxColor.getBlue(), null);
-        float h2 = hsb2[0];
-        float s2 = hsb2[1];
-        float b2 = hsb2[2];
-
-        // determine clockwise and counter-clockwise distance between hues
-        float distCCW;
-        float distCW;
-
-        if (h1 >= h2) {
-            distCCW = h1 - h2;
-            distCW = 1 + h2 - h1;
-        } else {
-            distCCW = 1 + h1 - h2;
-            distCW = h2 - h1;
-        }
-
-        float hue;
-
-        if (distCW >= distCCW) {
-            hue = (float) (h1 + (distCW * currentParameter));
-        } else {
-            hue = (float) (h1 - (distCCW * currentParameter));
-        }
-
-        if (hue < 0) {
-            hue = 1 + hue;
-        }
-        if (hue > 1) {
-            hue = hue - 1;
-        }
-
-        float saturation = (float) ((1 - currentParameter) * s1 + currentParameter * s2);
-        float brightness = (float) ((1 - currentParameter) * b1 + currentParameter * b2);
-
-        return Color.getHSBColor(hue, saturation, brightness);
-    }
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/GeneralGLEventListener.java b/GUI/src/main/java/cz/fidentis/analyst/gui/GeneralGLEventListener.java
deleted file mode 100644
index 7b301610bbff7f4c465659001016fbca31c133ac..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/GeneralGLEventListener.java
+++ /dev/null
@@ -1,560 +0,0 @@
-package cz.fidentis.analyst.gui;
-
-import cz.fidentis.analyst.mesh.core.MeshModel;
-import cz.fidentis.analyst.mesh.core.MeshFacet;
-import com.jogamp.opengl.GL;
-import static com.jogamp.opengl.GL.GL_DEPTH_TEST;
-import static com.jogamp.opengl.GL.GL_FRONT_AND_BACK;
-import static com.jogamp.opengl.GL.GL_VIEWPORT;
-import com.jogamp.opengl.GL2;
-import static com.jogamp.opengl.GL2GL3.GL_FILL;
-import static com.jogamp.opengl.GL2GL3.GL_LINE;
-import com.jogamp.opengl.GLAutoDrawable;
-import com.jogamp.opengl.GLEventListener;
-import static com.jogamp.opengl.fixedfunc.GLMatrixFunc.GL_MODELVIEW_MATRIX;
-import static com.jogamp.opengl.fixedfunc.GLMatrixFunc.GL_PROJECTION_MATRIX;
-import com.jogamp.opengl.glu.GLU;
-import cz.fidentis.analyst.symmetry.Config;
-import cz.fidentis.analyst.symmetry.SignificantPoints;
-import cz.fidentis.analyst.symmetry.SymmetryEstimator;
-import javax.vecmath.Point3d;
-
-import javax.vecmath.Vector3d;
-import javax.vecmath.Vector3f;
-
-/**
- *
- * @author Natália Bebjaková
- */
-public class GeneralGLEventListener implements GLEventListener {  
-    
-    /**
-     * MeshModel that is displayed
-     */
-    private MeshModel model = new MeshModel();
-    
-    /**
-     * MeshModel of the symmetry plane
-     */
-    private MeshFacet symmetryPlaneFacet = null;
-    
-    /**
-     * GLCanvas which listener belongs to 
-     */
-    protected Canvas glCanvas;  
-    
-    /**
-    * GLU object.
-    */
-    protected GLU glu;
-    
-    /**
-     * Usage of openGL version 2
-     */
-    protected GL2 gl;
-    
-    /**
-     * The last viewport.
-     */
-    protected int[] viewport = new int[4];
-     
-    /**
-     * The last model matrix.
-     */
-    protected float[] modelViewMatrix = new float[16];
-    
-    /**
-     * The last projection matrix.
-     */
-    protected float[] projectionMatrix = new float[16];  
-    
-    /**
-     * The X coordinate of the last known mouse position during the scene rotation.
-     */
-    int mouseX = 0;
-    
-    /**
-     * The Y coordinate of the last know mouse position during the scene rotation.
-     */
-    int mouseY = 0;
-    
-    protected Vector3f defaultPosition = new Vector3f(0, 0, 300);
-    protected Vector3f currentPosition = new Vector3f(0, 0, 300);
-
-    protected double zCenter = 0;
-    protected double xCenter = 0;
-    protected double yCenter = 0;
-
-    protected double zCameraPosition;
-    protected double xCameraPosition;
-    protected double yCameraPosition;
-
-    protected double zUpPosition = 0;
-    protected double xUpPosition = 0;
-    protected double yUpPosition = 1;
-    
-    /**
-     * Decides if model is displayed as wire-frame
-     */  
-    protected boolean wireModel = false;
-
-    /**
-     * decides if the symmetryPlane is displayed
-     */
-    protected static boolean symmetryPlane;
-
-    /**
-     * Decides if the background will be white
-     */
-    protected boolean whiteBackround = false;
-    
-    /**
-     * 
-     * @return is background white or not
-     */
-    public boolean isWhiteBackround() {
-        return whiteBackround;
-    }
-    
-    /**
-     * 
-     * @return Matrix for model view
-     */
-    public float[] getModelViewMatrix() {
-        return modelViewMatrix;
-    }
-
-    /**
-     * 
-     * @return Matrix for projection
-     */
-    public float[] getProjectionMatrix() {
-        return projectionMatrix;
-    }
-    
-    /**
-     * 
-     * @return GlCanvas for displaying
-     */
-    public Canvas getGlCanvas() {
-        return glCanvas;
-    }
-    
-    /**
-     * 
-     * @param drawWire Decides if model is displayed as wire-frame
-     */
-    public void setWireMode(boolean drawWire) {
-        wireModel = drawWire;
-    }
-
-    /**
-     *
-     * @param drawSymmetry Decides if model is displayed as wire-frame
-     */
-    public void setSymmetryPlane(boolean drawSymmetry) {
-        symmetryPlane = drawSymmetry;
-    }
-
-    /**
-     * 
-     * @param whiteBackround Is backround white or not
-     */
-    public void setWhiteBackround(boolean whiteBackround) {
-        this.whiteBackround = whiteBackround;
-    }
-
-    /**
-     * Creates new EventListener
-     * @param canvas GLCanvas which listener belongs to
-     */
-    public GeneralGLEventListener(Canvas canvas) {
-        this.glCanvas = canvas;
-    }
-    
-    /**
-     *
-     * @param model Set model to be displayed
-     */
-    public void setModel(MeshModel model) {
-        this.model = model;
-    }
-
-    /**
-     *
-     * @param symmetryPlaneFacet Set model of the symmetry plane
-     */
-    public void setSymmetryPlaneFacet(MeshFacet symmetryPlaneFacet) {
-        this.symmetryPlaneFacet = symmetryPlaneFacet;
-    }
-
-    /**
-     *
-     * @return Returns displayed model 
-     */
-    public MeshModel getModel() {
-        return model;
-    }
-
-    
-    /**
-     * Invoked when main frame is created
-     * @param glad Glad object
-     */
-    @Override
-    public void init(GLAutoDrawable glad) {
-        System.out.println("OLD GeneralGLEventListener.init");
-        
-        this.gl = (GL2) glad.getGL();
-        glu = new GLU();
-      
-        gl.setSwapInterval(1);
-        gl.glEnable(GL2.GL_LIGHTING);
-        gl.glEnable(GL2.GL_LIGHT0);
-        gl.glEnable(GL2.GL_DEPTH_TEST);
-        gl.glClearColor(0,0,0,0);     // background for GLCanvas
-        gl.glClear(GL2.GL_COLOR_BUFFER_BIT);
-        
-        gl.glShadeModel(GL2.GL_SMOOTH);    // use smooth shading
-
-        gl.glDepthFunc(GL2.GL_LESS);
-        gl.glDepthRange(0.0, 1.0);
-        gl.glEnable(GL_DEPTH_TEST); 
-
-        gl.glEnable(GL2.GL_NORMALIZE);
-        gl.glDisable(GL2.GL_CULL_FACE);
-    }
-
-    /**
-     * Invoked when main frame is closed
-     * @param glad Glad object
-     */
-    @Override
-    public void dispose(GLAutoDrawable glad) {
-    }
-    
-    /**
-     * Invoked every frame.
-     * @param glad Glad object
-     */
-    @Override
-    public void display(GLAutoDrawable glad) {
-        wireModel = glCanvas.getDrawWired(); // is wire-frame or not
-        symmetryPlane = glCanvas.getDrawSymmetryPlane();
-
-        //Generate SymmetryPlane first time we request to see it
-        if (symmetryPlane && symmetryPlaneFacet == null) {
-            SymmetryEstimator estimator = new SymmetryEstimator(Config.getDefault(), SignificantPoints.CurvatureAlg.GAUSSIAN);
-            model.getFacets().get(0).accept(estimator);
-            symmetryPlaneFacet = estimator.getSymmetryPlaneMesh();
-
-            //Set calculated planes for the loaded Face
-            glCanvas.loadedFace.setSymmetryPlane(estimator.getSymmetryPlane());
-            glCanvas.loadedFace.setCuttingPlane(symmetryPlaneFacet);
-        }
-
-        if (whiteBackround) {
-            gl.glClearColor(0.9f,0.9f,0.9f,0); 
-        } else {
-            gl.glClearColor(0.25f,0.25f,0.25f,0); 
-        }
-        // background for GLCanvas       
-        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
-        gl.glLoadIdentity();
-
-        // sets model to proper position
-        glu.gluLookAt(xCameraPosition, yCameraPosition, zCameraPosition, xCenter, yCenter, zCenter, xUpPosition, yUpPosition, zUpPosition);
-
-        gl.glShadeModel(GL2.GL_SMOOTH);
-        gl.glGetIntegerv(GL_VIEWPORT, viewport, 0);
-        gl.glGetFloatv(GL_MODELVIEW_MATRIX, modelViewMatrix, 0);
-        gl.glGetFloatv(GL_PROJECTION_MATRIX, projectionMatrix, 0);
-        
-        //if there is any model, draw 
-        if (model != null) {
-            if (wireModel) {
-                gl.glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); //drawn as wire-frame
-            } else {
-                gl.glPolygonMode( GL_FRONT_AND_BACK, GL_FILL); // drawn as full traingles
-            }
-
-            drawWithoutTextures(model);
-            if (symmetryPlane) {
-                renderFacet(symmetryPlaneFacet);
-            }
-        } 
-            
-        //gl.glPopMatrix();
-        gl.glFlush();
-    }
-    
-    /**
-     * Loops through the facets and render each of them 
-     * 
-     * @param model model of the face
-     */
-    public void drawWithoutTextures(MeshModel model) {
-        for (int i = 0; i < model.getFacets().size(); i++) {
-            renderFacet(model.getFacets().get(i));
-        }
-    }
-    
-    /**
-     * Loops through the facet and render all the vertices as they are stored in corner table
-     * 
-     * @param facet facet of model
-     */
-    public void renderFacet(MeshFacet facet) {
-        gl.glBegin(GL2.GL_TRIANGLES); //vertices are rendered as triangles
-     
-        // get the normal and tex coords indicies for face i  
-        for (int v = 0; v < facet.getCornerTable().getSize(); v++) { 
-            // render the normals
-            Vector3d norm = facet.getVertices().get(facet.getCornerTable().getRow(v).getVertexIndex()).getNormal(); 
-            if(norm != null) {
-                gl.glNormal3d(norm.x, norm.y, norm.z);
-            }
-            // render the vertices
-            Point3d vert = facet.getVertices().get(facet.getCornerTable().getRow(v).getVertexIndex()).getPosition(); 
-            gl.glVertex3d(vert.x, vert.y, vert.z);
-        }
-        gl.glEnd();
-
-    }
-
-    /**
-     *
-     * @param glad Glad object
-     * @param x x
-     * @param y y
-     * @param width New width
-     * @param height New height
-     */
-    @Override
-    public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) {
-
-        if (height == 0) {
-            height = 1;    // to avoid division by 0 in aspect ratio below
-        }
-        gl.glViewport(x, y, width, height);  // size of drawing area
-
-        float h = (float) height / (float) width;
-
-        gl.glMatrixMode(GL2.GL_PROJECTION);
-        gl.glLoadIdentity();
-
-        glu.gluPerspective(65, width / (float) height, 5.0f, 1500.0f);
-        gl.glMatrixMode(GL2.GL_MODELVIEW);
-        gl.glLoadIdentity();
-
-        gl.glTranslatef(0.0f, 0.0f, -40.0f);
-    }
-
-    /**
-     *
-     * @param x New x position
-     * @param y New y position
-     * @param z New z position
-     */
-    public void setCameraPosition(float x, float y, float z) {
-        currentPosition.set(x, y, z);
-
-        setNewCameraPosition(currentPosition);
-        zCameraPosition = defaultPosition.z;
-        xCameraPosition = defaultPosition.x;
-        yCameraPosition = defaultPosition.y;
-    }    
-
-    /**
-     *
-     * @param position New position of camera
-     */
-    public void setNewCameraPosition(Vector3f position) {
-        xCameraPosition = position.x;
-        yCameraPosition = position.y;
-        zCameraPosition = position.z;
-    }
-
-    /**
-     *
-     * @param degree degree of rotation
-     */
-    public void rotateUp(double degree) {
-        rotate(-degree, 0);
-    }
-
-    /**
-     *
-     * @param degree degree of rotation
-     */
-    public void rotateDown(double degree) {
-        rotate(degree, 0);
-    }
-
-    /**
-     *
-     * @param degree degree of rotation
-     */
-    public void rotateLeft(double degree) {
-        rotate(0, degree);
-    }
-
-    /**
-     *
-     * @param degree degree of rotation
-     */
-    public void rotateRight(double degree) {
-        rotate(0, -degree);
-    }
-
-    /**
-     * 
-     * @return X axis
-     */
-    private Vector3f getXaxis() {
-        Vector3f xAxis = new Vector3f(
-                (float) ((yCameraPosition - yCenter) *zUpPosition - (zCameraPosition - zCenter) * yUpPosition),
-                (float) ((zCameraPosition - zCenter) * xUpPosition - (xCameraPosition - xCenter) * zUpPosition),
-                (float) ((xCameraPosition - xCenter) * yUpPosition - xUpPosition * (yCameraPosition - yCenter)));
-         
-        float length = (float) Math.sqrt(xAxis.x * xAxis.x +
-                xAxis.y * xAxis.y + xAxis.z * xAxis.z);
-        xAxis.set(xAxis.x / length, xAxis.y / length, xAxis.z / length);
-        return xAxis;
-    }
-
-    /**
-     * 
-     * @return Y axis
-     */
-    private Vector3f getYaxis() {
-         Vector3f yAxis = new Vector3f((float) xUpPosition, (float) yUpPosition, (float) zUpPosition);
-        float length = (float) Math.sqrt(yAxis.x * yAxis.x +
-                yAxis.y * yAxis.y + yAxis.z * yAxis.z);
-        yAxis.set((yAxis.x / length), (yAxis.y / length), (yAxis.z / length));
-        return yAxis;
-    }
-
-    /**
-     * Rotates object around axes that apear as horizontal and vertical axe on
-     * screen (paralel to the sceen edges), intersecting at the center of
-     * screen( i.e head center).
-     *
-     * @param xAngle angle around vertical axe on screen
-     * @param yAngle angle around horizontal axe on screen
-     */
-    public void rotate(double xAngle, double yAngle) {
-        Vector3f xAxis = getXaxis();
-        Vector3f yAxis = getYaxis();
-
-        Vector3f point = new Vector3f((float) xCameraPosition,
-                (float) yCameraPosition, (float) zCameraPosition);
-
-        Vector3f camera = rotateAroundAxe(point, xAxis, Math.toRadians(xAngle));
-        camera = rotateAroundAxe(camera, yAxis, Math.toRadians(yAngle));
-
-        point = new Vector3f((float) xUpPosition, (float) yUpPosition, (float) zUpPosition);
-
-        Vector3f up = rotateAroundAxe(point, xAxis, Math.toRadians(xAngle));
-        up = rotateAroundAxe(up, yAxis, Math.toRadians(yAngle));
-
-        xUpPosition = up.x;
-        yUpPosition = up.y;
-        zUpPosition = up.z;
-
-        setNewCameraPosition(camera);
-    }
-
-    /**
-     * 
-     * @param xShift xShift
-     * @param yShift yShift
-     */
-    public void move(double xShift, double yShift) {
-        Vector3f xAxis = getXaxis();
-        Vector3f yAxis = getYaxis();
-
-        Vector3f shift = new Vector3f((float) (xAxis.x * xShift + yAxis.x * yShift),
-                (float) (xAxis.y * xShift + yAxis.y * yShift), (float) (xAxis.z * xShift + yAxis.z * yShift));
-        Vector3f camera = new Vector3f((float) xCameraPosition + shift.x, (float) yCameraPosition + shift.y,
-                (float) zCameraPosition + shift.z);
-        xCenter += shift.x;
-        yCenter += shift.y;
-        zCenter += shift.z;
-
-        setNewCameraPosition(camera);
-    }
-
-    /**
-     * Calculate the new position f point from given angle and rotation axe.
-     *
-     * @param point original position
-     * @param u vector of rotation axe
-     * @param angle angle of rotation
-     * @return new position
-     */
-    public Vector3f rotateAroundAxe(Vector3f point, Vector3f u, double angle) {
-        Vector3f p;
-        float x = (float) ((Math.cos(angle) + u.x * u.x * (1 - Math.cos(angle))) * point.x
-                + (u.x * u.y * (1 - Math.cos(angle)) - u.z * Math.sin(angle)) * point.y
-                + (u.x * u.z * (1 - Math.cos(angle)) + u.y * Math.sin(angle)) * point.z);
-        float y = (float) ((u.x * u.y * (1 - Math.cos(angle)) + u.z * Math.sin(angle)) * point.x
-                + (Math.cos(angle) + u.y * u.y * (1 - Math.cos(angle))) * point.y
-                + (u.y * u.z * (1 - Math.cos(angle)) - u.x * Math.sin(angle)) * point.z);
-        float z = (float) ((u.x * u.z * (1 - Math.cos(angle)) - u.y * Math.sin(angle)) * point.x
-                + (u.y * u.z * (1 - Math.cos(angle)) + u.x * Math.sin(angle)) * point.y
-                + (Math.cos(angle) + u.z * u.z * (1 - Math.cos(angle))) * point.z);
-        p = new Vector3f(x, y, z);
-
-        return p;
-    }
-
-    /**
-     * Sets model to the starting position
-     */
-    public void rotationAndSizeRestart() {
-        xUpPosition = 0;
-        yUpPosition = 1;
-        zUpPosition = 0;
-
-        setNewCameraPosition(defaultPosition);
-        xCenter = 0;
-        yCenter = 0;
-        zCenter = 0;
-    }
-
-    /**
-     *
-     * @param distance Distance to be zoom in
-     */
-    public void zoomIn(double distance) {
-        double x = xCameraPosition - xCenter;
-        double y = yCameraPosition - yCenter;
-        double z = zCameraPosition - zCenter;
-        double sqrt = Math.sqrt(x * x + y * y + z * z);
-
-        if (sqrt > 0) {
-            xCameraPosition = xCenter + ((sqrt - distance) * x / sqrt);
-            yCameraPosition = yCenter + ((sqrt - distance) * y / sqrt);
-            zCameraPosition = zCenter + ((sqrt - distance) * z / sqrt);
-        }
-    }
-
-    /**
-     *
-     * @param distance Distance to be zoom out
-     */
-    public void zoomOut(double distance) {
-        double x = xCameraPosition - xCenter;
-        double y = yCameraPosition - yCenter;
-        double z = zCameraPosition - zCenter;
-        double sqrt = Math.sqrt(x * x + y * y + z * z);
-
-        if (sqrt == 0) {
-            sqrt = 1;
-        }
-        xCameraPosition = xCenter + ((sqrt + distance) * x / sqrt);
-        yCameraPosition = yCenter + ((sqrt + distance) * y / sqrt);
-        zCameraPosition = zCenter + ((sqrt + distance) * z / sqrt);
-    }
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/HistogramComponent.java b/GUI/src/main/java/cz/fidentis/analyst/gui/HistogramComponent.java
new file mode 100644
index 0000000000000000000000000000000000000000..280fc4ddcc65da58d918564dbc28faf83d0af410
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/gui/HistogramComponent.java
@@ -0,0 +1,230 @@
+package cz.fidentis.analyst.gui;
+
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSlider;
+import javax.swing.JSpinner;
+import javax.swing.SpinnerModel;
+import javax.swing.SpinnerNumberModel;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.geom.AffineTransform;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+
+/**
+ * @author Daniel Sokol
+ * <p>
+ * Class for computing histogram and modifing distances
+ */
+
+public class HistogramComponent extends JPanel {
+    private final DrawCanvas drawnHistogram = new DrawCanvas();
+    private final JSpinner minSpinner = new JSpinner();
+    private final JSpinner maxSpinner = new JSpinner();
+
+    private Map<MeshFacet, List<Double>> values;
+    private Double minValue = 1.0;
+    private Double maxValue = 10.0;
+    private Double oneStep = 1.0;
+    private final Map<Double, Integer> frequencies = new TreeMap<>();
+
+    private int maxFrequency = 1;
+    private int intervalsCount = 20;
+
+
+
+    public HistogramComponent() {
+        setupComponents();
+    }
+
+    /**
+     * Add swing components to frame
+     */
+    private void setupComponents() {
+        setBackground(new Color(0, 174, 163));
+        setLayout(new BoxLayout(this,BoxLayout.PAGE_AXIS));
+
+        add(new JLabel("Number of intervals:"));
+        JSlider intervalSlider = new JSlider(JSlider.HORIZONTAL, 0, 200, intervalsCount);
+        intervalSlider.setMajorTickSpacing(20);
+        intervalSlider.setMinorTickSpacing(5);
+        intervalSlider.setPaintTicks(true);
+        intervalSlider.setPaintLabels(true);
+        intervalSlider.setBackground(new Color(0, 174, 163));
+        add(intervalSlider);
+
+        drawnHistogram.setMinimumSize(new Dimension(getMinimumSize().width, 330));
+        drawnHistogram.setMaximumSize(new Dimension(getMaximumSize().width, 330));
+        drawnHistogram.setPreferredSize(new Dimension(getPreferredSize().width, 330));
+        add(drawnHistogram);
+        Box tempBox = new Box(BoxLayout.LINE_AXIS);
+
+        tempBox.add(new JLabel("Select minimum value of distances"));
+        tempBox.add(minSpinner);
+        tempBox.add(new JLabel("Select maximum value of distances"));
+        tempBox.add(maxSpinner);
+
+        JButton newButton = new JButton("Set and Compute");
+
+        newButton.addActionListener(e -> {
+            intervalsCount = intervalSlider.getValue();
+            minValue = (Double) minSpinner.getValue();
+            maxValue = (Double) maxSpinner.getValue();
+            setSpinners();
+            cutValues();
+            computeFrequencies();
+            drawnHistogram.repaint();
+
+        });
+        tempBox.add(newButton);
+        add(tempBox);
+
+    }
+
+    /**
+     * Set spinners to new min a max values
+     */
+    private void setSpinners() {
+
+        SpinnerModel minModel = new SpinnerNumberModel((double) minValue,
+                (double) minValue, (double) maxValue, (double) oneStep);
+        minSpinner.setModel(minModel);
+
+        SpinnerModel maxModel = new SpinnerNumberModel((double) maxValue,
+                (double) minValue, (double) maxValue, (double) oneStep);
+        maxSpinner.setModel(maxModel);
+    }
+
+
+    public Map<MeshFacet, List<Double>> getValues() {
+        return values;
+    }
+
+    /**
+     * Set new distances and compute their frequencies
+     *
+     * @param values Values
+     */
+    public void setValues(Map<MeshFacet, List<Double>> values) {
+        this.values = values;
+        findMinMax();
+        computeFrequencies();
+        drawnHistogram.repaint();
+        setSpinners();
+    }
+
+    public void computeFrequencies() {
+
+        oneStep = maxValue - minValue;
+        if (maxValue < 0) {
+            oneStep = Math.abs(maxValue) - Math.abs(minValue);
+        }
+        oneStep /= intervalsCount;
+        //Remove old values in frequencies
+        frequencies.clear();
+
+        for (Double i = minValue; i < maxValue; i += oneStep) {
+            int currFrequency = 0; //Number of values in current interval
+            for (List<Double> facetValues : values.values() ){
+                for (Double temp : facetValues) {
+                    if (temp >= i && temp < i + oneStep) {
+                        currFrequency++;
+                    }
+                }
+            }
+            if (currFrequency > maxFrequency) {
+                maxFrequency = currFrequency;
+            }
+            //Add beginning of interval and number of values in it
+            frequencies.put(i, currFrequency);
+        }
+    }
+
+    private void findMinMax() {
+        minValue = Double.MAX_VALUE;
+        maxValue = Double.MIN_VALUE;
+        for (List<Double> facetValues : values.values() ){
+            for (Double temp : facetValues) {
+                if (temp < minValue) {
+                    minValue = temp;
+                }
+                if (temp > maxValue) {
+                    maxValue = temp;
+                }
+            }
+        }
+    }
+
+    /**
+     * Cut of distances that are before minimum or after maximum distance selected by user
+     */
+    private void cutValues() {
+        for (List<Double> double_values : values.values() ){
+            for (int i = 0; i < values.size(); ++i) {
+                if (double_values.get(i) < minValue) {
+                    double_values.set(i, minValue);
+                } else if (double_values.get(i) > maxValue) {
+                    double_values.set(i, maxValue);
+                }
+            }
+        }
+
+    }
+
+    public Double getMinValue() {
+        return minValue;
+    }
+
+    public Double getMaxValue() {
+        return maxValue;
+    }
+
+    /**
+     * @author Daniel Sokol
+     * <p>
+     * Internal class for drawing histogram
+     */
+    private class DrawCanvas extends JPanel {
+        @Override
+        public void paintComponent(Graphics g) {
+            super.paintComponent(g);
+            setBackground(new Color(0, 174, 163));
+
+            int place = 0;
+
+            int moveStep = this.getWidth() / intervalsCount;
+            double heightModificator = (double) this.getHeight() / maxFrequency;
+
+            Graphics2D g2 = (Graphics2D) g;
+            Font font = new Font("Arial Narrow", Font.BOLD, 12);
+
+            AffineTransform affineTransform = new AffineTransform();
+            affineTransform.rotate(Math.toRadians(90), 0, 0);
+            g2.setFont(font.deriveFont(affineTransform));
+
+            for (Map.Entry<Double, Integer> entry : frequencies.entrySet()) {
+
+                g.setColor(Color.ORANGE);
+                int height = (int) (entry.getValue() * heightModificator);
+                g2.fillRect(place, 300 - height, moveStep - 2, height);
+
+                g.setColor(Color.BLACK);
+                String value = String.format("%.4f", entry.getKey());
+                g2.drawString(value, place, this.getHeight() - 50);
+                g2.drawString(entry.getValue().toString(), place, 50);
+                place += moveStep;
+            }
+        }
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/Manipulator3D.java b/GUI/src/main/java/cz/fidentis/analyst/gui/Manipulator3D.java
deleted file mode 100644
index eb1ef64a51d9aeac580ba6a1bddb852b68b91ed4..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/Manipulator3D.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package cz.fidentis.analyst.gui;
-
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseWheelEvent;
-//import javax.swing.JOptionPane;
-import javax.swing.SwingUtilities;
-
-/**
- *
- * @author Richard Pajersky
- * 
- * 3D manipulation with mouse, using 3D movement from GeneralGLEventListener
- */
-public class Manipulator3D extends MouseAdapter {
-    
-    private GeneralGLEventListener listener;
-
-    private float lastX = 0;
-    private float lastY = 0;
-    
-    private static double rotationSpeed = 0.4;
-    private static double moveSpeed = 0.4;
-
-    public Manipulator3D(GeneralGLEventListener listener) {
-        this.listener = listener;
-    }
-
-    /**
-     * Left mouse button dragging rotates
-     * Right mouse button dragging moves
-     * Middle mouse button dragging resets rotation and zoom
-     */
-    @Override
-    public void mouseDragged(MouseEvent evt) {
-        //JOptionPane.showMessageDialog(null, evt.getButton());
-
-        if (SwingUtilities.isLeftMouseButton(evt)) {
-            double rotateX = -(lastY - evt.getY()) * rotationSpeed;
-            double rotateY = +(lastX - evt.getX()) * rotationSpeed;
-            if (Math.abs(rotateX) < Math.abs(rotateY)) {
-                rotateX = 0;
-            } else if (Math.abs(rotateY) < Math.abs(rotateX)) {
-                rotateY = 0;
-            }
-            listener.rotate(rotateX, rotateY);
-        }
-        if (SwingUtilities.isRightMouseButton(evt)) {
-            double moveX = -(lastX - evt.getX()) * moveSpeed;
-            double moveY = -(lastY - evt.getY()) * moveSpeed;
-            listener.move(moveX, moveY);
-        }
-        if (SwingUtilities.isMiddleMouseButton(evt)) {
-            listener.rotationAndSizeRestart();
-        }
-        lastX = evt.getX();
-        lastY = evt.getY();
-    }
-
-    /**
-     * Actualize mouse movement
-     */
-    @Override
-    public void mouseMoved(MouseEvent e) {
-        lastX = e.getX();
-        lastY = e.getY();
-    }
-
-    /**
-     * Zoom in or out based on mouse wheel movement
-     */
-    @Override
-    public void mouseWheelMoved(MouseWheelEvent evt) {
-        if (evt.getWheelRotation() > 0) {
-            listener.zoomIn(-5 * evt.getWheelRotation());
-        } else {
-            listener.zoomOut(5 * evt.getWheelRotation());
-        }
-    }
-    
-    /**
-     * Middle mouse button click resets rotation and zoom
-     */
-    @Override
-    public void mouseClicked(MouseEvent evt) {
-        if (SwingUtilities.isMiddleMouseButton(evt))
-            listener.rotationAndSizeRestart();
-    }
-    
-    public static double getRotationSpeed() {
-        return rotationSpeed;
-    }
-
-    public static void setRotationSpeed(double rotationSpeed) {
-        Manipulator3D.rotationSpeed = rotationSpeed;
-    }
-
-    public static double getMoveSpeed() {
-        return moveSpeed;
-    }
-
-    public static void setMoveSpeed(double moveSpeed) {
-        Manipulator3D.moveSpeed = moveSpeed;
-    }
-
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/PreferencesTopComponent.form b/GUI/src/main/java/cz/fidentis/analyst/gui/PreferencesTopComponent.form
deleted file mode 100644
index fccb39fbce6ed66061aa012cf70b120c0f5d365c..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/PreferencesTopComponent.form
+++ /dev/null
@@ -1,173 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<!--
-
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing,
-    software distributed under the License is distributed on an
-    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-    KIND, either express or implied.  See the License for the
-    specific language governing permissions and limitations
-    under the License.
-
--->
-
-<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
-  <AuxValues>
-    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
-    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
-    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
-    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
-    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
-    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
-    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
-  </AuxValues>
-
-  <Layout>
-    <DimensionLayout dim="0">
-      <Group type="103" groupAlignment="0" attributes="0">
-          <Group type="102" alignment="1" attributes="0">
-              <EmptySpace max="-2" attributes="0"/>
-              <Group type="103" groupAlignment="1" attributes="0">
-                  <Group type="102" attributes="0">
-                      <Group type="103" groupAlignment="0" attributes="0">
-                          <Component id="jFormattedTextField1" max="32767" attributes="0"/>
-                          <Group type="102" alignment="0" attributes="0">
-                              <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
-                              <EmptySpace min="0" pref="183" max="32767" attributes="0"/>
-                          </Group>
-                      </Group>
-                      <EmptySpace max="-2" attributes="0"/>
-                      <Component id="jButton1" min="-2" max="-2" attributes="0"/>
-                  </Group>
-                  <Group type="102" attributes="0">
-                      <Component id="jLabel3" min="-2" max="-2" attributes="0"/>
-                      <EmptySpace max="32767" attributes="0"/>
-                      <Component id="jSlider2" min="-2" max="-2" attributes="0"/>
-                  </Group>
-                  <Group type="102" alignment="1" attributes="0">
-                      <Component id="jLabel2" min="-2" max="-2" attributes="0"/>
-                      <EmptySpace max="32767" attributes="0"/>
-                      <Component id="jSlider1" min="-2" max="-2" attributes="0"/>
-                  </Group>
-              </Group>
-              <EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
-          </Group>
-      </Group>
-    </DimensionLayout>
-    <DimensionLayout dim="1">
-      <Group type="103" groupAlignment="0" attributes="0">
-          <Group type="102" attributes="0">
-              <EmptySpace max="-2" attributes="0"/>
-              <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
-              <EmptySpace max="-2" attributes="0"/>
-              <Group type="103" groupAlignment="3" attributes="0">
-                  <Component id="jFormattedTextField1" alignment="3" min="-2" max="-2" attributes="0"/>
-                  <Component id="jButton1" alignment="3" min="-2" max="-2" attributes="0"/>
-              </Group>
-              <EmptySpace max="-2" attributes="0"/>
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <Component id="jSlider1" min="-2" max="-2" attributes="0"/>
-                  <Component id="jLabel2" min="-2" max="-2" attributes="0"/>
-              </Group>
-              <EmptySpace max="-2" attributes="0"/>
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <Component id="jSlider2" min="-2" max="-2" attributes="0"/>
-                  <Component id="jLabel3" min="-2" max="-2" attributes="0"/>
-              </Group>
-              <EmptySpace pref="172" max="32767" attributes="0"/>
-          </Group>
-      </Group>
-    </DimensionLayout>
-  </Layout>
-  <SubComponents>
-    <Component class="javax.swing.JButton" name="jButton1">
-      <Properties>
-        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-          <ResourceString bundle="cz/fidentis/analyst/gui/Bundle.properties" key="PreferencesTopComponent.jButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-        </Property>
-      </Properties>
-      <Events>
-        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton1ActionPerformed"/>
-      </Events>
-    </Component>
-    <Component class="javax.swing.JFormattedTextField" name="jFormattedTextField1">
-      <Properties>
-        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-          <ResourceString bundle="cz/fidentis/analyst/gui/Bundle.properties" key="PreferencesTopComponent.jFormattedTextField1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-        </Property>
-      </Properties>
-      <Events>
-        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jFormattedTextField1ActionPerformed"/>
-      </Events>
-    </Component>
-    <Component class="javax.swing.JLabel" name="jLabel1">
-      <Properties>
-        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
-          <ComponentRef name="jFormattedTextField1"/>
-        </Property>
-        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-          <ResourceString bundle="cz/fidentis/analyst/gui/Bundle.properties" key="PreferencesTopComponent.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-        </Property>
-      </Properties>
-    </Component>
-    <Component class="javax.swing.JSlider" name="jSlider1">
-      <Properties>
-        <Property name="majorTickSpacing" type="int" value="3"/>
-        <Property name="maximum" type="int" value="7"/>
-        <Property name="minimum" type="int" value="1"/>
-        <Property name="minorTickSpacing" type="int" value="3"/>
-        <Property name="paintTicks" type="boolean" value="true"/>
-        <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-          <ResourceString bundle="cz/fidentis/analyst/gui/Bundle.properties" key="PreferencesTopComponent.jSlider1.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-        </Property>
-        <Property name="value" type="int" value="4"/>
-      </Properties>
-      <Events>
-        <EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="jSlider1StateChanged"/>
-      </Events>
-    </Component>
-    <Component class="javax.swing.JSlider" name="jSlider2">
-      <Properties>
-        <Property name="majorTickSpacing" type="int" value="3"/>
-        <Property name="maximum" type="int" value="7"/>
-        <Property name="minimum" type="int" value="1"/>
-        <Property name="minorTickSpacing" type="int" value="3"/>
-        <Property name="paintTicks" type="boolean" value="true"/>
-        <Property name="snapToTicks" type="boolean" value="true"/>
-        <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-          <ResourceString bundle="cz/fidentis/analyst/gui/Bundle.properties" key="PreferencesTopComponent.jSlider2.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-        </Property>
-        <Property name="value" type="int" value="4"/>
-      </Properties>
-      <Events>
-        <EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="jSlider2StateChanged"/>
-      </Events>
-    </Component>
-    <Component class="javax.swing.JLabel" name="jLabel2">
-      <Properties>
-        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-          <ResourceString bundle="cz/fidentis/analyst/gui/Bundle.properties" key="PreferencesTopComponent.jLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-        </Property>
-      </Properties>
-    </Component>
-    <Component class="javax.swing.JLabel" name="jLabel3">
-      <Properties>
-        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-          <ResourceString bundle="cz/fidentis/analyst/gui/Bundle.properties" key="PreferencesTopComponent.jLabel3.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-        </Property>
-      </Properties>
-    </Component>
-  </SubComponents>
-</Form>
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/PreferencesTopComponent.java b/GUI/src/main/java/cz/fidentis/analyst/gui/PreferencesTopComponent.java
deleted file mode 100644
index 58b0d699fde2ad88accfc523d818a4f1e198ad28..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/PreferencesTopComponent.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-package cz.fidentis.analyst.gui;
-
-import org.netbeans.api.settings.ConvertAsProperties;
-import org.openide.awt.ActionID;
-import org.openide.awt.ActionReference;
-import org.openide.windows.TopComponent;
-import org.openide.util.NbBundle.Messages;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.Scanner;
-import javax.swing.JFileChooser;
-import javax.swing.JOptionPane;
-
-/**
- *
- * @author Richard Pajerský
- * 
- * Window with basic Preferences
- */
-@ConvertAsProperties(
-        dtd = "-//cz.fidentis.analyst.gui//Preferences//EN",
-        autostore = false
-)
-@TopComponent.Description(
-        preferredID = "PreferencesTopComponent",
-        //iconBase="SET/PATH/TO/ICON/HERE",
-        persistenceType = TopComponent.PERSISTENCE_ALWAYS
-)
-@TopComponent.Registration(mode = "properties", openAtStartup = false)
-@ActionID(category = "Window", id = "cz.fidentis.analyst.gui.PreferencesTopComponent")
-@ActionReference(path = "Menu/Tools", position = 2600, separatorBefore = 2550 /*, position = 333 */)
-@TopComponent.OpenActionRegistration(
-        displayName = "#CTL_PreferencesAction",
-        preferredID = "PreferencesTopComponent"
-)
-@Messages({
-    "CTL_PreferencesAction=Preferences",
-    "CTL_PreferencesTopComponent=Preferences Window",
-    "HINT_PreferencesTopComponent=This is a Preferences window"
-})
-public final class PreferencesTopComponent extends TopComponent {
-
-    public PreferencesTopComponent() {
-        initComponents();
-        setName(Bundle.CTL_PreferencesTopComponent());
-        setToolTipText(Bundle.HINT_PreferencesTopComponent());
-        putClientProperty(TopComponent.PROP_KEEP_PREFERRED_SIZE_WHEN_SLIDED_IN, Boolean.TRUE);
-        
-        createPreferencesFile();
-    }
-    
-    private void createPreferencesFile() {
-        //testing preferences fodler        
-        //String propPath = System.getProperty("user.home") + "/preferences";
-        try {
-            File myObj = new File(/*propPath + */"preferences.fip");
-        if (myObj.createNewFile()) {
-            //JOptionPane.showConfirmDialog(null, "File created: " + myObj.getName());
-        } else {
-            //JOptionPane.showConfirmDialog(null, "File already exists." + myObj.getName());
-        }
-        } catch (IOException e) {
-        JOptionPane.showConfirmDialog(null, "An error occurred.");
-        e.printStackTrace();
-        }
-    }
-
-    /**
-     * This method is called from within the constructor to initialize the form.
-     * WARNING: Do NOT modify this code. The content of this method is always
-     * regenerated by the Form Editor.
-     */
-    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
-    private void initComponents() {
-
-        jButton1 = new javax.swing.JButton();
-        jFormattedTextField1 = new javax.swing.JFormattedTextField();
-        jLabel1 = new javax.swing.JLabel();
-        jSlider1 = new javax.swing.JSlider();
-        jSlider2 = new javax.swing.JSlider();
-        jLabel2 = new javax.swing.JLabel();
-        jLabel3 = new javax.swing.JLabel();
-
-        org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(PreferencesTopComponent.class, "PreferencesTopComponent.jButton1.text")); // NOI18N
-        jButton1.addActionListener(new java.awt.event.ActionListener() {
-            public void actionPerformed(java.awt.event.ActionEvent evt) {
-                jButton1ActionPerformed(evt);
-            }
-        });
-
-        jFormattedTextField1.setText(org.openide.util.NbBundle.getMessage(PreferencesTopComponent.class, "PreferencesTopComponent.jFormattedTextField1.text")); // NOI18N
-        jFormattedTextField1.addActionListener(new java.awt.event.ActionListener() {
-            public void actionPerformed(java.awt.event.ActionEvent evt) {
-                jFormattedTextField1ActionPerformed(evt);
-            }
-        });
-
-        jLabel1.setLabelFor(jFormattedTextField1);
-        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(PreferencesTopComponent.class, "PreferencesTopComponent.jLabel1.text")); // NOI18N
-
-        jSlider1.setMajorTickSpacing(3);
-        jSlider1.setMaximum(7);
-        jSlider1.setMinimum(1);
-        jSlider1.setMinorTickSpacing(3);
-        jSlider1.setPaintTicks(true);
-        jSlider1.setToolTipText(org.openide.util.NbBundle.getMessage(PreferencesTopComponent.class, "PreferencesTopComponent.jSlider1.toolTipText")); // NOI18N
-        jSlider1.setValue(4);
-        jSlider1.addChangeListener(new javax.swing.event.ChangeListener() {
-            public void stateChanged(javax.swing.event.ChangeEvent evt) {
-                jSlider1StateChanged(evt);
-            }
-        });
-
-        jSlider2.setMajorTickSpacing(3);
-        jSlider2.setMaximum(7);
-        jSlider2.setMinimum(1);
-        jSlider2.setMinorTickSpacing(3);
-        jSlider2.setPaintTicks(true);
-        jSlider2.setSnapToTicks(true);
-        jSlider2.setToolTipText(org.openide.util.NbBundle.getMessage(PreferencesTopComponent.class, "PreferencesTopComponent.jSlider2.toolTipText")); // NOI18N
-        jSlider2.setValue(4);
-        jSlider2.addChangeListener(new javax.swing.event.ChangeListener() {
-            public void stateChanged(javax.swing.event.ChangeEvent evt) {
-                jSlider2StateChanged(evt);
-            }
-        });
-
-        org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(PreferencesTopComponent.class, "PreferencesTopComponent.jLabel2.text")); // NOI18N
-
-        org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(PreferencesTopComponent.class, "PreferencesTopComponent.jLabel3.text")); // NOI18N
-
-        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
-        this.setLayout(layout);
-        layout.setHorizontalGroup(
-            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
-                .addContainerGap()
-                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
-                    .addGroup(layout.createSequentialGroup()
-                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                            .addComponent(jFormattedTextField1)
-                            .addGroup(layout.createSequentialGroup()
-                                .addComponent(jLabel1)
-                                .addGap(0, 183, Short.MAX_VALUE)))
-                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                        .addComponent(jButton1))
-                    .addGroup(layout.createSequentialGroup()
-                        .addComponent(jLabel3)
-                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                        .addComponent(jSlider2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
-                    .addGroup(layout.createSequentialGroup()
-                        .addComponent(jLabel2)
-                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                        .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
-                .addGap(18, 18, 18))
-        );
-        layout.setVerticalGroup(
-            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(layout.createSequentialGroup()
-                .addContainerGap()
-                .addComponent(jLabel1)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
-                    .addComponent(jFormattedTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                    .addComponent(jButton1))
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                    .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                    .addComponent(jLabel2))
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                    .addComponent(jSlider2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                    .addComponent(jLabel3))
-                .addContainerGap(172, Short.MAX_VALUE))
-        );
-    }// </editor-fold>//GEN-END:initComponents
-
-    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
-        // TODO add your handling code here:
-        JFileChooser chooser = new JFileChooser(getPrefferedModelPath());
-        chooser.setDialogTitle("Model directory");
-        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
-        chooser.setAcceptAllFileFilterUsed(false);
-        if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
-            //JOptionPane.showConfirmDialog(null,
-            //    chooser.getCurrentDirectory(), "", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
-            //JOptionPane.showConfirmDialog(null,
-            //    chooser.getSelectedFile(), "", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
-            setPrefferedModelPath(chooser.getSelectedFile().toString());
-        }
-        else {
-            System.out.println("No Selection ");
-        }
-        
-        componentOpened();
-    }//GEN-LAST:event_jButton1ActionPerformed
-
-    private void jFormattedTextField1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jFormattedTextField1ActionPerformed
-        // TODO add your handling code here:
-    }//GEN-LAST:event_jFormattedTextField1ActionPerformed
-
-    private void jSlider1StateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jSlider1StateChanged
-        double newSpeed = jSlider1.getValue() / 10.0;
-        Manipulator3D.setRotationSpeed(newSpeed);
-    }//GEN-LAST:event_jSlider1StateChanged
-
-    private void jSlider2StateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jSlider2StateChanged
-        double newSpeed = jSlider2.getValue() / 10.0;
-        Manipulator3D.setMoveSpeed(newSpeed);
-    }//GEN-LAST:event_jSlider2StateChanged
-
-    // Variables declaration - do not modify//GEN-BEGIN:variables
-    private javax.swing.JButton jButton1;
-    private javax.swing.JFormattedTextField jFormattedTextField1;
-    private javax.swing.JLabel jLabel1;
-    private javax.swing.JLabel jLabel2;
-    private javax.swing.JLabel jLabel3;
-    private javax.swing.JSlider jSlider1;
-    private javax.swing.JSlider jSlider2;
-    // End of variables declaration//GEN-END:variables
-    
-    private void setPrefferedModelPath(String s) {
-        try {
-            FileWriter rewriter = new FileWriter("preferences.fip", false);
-            rewriter.write(s);
-            rewriter.close();
-        } catch (IOException ex) {
-            ex.printStackTrace();
-        }   
-    }
-    
-    private String getPrefferedModelPath() {
-        String data = "";
-        try {
-            File myObj = new File(/*propPath + */"preferences.fip");
-            if (myObj.length() == 0)
-                return data;
-            try (Scanner myReader = new Scanner(myObj)) {
-                data = myReader.nextLine();
-            }            
-        } catch (FileNotFoundException e) {
-            System.out.println("An error occurred.");
-            e.printStackTrace();
-        }
-        return data;
-    }
-    
-    @Override
-    public void componentOpened() {
-        // TODO add custom code on component opening
-        jFormattedTextField1.setText(getPrefferedModelPath());
-    }
-
-    @Override
-    public void componentClosed() {
-        // TODO add custom code on component closing
-    }
-
-    void writeProperties(java.util.Properties p) {
-        // better to version settings since initial version as advocated at
-        // http://wiki.apidesign.org/wiki/PropertyFiles
-        p.setProperty("version", "1.0");
-        // TODO store your settings
-    }
-
-    void readProperties(java.util.Properties p) {
-        String version = p.getProperty("version");
-        // TODO read your settings according to their version
-    }
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/ProjectTopComp.java b/GUI/src/main/java/cz/fidentis/analyst/gui/ProjectTopComp.java
deleted file mode 100644
index 03232d79cdc2f2fde8e049114bfc7d00d6b0a725..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/ProjectTopComp.java
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-package cz.fidentis.analyst.gui;
-
-import cz.fidentis.analyst.gui.tab.SingleFaceTab;
-import org.netbeans.api.settings.ConvertAsProperties;
-import org.openide.awt.ActionID;
-import org.openide.awt.ActionReference;
-import org.openide.windows.TopComponent;
-import org.openide.util.NbBundle.Messages;
-import cz.fidentis.analyst.Project;
-import cz.fidentis.analyst.face.HumanFace;
-import cz.fidentis.analyst.mesh.io.ModelFileFilter;
-import cz.fidentis.analyst.gui.scene.DrawableMesh;
-import java.awt.Dimension;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Scanner;
-import javax.swing.ImageIcon;
-import javax.swing.JFileChooser;
-import javax.swing.JOptionPane;
-
-/**
- * The main panel enabling analysts to select the primary and secondary faces, 
- * and to perform basic batch processing. This panel also serves as an entry point 
- * for detailed face analysis and face-to-face comparison.
- * 
- * @author Matej Kovar
- */
-@ConvertAsProperties(
-        dtd = "-//cz.fidentis.analyst.gui//Dashboard//EN",
-        autostore = false
-)
-@TopComponent.Description(
-        preferredID = "ProjectTopComp",
-        //iconBase="SET/PATH/TO/ICON/HERE",
-        persistenceType = TopComponent.PERSISTENCE_ALWAYS
-)
-@TopComponent.Registration(mode = "editor", openAtStartup = true)
-@ActionID(category = "Window", id = "cz.fidentis.analyst.gui.ProjectTopComp")
-@ActionReference(path = "Menu/Window" /*, position = 333 */)
-@TopComponent.OpenActionRegistration(
-        displayName = "#CTL_ProjectTopCompAction",
-        preferredID = "ProjectTopComp"
-)
-@Messages({
-    "CTL_ProjectTopCompAction=Project",
-    "CTL_ProjectTopCompTopComponent=Project",
-    "HINT_ProjectTopCompTopComponent=This is a Project window"
-})
-public final class ProjectTopComp extends TopComponent {
-
-    private final Project project;
-    private Map<HumanFace, SingleFaceTab> singleFaceTabs = new HashMap<>();
-
-    
-    /**
-     * Creates new ProjectTopComp, initializes new project
-     */
-    public ProjectTopComp() {
-        project = new Project();
-        initComponents();
-        setName(Bundle.CTL_ProjectTopCompTopComponent());
-        setToolTipText(Bundle.HINT_ProjectTopCompTopComponent());
-        putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
-        putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, Boolean.TRUE);
-        putClientProperty(TopComponent.PROP_UNDOCKING_DISABLED, Boolean.TRUE);
-    }
-
-    /**
-     * This method is called from within the constructor to initialize the form.
-     * WARNING: Do NOT modify this code. The content of this method is always
-     * regenerated by the Form Editor.
-     */
-    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
-    private void initComponents() {
-        java.awt.GridBagConstraints gridBagConstraints;
-
-        jPanel1 = new javax.swing.JPanel();
-        jPanel4 = new javax.swing.JPanel();
-        jPanel2 = new javax.swing.JPanel();
-        jLabel1 = new javax.swing.JLabel();
-        jPanel5 = new javax.swing.JPanel();
-        addButton1 = new javax.swing.JButton();
-        removeButton1 = new javax.swing.JButton();
-        selectAllButton1 = new javax.swing.JButton();
-        deselectAllButton1 = new javax.swing.JButton();
-        collapseButton1 = new javax.swing.JButton();
-        inflateButton1 = new javax.swing.JButton();
-        analyzeButton1 = new javax.swing.JButton();
-
-        setLayout(new java.awt.BorderLayout());
-
-        jPanel1.setBackground(new java.awt.Color(0, 174, 163));
-        jPanel1.setPreferredSize(new java.awt.Dimension(0, 0));
-
-        jPanel4.setBackground(new java.awt.Color(2, 138, 129));
-        jPanel4.setBorder(javax.swing.BorderFactory.createEtchedBorder());
-        jPanel4.setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());
-
-        jPanel2.setBackground(new java.awt.Color(0, 87, 87));
-
-        jLabel1.setFont(new java.awt.Font("Tahoma", 0, 18)); // NOI18N
-        jLabel1.setForeground(new java.awt.Color(204, 204, 204));
-        jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
-
-        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
-        jPanel2.setLayout(jPanel2Layout);
-        jPanel2Layout.setHorizontalGroup(
-            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
-                .addContainerGap()
-                .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 100, Short.MAX_VALUE)
-                .addContainerGap())
-        );
-        jPanel2Layout.setVerticalGroup(
-            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
-                .addContainerGap()
-                .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 98, Short.MAX_VALUE)
-                .addContainerGap())
-        );
-
-        jPanel4.add(jPanel2, new org.netbeans.lib.awtextra.AbsoluteConstraints(30, 30, 120, 120));
-
-        jPanel5.setBackground(new java.awt.Color(2, 138, 129));
-        jPanel5.setBorder(javax.swing.BorderFactory.createEtchedBorder());
-        jPanel5.setLayout(new java.awt.GridBagLayout());
-
-        addButton1.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
-        org.openide.awt.Mnemonics.setLocalizedText(addButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.addButton1.text")); // NOI18N
-        addButton1.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                addButton1MouseClicked(evt);
-            }
-        });
-        gridBagConstraints = new java.awt.GridBagConstraints();
-        gridBagConstraints.gridx = 0;
-        gridBagConstraints.gridy = 0;
-        gridBagConstraints.ipadx = 20;
-        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
-        gridBagConstraints.insets = new java.awt.Insets(16, 16, 13, 4);
-        jPanel5.add(addButton1, gridBagConstraints);
-
-        removeButton1.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
-        org.openide.awt.Mnemonics.setLocalizedText(removeButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.removeButton1.text")); // NOI18N
-        removeButton1.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                removeButton1MouseClicked(evt);
-            }
-        });
-        gridBagConstraints = new java.awt.GridBagConstraints();
-        gridBagConstraints.gridx = 1;
-        gridBagConstraints.gridy = 0;
-        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
-        gridBagConstraints.insets = new java.awt.Insets(16, 22, 13, 4);
-        jPanel5.add(removeButton1, gridBagConstraints);
-
-        selectAllButton1.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
-        org.openide.awt.Mnemonics.setLocalizedText(selectAllButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.selectAllButton1.text")); // NOI18N
-        gridBagConstraints = new java.awt.GridBagConstraints();
-        gridBagConstraints.gridx = 2;
-        gridBagConstraints.gridy = 0;
-        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
-        gridBagConstraints.insets = new java.awt.Insets(16, 22, 13, 4);
-        jPanel5.add(selectAllButton1, gridBagConstraints);
-
-        deselectAllButton1.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
-        org.openide.awt.Mnemonics.setLocalizedText(deselectAllButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.deselectAllButton1.text")); // NOI18N
-        gridBagConstraints = new java.awt.GridBagConstraints();
-        gridBagConstraints.gridx = 3;
-        gridBagConstraints.gridy = 0;
-        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
-        gridBagConstraints.insets = new java.awt.Insets(16, 22, 13, 4);
-        jPanel5.add(deselectAllButton1, gridBagConstraints);
-
-        collapseButton1.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
-        org.openide.awt.Mnemonics.setLocalizedText(collapseButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.collapseButton1.text")); // NOI18N
-        gridBagConstraints = new java.awt.GridBagConstraints();
-        gridBagConstraints.gridx = 4;
-        gridBagConstraints.gridy = 0;
-        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
-        gridBagConstraints.insets = new java.awt.Insets(16, 22, 13, 4);
-        jPanel5.add(collapseButton1, gridBagConstraints);
-
-        inflateButton1.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
-        org.openide.awt.Mnemonics.setLocalizedText(inflateButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.inflateButton1.text")); // NOI18N
-        inflateButton1.setAlignmentX(0.5F);
-        gridBagConstraints = new java.awt.GridBagConstraints();
-        gridBagConstraints.gridx = 5;
-        gridBagConstraints.gridy = 0;
-        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
-        gridBagConstraints.insets = new java.awt.Insets(16, 22, 13, 4);
-        jPanel5.add(inflateButton1, gridBagConstraints);
-
-        analyzeButton1.setBackground(new java.awt.Color(183, 240, 240));
-        analyzeButton1.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
-        org.openide.awt.Mnemonics.setLocalizedText(analyzeButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.analyzeButton1.text")); // NOI18N
-        analyzeButton1.setAlignmentX(0.5F);
-        gridBagConstraints = new java.awt.GridBagConstraints();
-        gridBagConstraints.insets = new java.awt.Insets(16, 43, 13, 25);
-        jPanel5.add(analyzeButton1, gridBagConstraints);
-
-        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
-        jPanel1.setLayout(jPanel1Layout);
-        jPanel1Layout.setHorizontalGroup(
-            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(jPanel1Layout.createSequentialGroup()
-                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
-                    .addComponent(jPanel4, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                    .addComponent(jPanel5, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
-                .addGap(0, 450, Short.MAX_VALUE))
-        );
-        jPanel1Layout.setVerticalGroup(
-            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(jPanel1Layout.createSequentialGroup()
-                .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, 180, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addContainerGap(580, Short.MAX_VALUE))
-        );
-
-        add(jPanel1, java.awt.BorderLayout.CENTER);
-    }// </editor-fold>//GEN-END:initComponents
-
-    /**
-     * 
-     * @param evt starts function for loading model
-     */
-    private void addButton1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_addButton1MouseClicked
-        loadModel();
-    }//GEN-LAST:event_addButton1MouseClicked
-
-    /**
-     * TEMP. behavior, remove button will be removing selected secondary face later
-     * @param evt Removes primary face
-     */
-    private void removeButton1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_removeButton1MouseClicked
-        if (this.project.getPrimaryFace() != null) {
-            this.project.removePrimaryFace();
-            jLabel1.setText("");   
-        }
-    }//GEN-LAST:event_removeButton1MouseClicked
-
-    // Variables declaration - do not modify//GEN-BEGIN:variables
-    private javax.swing.JButton addButton1;
-    private javax.swing.JButton analyzeButton1;
-    private javax.swing.JButton collapseButton1;
-    private javax.swing.JButton deselectAllButton1;
-    private javax.swing.JButton inflateButton1;
-    private javax.swing.JLabel jLabel1;
-    private javax.swing.JPanel jPanel1;
-    private javax.swing.JPanel jPanel2;
-    private javax.swing.JPanel jPanel4;
-    private javax.swing.JPanel jPanel5;
-    private javax.swing.JButton removeButton1;
-    private javax.swing.JButton selectAllButton1;
-    // End of variables declaration//GEN-END:variables
-    @Override
-    public void componentOpened() {
-        // TODO add custom code on component opening
-    }
-
-    @Override
-    public void componentClosed() {
-        // TODO add custom code on component closing
-    }
-
-    void writeProperties(java.util.Properties p) {
-        // better to version settings since initial version as advocated at
-        // http://wiki.apidesign.org/wiki/PropertyFiles
-        p.setProperty("version", "1.0");
-        // TODO store your settings
-    }
-
-    void readProperties(java.util.Properties p) {
-        String version = p.getProperty("version");
-        // TODO read your settings according to their version
-    }
-    
-    /**
-     * Loads model selected in file chooser by user
-     */
-    public void loadModel () {
-        String[] extensions = new String[2];
-        extensions[0] = "obj";
-        extensions[1] = "OBJ";
-        
-        //enables to shows just .obj files in file chooser
-        ModelFileFilter filter = new ModelFileFilter(extensions, "*.obj");
-        JFileChooser jFileChooser1 = new JFileChooser(getPrefferedModelPath());
-        jFileChooser1.setPreferredSize(new Dimension (800,500));
-       
-        jFileChooser1.addChoosableFileFilter(filter);        
-       
-        //file chooser will appear on top of projectTopComp
-        jFileChooser1.showOpenDialog(this);
-        jFileChooser1.setDialogTitle("Import obj file");
-        
-        setPrefferedModelPath(jFileChooser1.getCurrentDirectory().toString());
-        
-        File[] fileArray = new File[1];
-        //saves selected file by user as first element in array
-        fileArray[0] = jFileChooser1.getSelectedFile();
-
-        if (fileArray.length <= 0) {
-            System.out.print("No file chosen.");
-        } else {
-            this.addModel(fileArray[0]);
-        }       
-    }
-    
-    /**
-     * Loads the model in .obj format from file and adds this model to project
-     * as primary face. If file is not correct, shows dialog with message.
-     *
-     * @param file File from which model will be read
-     */
-    private void addModel (final File file) {
-        try {
-            HumanFace loadedFace;
-            loadedFace = new HumanFace(new File (file.getPath()));
-            this.project.setPrimaryFace(loadedFace);
-            jLabel1.setText(file.getName());
-            createSingleFaceTab(loadedFace, file.getName());
-        } catch (Exception e) {
-            System.out.println(e.getMessage());
-            JOptionPane.showMessageDialog(this, "File doesn't contain any model", "Model is not loaded.",
-                    0, new ImageIcon(getClass().getResource("/notLoadedModel.png")));
-            System.out.println ("File doesn't contain any model");
-        }
-    }
-    
-    private void setPrefferedModelPath(String s) {
-        //TODO remove duplicate with PreferenceTopComponent
-        try {
-            FileWriter rewriter = new FileWriter("preferences.fip", false);
-            rewriter.write(s);
-            rewriter.close();
-        } catch (IOException ex) {
-            ex.printStackTrace();
-        }   
-    }
-    
-    private String getPrefferedModelPath() {
-        //TODO remove duplicate with PreferenceTopComponent
-        String data = "";
-        try {
-            File myObj = new File(/*propPath + */"preferences.fip");
-            if (myObj.length() == 0)
-                return data;
-            try (Scanner myReader = new Scanner(myObj)) {
-                data = myReader.nextLine();
-            }            
-        } catch (FileNotFoundException e) {
-            System.out.println("An error occurred.");
-            e.printStackTrace();
-        }
-        return data;
-    }
-    
-    private void createSingleFaceTab(HumanFace face, String name) {
-        SingleFaceTab newTab = new SingleFaceTab();
-        newTab.setName(name);
-        newTab.getCanvas().initScene(face);
-        this.singleFaceTabs.put(face, newTab);
-        newTab.open();
-        newTab.requestActive();
-    }
-
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/RegistrationGLEventListener.java b/GUI/src/main/java/cz/fidentis/analyst/gui/RegistrationGLEventListener.java
deleted file mode 100644
index 0b9fd9f1fb76495aeb3719f9e77be53f1ea4494e..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/RegistrationGLEventListener.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-package cz.fidentis.analyst.gui;
-
-import com.jogamp.opengl.GL;
-import static com.jogamp.opengl.GL.GL_FRONT_AND_BACK;
-import static com.jogamp.opengl.GL.GL_VIEWPORT;
-import com.jogamp.opengl.GL2;
-import static com.jogamp.opengl.GL2GL3.GL_FILL;
-import static com.jogamp.opengl.GL2GL3.GL_LINE;
-import com.jogamp.opengl.GLAutoDrawable;
-import static com.jogamp.opengl.fixedfunc.GLMatrixFunc.GL_MODELVIEW_MATRIX;
-import static com.jogamp.opengl.fixedfunc.GLMatrixFunc.GL_PROJECTION_MATRIX;
-import cz.fidentis.analyst.icp.Icp;
-//import cz.fidentis.analyst.face.HumanFace;
-import cz.fidentis.analyst.mesh.core.MeshFacet;
-import cz.fidentis.analyst.mesh.core.MeshModel;
-import cz.fidentis.analyst.mesh.core.MeshPoint;
-import java.awt.Color;
-import javax.vecmath.Point3d;
-import javax.vecmath.Vector3d;
-
-/**
- *
- * @author Richard Pajersky
- */
-public class RegistrationGLEventListener extends GeneralGLEventListener{
-    
-    private MeshModel primaryModel = null;
-    private MeshModel secondaryModel = null;
-    
-    private Color primaryColor = Color.BLUE;
-    private Color secondaryColor = Color.RED;
-    
-    private boolean other = false;
-    
-    private double leftPt = 0.0f;
-    private double rightPt = 0.0f;
-    private double topPt = 0.0f;
-    private double bottomPt = 0.0f;
-    private double farPt = 0.0f;
-    private double nearPt = 0.0f;
-    private Vector3d center;
-    
-    public RegistrationGLEventListener(Canvas primary, Canvas secondary) {
-        super(primary);
-    }
-    
-    private void calculateCenter(MeshModel model) {
-        for (MeshFacet mf : model.getFacets()) {
-            for (MeshPoint mp : mf.getVertices()) {
-                Point3d vert = mp.getPosition();
-                if (vert.x > rightPt) {
-                    rightPt = vert.x;
-                }
-                if (vert.x < leftPt) {
-                    leftPt = vert.x;
-                }
-                if (vert.y > topPt) {
-                    topPt = vert.y;
-                }
-                if (vert.y < bottomPt) {
-                    bottomPt = vert.y;
-                }
-                if (vert.z > nearPt) {
-                    nearPt = vert.z;
-                }
-                if (vert.z < farPt) {
-                    farPt = vert.z;
-                }
-            }
-        }
-        double xc = (rightPt + leftPt) / 2.0f;
-        double yc = (topPt + bottomPt) / 2.0f;
-        double zc = (nearPt + farPt) / 2.0f;
-        center = new Vector3d(xc, yc, zc);
-    }
-    
-    @Override
-    public void setModel(MeshModel model) {
-        if (primaryModel == null) { 
-            primaryModel = model;
-        }
-        else {
-            Icp icp = new Icp();
-            icp.setParameters(10, false, 0.05);
-            MeshFacet facet = icp.getTransformedFacet(primaryModel.getFacets().get(0), model.getFacets().get(0));
-            MeshModel newModel = new MeshModel();
-            newModel.addFacet(facet);
-            secondaryModel = newModel;
-        }
-    }
-    
-    @Override
-    public void display(GLAutoDrawable glad) {
-        wireModel = glCanvas.getDrawWired(); // is wire-frame or not
-        if (whiteBackround) {
-            gl.glClearColor(0.9f,0.9f,0.9f,0); 
-        } else {
-            gl.glClearColor(0.25f,0.25f,0.25f,0);
-        }
-        // background for GLCanvas       
-        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
-        gl.glLoadIdentity();
-
-        // sets model to proper position
-        glu.gluLookAt(xCameraPosition, yCameraPosition, zCameraPosition, xCenter, yCenter, zCenter, xUpPosition, yUpPosition, zUpPosition);
-
-        gl.glShadeModel(GL2.GL_SMOOTH);
-        gl.glGetIntegerv(GL_VIEWPORT, viewport, 0);
-        gl.glGetFloatv(GL_MODELVIEW_MATRIX, modelViewMatrix, 0);
-        gl.glGetFloatv(GL_PROJECTION_MATRIX, projectionMatrix, 0);
-        
-        //if there is any model, draw 
-        if (primaryModel != null) {
-            if (wireModel) {
-                gl.glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); //drawn as wire-frame
-                drawWithoutTextures(primaryModel);
-                if (secondaryModel != null)
-                    drawWithoutTextures(secondaryModel);
-            } else {
-                gl.glPolygonMode( GL_FRONT_AND_BACK, GL_FILL); // drawn as full traingles
-                drawWithoutTextures(primaryModel);
-                if (secondaryModel != null)
-                    drawWithoutTextures(secondaryModel);
-            }
-        } 
-            
-        //gl.glPopMatrix();
-        gl.glFlush();
-    }
-    
-    /**
-     * Loops through the facets and render each of them 
-     * 
-     * @param model model of the face
-     */
-    @Override
-    public void drawWithoutTextures(MeshModel model) {
-        for (int i = 0; i < model.getFacets().size(); i++) {
-            renderFacet(model.getFacets().get(i));
-        }
-        other = !other;
-    }
-    
-    /**
-     * Loops through the facet and render all the vertices as they are stored in corner table
-     * 
-     * @param facet facet of model
-     */
-    @Override
-    public void renderFacet(MeshFacet facet) {
-        gl.glBegin(GL2.GL_TRIANGLES); //vertices are rendered as triangles
-        // get the normal and tex coords indicies for face i  
-        for (int v = 0; v < facet.getCornerTable().getSize(); v++) { 
-            // render the normals
-            Vector3d norm; 
-            norm = facet.getVertices().get(facet.getCornerTable().getRow(v).getVertexIndex()).getNormal();
-            if(norm != null) {
-                gl.glNormal3d(norm.x, norm.y, norm.z);
-            }
-            // render the vertices
-            Point3d vert; 
-            vert = facet.getVertices().get(facet.getCornerTable().getRow(v).getVertexIndex()).getPosition();
-            //Color c = Color.GREEN;
-            if (other && secondaryModel != null)
-                gl.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_DIFFUSE, secondaryColor.getComponents(null), 0);
-            else
-                gl.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_DIFFUSE, primaryColor.getComponents(null), 0);
-            gl.glVertex3d(vert.x, vert.y, vert.z);
-        }
-        gl.glEnd();
-    }
-    
-    public Color getPrimaryColor() {
-        return primaryColor;
-    }
-
-    public void setPrimaryColor(Color primaryColor) {
-        this.primaryColor = primaryColor;
-    }
-
-    public Color getSecondaryColor() {
-        return secondaryColor;
-    }
-
-    public void setSecondaryColor(Color secondaryColor) {
-        this.secondaryColor = secondaryColor;
-    }
-    
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/SymmetryEstimator.java b/GUI/src/main/java/cz/fidentis/analyst/gui/SymmetryEstimator.java
deleted file mode 100644
index cadbb914dc697d00c95538de658354d33b4093b8..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/SymmetryEstimator.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package cz.fidentis.analyst.gui;
-
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import org.openide.awt.ActionID;
-import org.openide.awt.ActionReference;
-import org.openide.awt.ActionReferences;
-import org.openide.awt.ActionRegistration;
-import org.openide.util.NbBundle.Messages;
-
-/**
- *
- * @author Natalia Bebjakova 
- * 
- * Symmetry estimator.
- */
-
-@ActionID(
-        category = "File",
-        id = "cz.fidentis.analyst.gui.SymmetryEstimator"
-)
-@ActionRegistration(
-        iconBase = "symmetry16x16.png",
-        displayName = "#CTL_SymmetryEstimator"
-)
-@ActionReferences({
-    @ActionReference(path = "Menu/Edit", position = 2600, separatorBefore = 2550),
-    @ActionReference(path = "Toolbars/File", position = 300)
-})
-@Messages("CTL_SymmetryEstimator=Symmetry Estimator")
-public final class SymmetryEstimator implements ActionListener {
-
-    /**
-     * Flag for whether the symmetry plane should be displayed
-     */
-    boolean symmetryPlaneClicked = false;
-
-    @Override
-    public void actionPerformed(ActionEvent e) {
-        if (symmetryPlaneClicked) {
-            symmetryPlaneClicked = false;
-            Canvas.setDrawSymmetryPlane(symmetryPlaneClicked);
-        } else {
-            symmetryPlaneClicked = true;
-            Canvas.setDrawSymmetryPlane(symmetryPlaneClicked);
-        }
-    }
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/SymmetryPanel.form b/GUI/src/main/java/cz/fidentis/analyst/gui/SymmetryPanel.form
deleted file mode 100644
index 6080c1c14b9ea359619d3141209a7efa4adaae1a..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/SymmetryPanel.form
+++ /dev/null
@@ -1,499 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
-  <AuxValues>
-    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
-    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
-    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
-    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
-    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
-  </AuxValues>
-
-  <Layout>
-    <DimensionLayout dim="0">
-      <Group type="103" groupAlignment="0" attributes="0">
-          <Component id="symetrySpecificationPanel" alignment="0" max="32767" attributes="0"/>
-      </Group>
-    </DimensionLayout>
-    <DimensionLayout dim="1">
-      <Group type="103" groupAlignment="0" attributes="0">
-          <Component id="symetrySpecificationPanel" alignment="0" max="32767" attributes="0"/>
-      </Group>
-    </DimensionLayout>
-  </Layout>
-  <SubComponents>
-    <Container class="javax.swing.JPanel" name="symetrySpecificationPanel">
-      <Properties>
-        <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-          <Color blue="e2" green="e6" red="b0" type="rgb"/>
-        </Property>
-      </Properties>
-
-      <Layout>
-        <DimensionLayout dim="0">
-          <Group type="103" groupAlignment="0" attributes="0">
-              <Group type="102" attributes="0">
-                  <Group type="103" groupAlignment="1" attributes="0">
-                      <Group type="102" attributes="0">
-                          <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
-                          <Component id="defaultValues" min="-2" max="-2" attributes="0"/>
-                      </Group>
-                      <Group type="102" attributes="0">
-                          <EmptySpace min="-2" pref="17" max="-2" attributes="0"/>
-                          <Group type="103" groupAlignment="0" attributes="0">
-                              <Group type="102" attributes="0">
-                                  <EmptySpace min="-2" pref="154" max="-2" attributes="0"/>
-                                  <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
-                              </Group>
-                              <Group type="102" attributes="0">
-                                  <Component id="showPlaneLabel" min="-2" pref="147" max="-2" attributes="0"/>
-                                  <EmptySpace max="32767" attributes="0"/>
-                                  <Component id="originalModelButton" min="-2" pref="181" max="-2" attributes="0"/>
-                              </Group>
-                          </Group>
-                      </Group>
-                      <Group type="102" attributes="0">
-                          <EmptySpace max="-2" attributes="0"/>
-                          <Group type="103" groupAlignment="0" attributes="0">
-                              <Group type="102" attributes="0">
-                                  <EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
-                                  <Component id="minCurvatio8" min="-2" max="-2" attributes="0"/>
-                                  <EmptySpace type="unrelated" max="-2" attributes="0"/>
-                                  <Component id="averagingCheckBox" min="-2" max="-2" attributes="0"/>
-                                  <EmptySpace max="32767" attributes="0"/>
-                                  <Component id="symetryButton" min="-2" max="-2" attributes="0"/>
-                              </Group>
-                              <Group type="102" attributes="0">
-                                  <Group type="103" groupAlignment="0" attributes="0">
-                                      <Component id="infoMinAngleCos" min="-2" max="-2" attributes="0"/>
-                                      <Component id="infoRelDist" alignment="0" min="-2" max="-2" attributes="0"/>
-                                      <Component id="infoNormalAngle" alignment="0" min="-2" max="-2" attributes="0"/>
-                                      <Component id="infoPoints" alignment="0" min="-2" max="-2" attributes="0"/>
-                                      <Component id="infoMinCurv" alignment="0" min="-2" max="-2" attributes="0"/>
-                                  </Group>
-                                  <EmptySpace max="-2" attributes="0"/>
-                                  <Group type="103" groupAlignment="0" attributes="0">
-                                      <Component id="minCurvatio4" pref="0" max="32767" attributes="0"/>
-                                      <Group type="102" alignment="0" attributes="0">
-                                          <Group type="103" groupAlignment="0" attributes="0">
-                                              <Component id="minCurvatio" min="-2" max="-2" attributes="0"/>
-                                              <Component id="minCurvatio3" min="-2" max="-2" attributes="0"/>
-                                              <Component id="minCurvatio2" alignment="0" min="-2" max="-2" attributes="0"/>
-                                              <Component id="significantPointLabel" alignment="0" min="-2" max="-2" attributes="0"/>
-                                          </Group>
-                                          <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
-                                      </Group>
-                                  </Group>
-                                  <EmptySpace max="-2" attributes="0"/>
-                                  <Group type="103" groupAlignment="1" attributes="0">
-                                      <Group type="103" groupAlignment="0" max="-2" attributes="0">
-                                          <Component id="curavatureSlider" alignment="1" pref="0" max="32767" attributes="0"/>
-                                          <Component id="relativeDistanceSlider" alignment="1" pref="0" max="32767" attributes="0"/>
-                                          <Component id="significantPointSlider" alignment="1" min="-2" pref="164" max="-2" attributes="0"/>
-                                          <Component id="angleCosineSlider" alignment="1" min="-2" pref="164" max="-2" attributes="0"/>
-                                      </Group>
-                                      <Component id="normalAngleSlider" min="-2" pref="164" max="-2" attributes="0"/>
-                                  </Group>
-                                  <EmptySpace type="separate" max="-2" attributes="0"/>
-                                  <Group type="103" groupAlignment="0" max="-2" attributes="0">
-                                      <Component id="distanceTextField" max="32767" attributes="0"/>
-                                      <Component id="normalTextField" alignment="0" max="32767" attributes="0"/>
-                                      <Component id="significantTextField" min="-2" pref="46" max="-2" attributes="0"/>
-                                      <Component id="textFieldCurvature" min="-2" pref="46" max="-2" attributes="0"/>
-                                      <Component id="textFieldMinCos" min="-2" pref="46" max="-2" attributes="0"/>
-                                  </Group>
-                              </Group>
-                          </Group>
-                      </Group>
-                  </Group>
-                  <EmptySpace max="32767" attributes="0"/>
-              </Group>
-          </Group>
-        </DimensionLayout>
-        <DimensionLayout dim="1">
-          <Group type="103" groupAlignment="0" attributes="0">
-              <Group type="102" attributes="0">
-                  <EmptySpace max="32767" attributes="0"/>
-                  <Group type="103" groupAlignment="1" attributes="0">
-                      <Group type="103" alignment="1" groupAlignment="0" attributes="0">
-                          <Component id="infoPoints" min="-2" max="-2" attributes="0"/>
-                          <Component id="significantPointLabel" min="-2" pref="27" max="-2" attributes="0"/>
-                      </Group>
-                      <Group type="103" alignment="1" groupAlignment="0" attributes="0">
-                          <Component id="significantTextField" min="-2" max="-2" attributes="0"/>
-                          <Component id="significantPointSlider" min="-2" pref="28" max="-2" attributes="0"/>
-                      </Group>
-                  </Group>
-                  <EmptySpace type="unrelated" max="-2" attributes="0"/>
-                  <Group type="103" groupAlignment="1" attributes="0">
-                      <Component id="minCurvatio" min="-2" pref="26" max="-2" attributes="0"/>
-                      <Group type="102" alignment="1" attributes="0">
-                          <Component id="textFieldCurvature" min="-2" max="-2" attributes="0"/>
-                          <EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
-                      </Group>
-                      <Component id="infoMinCurv" min="-2" max="-2" attributes="0"/>
-                      <Component id="curavatureSlider" min="-2" pref="26" max="-2" attributes="0"/>
-                  </Group>
-                  <EmptySpace type="unrelated" max="-2" attributes="0"/>
-                  <Group type="103" groupAlignment="0" attributes="0">
-                      <Component id="infoMinAngleCos" alignment="1" min="-2" max="-2" attributes="0"/>
-                      <Component id="minCurvatio2" alignment="1" min="-2" pref="26" max="-2" attributes="0"/>
-                      <Component id="textFieldMinCos" alignment="0" min="-2" max="-2" attributes="0"/>
-                      <Component id="angleCosineSlider" min="-2" max="-2" attributes="0"/>
-                  </Group>
-                  <EmptySpace type="unrelated" max="-2" attributes="0"/>
-                  <Group type="103" groupAlignment="0" attributes="0">
-                      <Group type="102" alignment="0" attributes="0">
-                          <Group type="103" groupAlignment="0" max="-2" attributes="0">
-                              <Component id="normalAngleSlider" max="32767" attributes="0"/>
-                              <Component id="normalTextField" max="32767" attributes="0"/>
-                          </Group>
-                          <EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
-                          <Component id="distanceTextField" min="-2" max="-2" attributes="0"/>
-                      </Group>
-                      <Group type="102" alignment="0" attributes="0">
-                          <Group type="103" groupAlignment="0" attributes="0">
-                              <Component id="minCurvatio4" min="-2" pref="27" max="-2" attributes="0"/>
-                              <Component id="infoNormalAngle" min="-2" max="-2" attributes="0"/>
-                          </Group>
-                          <EmptySpace max="32767" attributes="0"/>
-                          <Group type="103" groupAlignment="0" attributes="0">
-                              <Component id="infoRelDist" alignment="1" min="-2" max="-2" attributes="0"/>
-                              <Group type="103" alignment="1" groupAlignment="0" attributes="0">
-                                  <Component id="relativeDistanceSlider" min="-2" pref="22" max="-2" attributes="0"/>
-                                  <Component id="minCurvatio3" min="-2" pref="26" max="-2" attributes="0"/>
-                              </Group>
-                          </Group>
-                          <EmptySpace min="-2" pref="13" max="-2" attributes="0"/>
-                      </Group>
-                  </Group>
-                  <Component id="defaultValues" min="-2" max="-2" attributes="0"/>
-                  <EmptySpace min="-2" pref="17" max="-2" attributes="0"/>
-                  <Group type="103" groupAlignment="0" attributes="0">
-                      <Group type="102" attributes="0">
-                          <Component id="symetryButton" min="-2" pref="75" max="-2" attributes="0"/>
-                          <EmptySpace max="32767" attributes="0"/>
-                          <Component id="originalModelButton" min="-2" max="-2" attributes="0"/>
-                          <EmptySpace max="32767" attributes="0"/>
-                      </Group>
-                      <Group type="102" alignment="0" attributes="0">
-                          <Group type="103" groupAlignment="1" attributes="0">
-                              <Component id="averagingCheckBox" min="-2" max="-2" attributes="0"/>
-                              <Component id="minCurvatio8" min="-2" pref="28" max="-2" attributes="0"/>
-                          </Group>
-                          <EmptySpace pref="53" max="32767" attributes="0"/>
-                          <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
-                          <EmptySpace min="-2" pref="45" max="-2" attributes="0"/>
-                          <Component id="showPlaneLabel" min="-2" max="-2" attributes="0"/>
-                          <EmptySpace pref="27" max="32767" attributes="0"/>
-                      </Group>
-                  </Group>
-              </Group>
-          </Group>
-        </DimensionLayout>
-      </Layout>
-      <SubComponents>
-        <Component class="javax.swing.JSlider" name="curavatureSlider">
-          <Properties>
-            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="fa" green="fa" red="fa" type="rgb"/>
-            </Property>
-            <Property name="majorTickSpacing" type="int" value="1"/>
-            <Property name="minimum" type="int" value="50"/>
-            <Property name="snapToTicks" type="boolean" value="true"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-        </Component>
-        <Component class="javax.swing.JSlider" name="angleCosineSlider">
-          <Properties>
-            <Property name="minimum" type="int" value="80"/>
-            <Property name="snapToTicks" type="boolean" value="true"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-        </Component>
-        <Component class="javax.swing.JLabel" name="minCurvatio">
-          <Properties>
-            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
-              <Font name="Arial" size="14" style="1"/>
-            </Property>
-            <Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="69" green="72" red="14" type="rgb"/>
-            </Property>
-            <Property name="text" type="java.lang.String" value="Min. Curvature Ratio"/>
-          </Properties>
-        </Component>
-        <Component class="javax.swing.JLabel" name="minCurvatio2">
-          <Properties>
-            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
-              <Font name="Arial" size="14" style="1"/>
-            </Property>
-            <Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="69" green="72" red="14" type="rgb"/>
-            </Property>
-            <Property name="text" type="java.lang.String" value="Min. Angle Cosine"/>
-          </Properties>
-        </Component>
-        <Component class="javax.swing.JSlider" name="normalAngleSlider">
-          <Properties>
-            <Property name="minimum" type="int" value="80"/>
-            <Property name="snapToTicks" type="boolean" value="true"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-        </Component>
-        <Component class="javax.swing.JLabel" name="minCurvatio3">
-          <Properties>
-            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
-              <Font name="Arial" size="14" style="1"/>
-            </Property>
-            <Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="69" green="72" red="14" type="rgb"/>
-            </Property>
-            <Property name="text" type="java.lang.String" value="Relative Distance"/>
-          </Properties>
-        </Component>
-        <Component class="javax.swing.JSlider" name="significantPointSlider">
-          <Properties>
-            <Property name="majorTickSpacing" type="int" value="100"/>
-            <Property name="maximum" type="int" value="300"/>
-            <Property name="snapToTicks" type="boolean" value="true"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-        </Component>
-        <Component class="javax.swing.JLabel" name="minCurvatio4">
-          <Properties>
-            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
-              <Font name="Arial" size="14" style="1"/>
-            </Property>
-            <Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="69" green="72" red="14" type="rgb"/>
-            </Property>
-            <Property name="text" type="java.lang.String" value="Normal Angle Cosine"/>
-          </Properties>
-        </Component>
-        <Component class="javax.swing.JSlider" name="relativeDistanceSlider">
-          <Properties>
-            <Property name="maximum" type="int" value="5"/>
-            <Property name="snapToTicks" type="boolean" value="true"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-        </Component>
-        <Component class="javax.swing.JLabel" name="significantPointLabel">
-          <Properties>
-            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
-              <Font name="Arial" size="14" style="1"/>
-            </Property>
-            <Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="69" green="72" red="14" type="rgb"/>
-            </Property>
-            <Property name="text" type="java.lang.String" value="Significant Points"/>
-          </Properties>
-        </Component>
-        <Component class="javax.swing.JLabel" name="symetryButton">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/symetryCount.png"/>
-            </Property>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseMoved" listener="java.awt.event.MouseMotionListener" parameters="java.awt.event.MouseEvent" handler="symetryButtonMouseMoved"/>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="symetryButtonMouseClicked"/>
-            <EventHandler event="mouseExited" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="symetryButtonMouseExited"/>
-          </Events>
-        </Component>
-        <Component class="javax.swing.JCheckBox" name="averagingCheckBox">
-          <Properties>
-            <Property name="selected" type="boolean" value="true"/>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="averagingCheckBoxMouseClicked"/>
-          </Events>
-        </Component>
-        <Component class="javax.swing.JTextField" name="textFieldCurvature">
-          <Properties>
-            <Property name="text" type="java.lang.String" value="0.5"/>
-            <Property name="toolTipText" type="java.lang.String" value=""/>
-          </Properties>
-        </Component>
-        <Component class="javax.swing.JTextField" name="textFieldMinCos">
-          <Properties>
-            <Property name="text" type="java.lang.String" value="0.985"/>
-            <Property name="toolTipText" type="java.lang.String" value=""/>
-          </Properties>
-        </Component>
-        <Component class="javax.swing.JTextField" name="normalTextField">
-          <Properties>
-            <Property name="text" type="java.lang.String" value="0.985"/>
-            <Property name="toolTipText" type="java.lang.String" value=""/>
-          </Properties>
-        </Component>
-        <Component class="javax.swing.JTextField" name="distanceTextField">
-          <Properties>
-            <Property name="text" type="java.lang.String" value="0.01"/>
-            <Property name="toolTipText" type="java.lang.String" value=""/>
-          </Properties>
-        </Component>
-        <Component class="javax.swing.JTextField" name="significantTextField">
-          <Properties>
-            <Property name="text" type="java.lang.String" value="200"/>
-            <Property name="toolTipText" type="java.lang.String" value=""/>
-          </Properties>
-        </Component>
-        <Component class="javax.swing.JLabel" name="minCurvatio8">
-          <Properties>
-            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
-              <Font name="Arial" size="14" style="1"/>
-            </Property>
-            <Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="69" green="72" red="14" type="rgb"/>
-            </Property>
-            <Property name="text" type="java.lang.String" value="Averaging"/>
-            <Property name="toolTipText" type="java.lang.String" value="Average planes with highest number of votes"/>
-          </Properties>
-        </Component>
-        <Component class="javax.swing.JLabel" name="jLabel1">
-        </Component>
-        <Component class="javax.swing.JLabel" name="originalModelButton">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/originalModel.png"/>
-            </Property>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseMoved" listener="java.awt.event.MouseMotionListener" parameters="java.awt.event.MouseEvent" handler="originalModelButtonMouseMoved"/>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="originalModelButtonMouseClicked"/>
-            <EventHandler event="mouseExited" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="originalModelButtonMouseExited"/>
-          </Events>
-        </Component>
-        <Component class="javax.swing.JLabel" name="showPlaneLabel">
-          <Properties>
-            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
-              <Font name="Arial" size="16" style="1"/>
-            </Property>
-            <Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="69" green="72" red="14" type="rgb"/>
-            </Property>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/show2.png"/>
-            </Property>
-            <Property name="text" type="java.lang.String" value="Show plane"/>
-            <Property name="toolTipText" type="java.lang.String" value="Show approximate plane of symmetry"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-            <Property name="doubleBuffered" type="boolean" value="true"/>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="showPlaneLabelMouseClicked"/>
-          </Events>
-        </Component>
-        <Component class="javax.swing.JLabel" name="defaultValues">
-          <Properties>
-            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
-              <Font name="Arial" size="14" style="0"/>
-            </Property>
-            <Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="69" green="72" red="14" type="rgb"/>
-            </Property>
-            <Property name="text" type="java.lang.String" value="Default values"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="defaultValuesMouseClicked"/>
-          </Events>
-        </Component>
-        <Component class="javax.swing.JLabel" name="infoPoints">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/info.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Info "/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="infoPointsMouseClicked"/>
-          </Events>
-        </Component>
-        <Component class="javax.swing.JLabel" name="infoMinAngleCos">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/info.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Info "/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="infoMinAngleCosMouseClicked"/>
-          </Events>
-        </Component>
-        <Component class="javax.swing.JLabel" name="infoRelDist">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/info.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Info "/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="infoRelDistMouseClicked"/>
-          </Events>
-        </Component>
-        <Component class="javax.swing.JLabel" name="infoNormalAngle">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/info.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Info "/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="infoNormalAngleMouseClicked"/>
-          </Events>
-        </Component>
-        <Component class="javax.swing.JLabel" name="infoMinCurv">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/info.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Info "/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="infoMinCurvMouseClicked"/>
-          </Events>
-        </Component>
-      </SubComponents>
-    </Container>
-  </SubComponents>
-</Form>
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/SymmetryPanel.java b/GUI/src/main/java/cz/fidentis/analyst/gui/SymmetryPanel.java
deleted file mode 100644
index af8c975bae39086c5cdac07282e2bd6aa850a9c7..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/SymmetryPanel.java
+++ /dev/null
@@ -1,727 +0,0 @@
-package cz.fidentis.analyst.gui;
-
-import static cz.fidentis.analyst.gui.UserInterface.frameMain;
-import cz.fidentis.analyst.mesh.core.MeshFacet;
-import cz.fidentis.analyst.mesh.core.MeshModel;
-import cz.fidentis.analyst.symmetry.Config;
-import cz.fidentis.analyst.symmetry.Plane;
-import cz.fidentis.analyst.symmetry.SignificantPoints;
-import cz.fidentis.analyst.symmetry.SymmetryEstimator;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.swing.ImageIcon;
-import javax.swing.JOptionPane;
-import javax.swing.JSlider;
-import javax.swing.JTextField;
-import javax.swing.event.ChangeEvent;
-
-/**
- * Panel for estimating approximate symmetry of the model
- *
- * @author Natalia Bebjakova
- */
-public final class SymmetryPanel extends javax.swing.JPanel {
-    
-    /**
-     * Configuration with optional parameters of the algorithm 
-     */
-    private Config config;
-    
-    /**
-     * GL Canvas on which model is displayed
-     */
-    private Canvas canvas;
-    
-    /**
-     * Computed approximate plane of the symmetry
-     */
-    private Plane symmetryPlane;
-
-    /**
-     * 
-     * @return GL canvas for displaying the model
-     */
-    public Canvas getCanvas() {
-        return canvas;
-    }
-
-    /**
-     * Sets canvas for displaying the model
-     * 
-     * @param canvas GL Canvas
-     */
-    public void setCanvas(Canvas canvas) {
-        this.canvas = canvas;
-    }
-
-    /**
-     * 
-     * @return Configuration for computing symmetry
-     */
-    public Config getConfig() {
-        return config;
-    }
-
-    /**
-     * 
-     * @param config Configuration for computing symmetry
-     */
-    public void setConfig(Config config) {
-        this.config = config;
-    }
-    
-        
-    /**
-     * Sets configuration values according to text fields on panel
-     * User can change this text fields
-     */
-    public void setConfigParams() {
-        config.setMaxRelDistance(Double.parseDouble(distanceTextField.getText()));
-        config.setMinAngleCos(Double.parseDouble(textFieldMinCos.getText()));
-        config.setMinCurvRatio(Double.parseDouble(textFieldCurvature.getText()));
-        config.setMinNormAngleCos(Double.parseDouble(normalTextField.getText()));
-        config.setSignificantPointCount(Integer.parseInt(significantTextField.getText()));
-    }
-    
-    /**
-     * Sets values in text field according to configuration
-     */
-    public void setTextFieldsDueToConfig() {
-        distanceTextField.setText(Double.toString(config.getMaxRelDistance()));
-        textFieldMinCos.setText(Double.toString(config.getMinAngleCos()));
-        textFieldCurvature.setText(Double.toString(config.getMinCurvRatio()));
-        normalTextField.setText(Double.toString(config.getMinNormAngleCos()));
-        significantTextField.setText(Integer.toString(config.getSignificantPointCount()));    
-    }
-    
-    /**
-     * 
-     * @param slider Slider 
-     * @param field text field which belongs to slider
-     */
-    public void setSlider(JSlider slider, JTextField field) {
-        slider.setValue((int) (Double.parseDouble(field.getText()) * 100));
-        
-        slider.addChangeListener((ChangeEvent ce) -> {
-            field.setText(""+slider.getValue()/100.0);
-            defaultValues.setVisible(true);
-        });
-        
-    }
-    
-    /**
-     * Sets values of the sliders according to textFields 
-     */
-    public void setSliders() {
-        setSlider(relativeDistanceSlider, distanceTextField);
-        setSlider(curavatureSlider, textFieldCurvature);
-        setSlider(angleCosineSlider, textFieldMinCos);
-        setSlider(normalAngleSlider, normalTextField);
-                
-        significantPointSlider.setValue((int) (Double.parseDouble(significantTextField.getText())));
-        significantPointSlider.addChangeListener((ChangeEvent ce) -> {
-            significantTextField.setText("" + significantPointSlider.getValue());
-        });
-    }
-    
-    /**
-     * If plane of symmtery is computed, three new buttons are shown on panel
-     * 
-     * @param isComputed true if plane is computed and shown on model otherwise false
-     */
-    public void showPlaneButtonsOnPanel(boolean isComputed) {
-        originalModelButton.setVisible(isComputed);
-        showPlaneLabel.setVisible(isComputed);
-    }
-    
-    /**
-     * Creates new form symmetryPanel
-     */
-    public SymmetryPanel() {
-        initComponents();
-        config = Config.getDefault();
-        setSliders();
-        
-        showPlaneButtonsOnPanel(false);
-    }
-
-    /**
-     * Calculate approxy symmetry of the model 
-     * Accuracy of the symmetry plane is influenced by configuration represented by config
-     * 
-     * @throws InterruptedException exception can be thrown beacause of progress monitor
-     */
-    private void computeSymmetryPlane() throws InterruptedException {
-        MeshModel model = new MeshModel();
-        canvas.changeModel(canvas.getLoadedFace().getMeshModel());
-        SymmetryEstimator est = new SymmetryEstimator(config, SignificantPoints.CurvatureAlg.GAUSSIAN); // MISTO TRUE MUSI BYT VYBER STRATEGIE VYPOCTU ZAKRIVENI!!!
-        canvas.getLoadedFace().getMeshModel().getFacets().get(0).accept(est);
-        symmetryPlane = est.getSymmetryPlane();
-        MeshFacet facet = est.getSymmetryPlaneMesh();
-        if (facet != null) {
-            model.addFacet(facet);
-            this.canvas.changeModel(model);
-        }
-    }
-
-
-    /**
-     * This method is called from within the constructor to initialize the form.
-     * WARNING: Do NOT modify this code. The content of this method is always
-     * regenerated by the Form Editor.
-     * 
-     * Code generated by NetBeans
-     */
-    @SuppressWarnings("unchecked")
-    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
-    private void initComponents() {
-
-        symetrySpecificationPanel = new javax.swing.JPanel();
-        curavatureSlider = new javax.swing.JSlider();
-        angleCosineSlider = new javax.swing.JSlider();
-        minCurvatio = new javax.swing.JLabel();
-        minCurvatio2 = new javax.swing.JLabel();
-        normalAngleSlider = new javax.swing.JSlider();
-        minCurvatio3 = new javax.swing.JLabel();
-        significantPointSlider = new javax.swing.JSlider();
-        minCurvatio4 = new javax.swing.JLabel();
-        relativeDistanceSlider = new javax.swing.JSlider();
-        significantPointLabel = new javax.swing.JLabel();
-        symetryButton = new javax.swing.JLabel();
-        averagingCheckBox = new javax.swing.JCheckBox();
-        textFieldCurvature = new javax.swing.JTextField();
-        textFieldMinCos = new javax.swing.JTextField();
-        normalTextField = new javax.swing.JTextField();
-        distanceTextField = new javax.swing.JTextField();
-        significantTextField = new javax.swing.JTextField();
-        minCurvatio8 = new javax.swing.JLabel();
-        jLabel1 = new javax.swing.JLabel();
-        originalModelButton = new javax.swing.JLabel();
-        showPlaneLabel = new javax.swing.JLabel();
-        defaultValues = new javax.swing.JLabel();
-        infoPoints = new javax.swing.JLabel();
-        infoMinAngleCos = new javax.swing.JLabel();
-        infoRelDist = new javax.swing.JLabel();
-        infoNormalAngle = new javax.swing.JLabel();
-        infoMinCurv = new javax.swing.JLabel();
-
-        symetrySpecificationPanel.setBackground(new java.awt.Color(176, 230, 226));
-
-        curavatureSlider.setBackground(new java.awt.Color(250, 250, 250));
-        curavatureSlider.setMajorTickSpacing(1);
-        curavatureSlider.setMinimum(50);
-        curavatureSlider.setSnapToTicks(true);
-        curavatureSlider.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        curavatureSlider.setOpaque(false);
-
-        angleCosineSlider.setMinimum(80);
-        angleCosineSlider.setSnapToTicks(true);
-        angleCosineSlider.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        angleCosineSlider.setOpaque(false);
-
-        minCurvatio.setFont(new java.awt.Font("Arial", 1, 14)); // NOI18N
-        minCurvatio.setForeground(new java.awt.Color(20, 114, 105));
-        minCurvatio.setText("Min. Curvature Ratio");
-
-        minCurvatio2.setFont(new java.awt.Font("Arial", 1, 14)); // NOI18N
-        minCurvatio2.setForeground(new java.awt.Color(20, 114, 105));
-        minCurvatio2.setText("Min. Angle Cosine");
-
-        normalAngleSlider.setMinimum(80);
-        normalAngleSlider.setSnapToTicks(true);
-        normalAngleSlider.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        normalAngleSlider.setOpaque(false);
-
-        minCurvatio3.setFont(new java.awt.Font("Arial", 1, 14)); // NOI18N
-        minCurvatio3.setForeground(new java.awt.Color(20, 114, 105));
-        minCurvatio3.setText("Relative Distance");
-
-        significantPointSlider.setMajorTickSpacing(100);
-        significantPointSlider.setMaximum(300);
-        significantPointSlider.setSnapToTicks(true);
-        significantPointSlider.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        significantPointSlider.setOpaque(false);
-
-        minCurvatio4.setFont(new java.awt.Font("Arial", 1, 14)); // NOI18N
-        minCurvatio4.setForeground(new java.awt.Color(20, 114, 105));
-        minCurvatio4.setText("Normal Angle Cosine");
-
-        relativeDistanceSlider.setMaximum(5);
-        relativeDistanceSlider.setSnapToTicks(true);
-        relativeDistanceSlider.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        relativeDistanceSlider.setOpaque(false);
-
-        significantPointLabel.setFont(new java.awt.Font("Arial", 1, 14)); // NOI18N
-        significantPointLabel.setForeground(new java.awt.Color(20, 114, 105));
-        significantPointLabel.setText("Significant Points");
-
-        symetryButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/symetryCount.png"))); // NOI18N
-        symetryButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        symetryButton.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
-            public void mouseMoved(java.awt.event.MouseEvent evt) {
-                symetryButtonMouseMoved(evt);
-            }
-        });
-        symetryButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                symetryButtonMouseClicked(evt);
-            }
-            public void mouseExited(java.awt.event.MouseEvent evt) {
-                symetryButtonMouseExited(evt);
-            }
-        });
-
-        averagingCheckBox.setSelected(true);
-        averagingCheckBox.setOpaque(false);
-        averagingCheckBox.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                averagingCheckBoxMouseClicked(evt);
-            }
-        });
-
-        textFieldCurvature.setText("0.5");
-        textFieldCurvature.setToolTipText("");
-
-        textFieldMinCos.setText("0.985");
-        textFieldMinCos.setToolTipText("");
-
-        normalTextField.setText("0.985");
-        normalTextField.setToolTipText("");
-
-        distanceTextField.setText("0.01");
-        distanceTextField.setToolTipText("");
-
-        significantTextField.setText("200");
-        significantTextField.setToolTipText("");
-
-        minCurvatio8.setFont(new java.awt.Font("Arial", 1, 14)); // NOI18N
-        minCurvatio8.setForeground(new java.awt.Color(20, 114, 105));
-        minCurvatio8.setText("Averaging");
-        minCurvatio8.setToolTipText("Average planes with highest number of votes");
-
-        originalModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/originalModel.png"))); // NOI18N
-        originalModelButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        originalModelButton.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
-            public void mouseMoved(java.awt.event.MouseEvent evt) {
-                originalModelButtonMouseMoved(evt);
-            }
-        });
-        originalModelButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                originalModelButtonMouseClicked(evt);
-            }
-            public void mouseExited(java.awt.event.MouseEvent evt) {
-                originalModelButtonMouseExited(evt);
-            }
-        });
-
-        showPlaneLabel.setFont(new java.awt.Font("Arial", 1, 16)); // NOI18N
-        showPlaneLabel.setForeground(new java.awt.Color(20, 114, 105));
-        showPlaneLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/show2.png"))); // NOI18N
-        showPlaneLabel.setText("Show plane");
-        showPlaneLabel.setToolTipText("Show approximate plane of symmetry");
-        showPlaneLabel.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        showPlaneLabel.setDoubleBuffered(true);
-        showPlaneLabel.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                showPlaneLabelMouseClicked(evt);
-            }
-        });
-
-        defaultValues.setFont(new java.awt.Font("Arial", 0, 14)); // NOI18N
-        defaultValues.setForeground(new java.awt.Color(20, 114, 105));
-        defaultValues.setText("Default values");
-        defaultValues.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        defaultValues.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                defaultValuesMouseClicked(evt);
-            }
-        });
-
-        infoPoints.setIcon(new javax.swing.ImageIcon(getClass().getResource("/info.png"))); // NOI18N
-        infoPoints.setToolTipText("Info ");
-        infoPoints.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        infoPoints.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                infoPointsMouseClicked(evt);
-            }
-        });
-
-        infoMinAngleCos.setIcon(new javax.swing.ImageIcon(getClass().getResource("/info.png"))); // NOI18N
-        infoMinAngleCos.setToolTipText("Info ");
-        infoMinAngleCos.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        infoMinAngleCos.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                infoMinAngleCosMouseClicked(evt);
-            }
-        });
-
-        infoRelDist.setIcon(new javax.swing.ImageIcon(getClass().getResource("/info.png"))); // NOI18N
-        infoRelDist.setToolTipText("Info ");
-        infoRelDist.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        infoRelDist.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                infoRelDistMouseClicked(evt);
-            }
-        });
-
-        infoNormalAngle.setIcon(new javax.swing.ImageIcon(getClass().getResource("/info.png"))); // NOI18N
-        infoNormalAngle.setToolTipText("Info ");
-        infoNormalAngle.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        infoNormalAngle.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                infoNormalAngleMouseClicked(evt);
-            }
-        });
-
-        infoMinCurv.setIcon(new javax.swing.ImageIcon(getClass().getResource("/info.png"))); // NOI18N
-        infoMinCurv.setToolTipText("Info ");
-        infoMinCurv.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        infoMinCurv.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                infoMinCurvMouseClicked(evt);
-            }
-        });
-
-        javax.swing.GroupLayout symetrySpecificationPanelLayout = new javax.swing.GroupLayout(symetrySpecificationPanel);
-        symetrySpecificationPanel.setLayout(symetrySpecificationPanelLayout);
-        symetrySpecificationPanelLayout.setHorizontalGroup(
-            symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
-                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
-                    .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
-                        .addGap(0, 0, Short.MAX_VALUE)
-                        .addComponent(defaultValues))
-                    .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
-                        .addGap(17, 17, 17)
-                        .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                            .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
-                                .addGap(154, 154, 154)
-                                .addComponent(jLabel1))
-                            .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
-                                .addComponent(showPlaneLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 147, javax.swing.GroupLayout.PREFERRED_SIZE)
-                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                                .addComponent(originalModelButton, javax.swing.GroupLayout.PREFERRED_SIZE, 181, javax.swing.GroupLayout.PREFERRED_SIZE))))
-                    .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
-                        .addContainerGap()
-                        .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                            .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
-                                .addGap(10, 10, 10)
-                                .addComponent(minCurvatio8)
-                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
-                                .addComponent(averagingCheckBox)
-                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                                .addComponent(symetryButton))
-                            .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
-                                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                                    .addComponent(infoMinAngleCos)
-                                    .addComponent(infoRelDist)
-                                    .addComponent(infoNormalAngle)
-                                    .addComponent(infoPoints)
-                                    .addComponent(infoMinCurv))
-                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                                    .addComponent(minCurvatio4, javax.swing.GroupLayout.DEFAULT_SIZE, 157, Short.MAX_VALUE)
-                                    .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
-                                        .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                                            .addComponent(minCurvatio)
-                                            .addComponent(minCurvatio3)
-                                            .addComponent(minCurvatio2)
-                                            .addComponent(significantPointLabel))
-                                        .addGap(0, 0, Short.MAX_VALUE)))
-                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
-                                    .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
-                                        .addComponent(curavatureSlider, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
-                                        .addComponent(relativeDistanceSlider, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
-                                        .addComponent(significantPointSlider, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 164, javax.swing.GroupLayout.PREFERRED_SIZE)
-                                        .addComponent(angleCosineSlider, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 164, javax.swing.GroupLayout.PREFERRED_SIZE))
-                                    .addComponent(normalAngleSlider, javax.swing.GroupLayout.PREFERRED_SIZE, 164, javax.swing.GroupLayout.PREFERRED_SIZE))
-                                .addGap(18, 18, 18)
-                                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
-                                    .addComponent(distanceTextField)
-                                    .addComponent(normalTextField)
-                                    .addComponent(significantTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE)
-                                    .addComponent(textFieldCurvature, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE)
-                                    .addComponent(textFieldMinCos, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE))))))
-                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
-        );
-        symetrySpecificationPanelLayout.setVerticalGroup(
-            symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
-                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
-                    .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                        .addComponent(infoPoints)
-                        .addComponent(significantPointLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE))
-                    .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                        .addComponent(significantTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                        .addComponent(significantPointSlider, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)))
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
-                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
-                    .addComponent(minCurvatio, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
-                    .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
-                        .addComponent(textFieldCurvature, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                        .addGap(4, 4, 4))
-                    .addComponent(infoMinCurv)
-                    .addComponent(curavatureSlider, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
-                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                    .addComponent(infoMinAngleCos, javax.swing.GroupLayout.Alignment.TRAILING)
-                    .addComponent(minCurvatio2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
-                    .addComponent(textFieldMinCos, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                    .addComponent(angleCosineSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
-                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                    .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
-                        .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
-                            .addComponent(normalAngleSlider, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                            .addComponent(normalTextField))
-                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
-                        .addComponent(distanceTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
-                    .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
-                        .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                            .addComponent(minCurvatio4, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE)
-                            .addComponent(infoNormalAngle))
-                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                        .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                            .addComponent(infoRelDist, javax.swing.GroupLayout.Alignment.TRAILING)
-                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                                .addComponent(relativeDistanceSlider, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE)
-                                .addComponent(minCurvatio3, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)))
-                        .addGap(13, 13, 13)))
-                .addComponent(defaultValues)
-                .addGap(17, 17, 17)
-                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                    .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
-                        .addComponent(symetryButton, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)
-                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                        .addComponent(originalModelButton)
-                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
-                    .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
-                        .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
-                            .addComponent(averagingCheckBox)
-                            .addComponent(minCurvatio8, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE))
-                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 53, Short.MAX_VALUE)
-                        .addComponent(jLabel1)
-                        .addGap(45, 45, 45)
-                        .addComponent(showPlaneLabel)
-                        .addContainerGap(27, Short.MAX_VALUE))))
-        );
-
-        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
-        this.setLayout(layout);
-        layout.setHorizontalGroup(
-            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addComponent(symetrySpecificationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-        );
-        layout.setVerticalGroup(
-            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addComponent(symetrySpecificationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-        );
-    }// </editor-fold>//GEN-END:initComponents
-
-    /**
-     * 
-     * @param evt Final computed plane is shown to user
-     */
-    private void showPlaneLabelMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_showPlaneLabelMouseClicked
-        JOptionPane.showMessageDialog(frameMain, "Approximate plane of symmetry:  \n" + symmetryPlane.getNormal().x + "\n" + symmetryPlane.getNormal().y + "\n" + symmetryPlane.getNormal().z + "\n" +
-            symmetryPlane.getDistance() + "\n", "Final plane.", 0, new ImageIcon(getClass().getResource("/showPlanePane.png")));
-    }//GEN-LAST:event_showPlaneLabelMouseClicked
-
-    /**
-     * 
-     * @param evt Changes button
-     */
-    private void originalModelButtonMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_originalModelButtonMouseExited
-        originalModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/originalModel.png")));
-    }//GEN-LAST:event_originalModelButtonMouseExited
-
-    /**
-     * 
-     * @param evt Original model (without plane) is displayed
-     */
-    private void originalModelButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_originalModelButtonMouseClicked
-        canvas.changeModel(canvas.getLoadedFace().getMeshModel());
-        showPlaneButtonsOnPanel(false);
-    }//GEN-LAST:event_originalModelButtonMouseClicked
-
-    /**
-     * 
-     * @param evt Changes button
-     */
-    private void originalModelButtonMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_originalModelButtonMouseMoved
-        originalModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/originalModelPressed.png")));
-    }//GEN-LAST:event_originalModelButtonMouseMoved
-
-    /**
-     * 
-     * @param evt Decides if averaging is ON or OFF
-     */
-    private void averagingCheckBoxMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_averagingCheckBoxMouseClicked
-        if(config.isAveraging()) {
-            config.setAveraging(false);
-        } else {
-            config.setAveraging(true);
-        }
-    }//GEN-LAST:event_averagingCheckBoxMouseClicked
-
-    /**
-     * 
-     * @param evt Changes button
-     */
-    private void symetryButtonMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_symetryButtonMouseExited
-        symetryButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/symetryCount.png")));
-    }//GEN-LAST:event_symetryButtonMouseExited
-
-    /**
-     * 
-     * @param evt Symmetry is estimated. If model is not loaded, user is warned 
-     */
-    private void symetryButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_symetryButtonMouseClicked
-        setConfigParams();
-        if (canvas.getModel().getFacets().isEmpty()){
-            JOptionPane.showMessageDialog(frameMain, "You have to load the model.", "Model not loaded",
-                0, new ImageIcon(getClass().getResource("/notLoadedModel.png")));
-        } else {
-            try {
-                computeSymmetryPlane();
-            } catch (InterruptedException ex) {
-                Logger.getLogger(SymmetryPanel.class.getName()).log(Level.SEVERE, null, ex);
-            }
-            showPlaneButtonsOnPanel(true);
-        }
-    }//GEN-LAST:event_symetryButtonMouseClicked
-
-    /**
-    * 
-    * @param evt Changes button
-    */
-    private void symetryButtonMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_symetryButtonMouseMoved
-        symetryButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/symetryCountClicked.png")));
-    }//GEN-LAST:event_symetryButtonMouseMoved
-
-    /**
-     * 
-     * @param evt configuration is set to deafult values
-     */
-    private void defaultValuesMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_defaultValuesMouseClicked
-        config = Config.getDefault();
-        setTextFieldsDueToConfig();
-        setSliders();
-    }//GEN-LAST:event_defaultValuesMouseClicked
-
-    /**
-     * Shows details about minimum curv ratio parameter
-     * 
-     * @param evt 
-     */
-    private void infoMinCurvMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_infoMinCurvMouseClicked
-        JOptionPane.showMessageDialog(frameMain,
-                "Entered number represents how similar the curvature in two vertices must be\n"
-                        + "to take into account these vertices while counting the plane of approximate symmetry.\n"
-                        + "The higher the number is the more similar they must be.\n\n"
-                        
-                        + "Higher number → fewer pairs of vertices satisfy the criterion → shorter calculation, possibly less accurate result.\n"
-                        + "Lower number → more pairs of vertices satisfy the criterion → longer calculation, possibly more accurate result.",
-                "Minimum curvature ratio",
-                0, new ImageIcon(getClass().getResource("/curvature.png")));
-    }//GEN-LAST:event_infoMinCurvMouseClicked
-
-    /**
-     * Shows details about maximum relative distance parameter
-     * 
-     * @param evt 
-    */
-    private void infoRelDistMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_infoRelDistMouseClicked
-        JOptionPane.showMessageDialog(frameMain,
-                "Entered number represents how far middle point of two vertices can be from candidate plane of symmetry\n"
-                        + "to give this plane vote. Plane with highest number of votes is plane of approximate symmetry.\n\n"
-                        
-                        + "Higher number → more pairs of vertices satisfy the criterion → longer calculation, possibly more accurate result.\n"
-                        + "Lower number → fewer pairs of vertices satisfy the criterion → shorter calculation, possibly less accurate result.",
-                "Maximum relative distance from plane",
-                0, new ImageIcon(getClass().getResource("/distance.png")));
-    }//GEN-LAST:event_infoRelDistMouseClicked
-
-    /**
-     * Shows details about significant points parameter
-     * 
-     * @param evt 
-     */
-    private void infoPointsMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_infoPointsMouseClicked
-        JOptionPane.showMessageDialog(frameMain, 
-                "Entered number represents amount of points of the mesh that are taken into account\n"
-                        + "while counting the plane of approximate symmetry.\n\n"
-                        
-                        + "Higher number → longer calculation, possibly more accurate result.\n"
-                        + "Lower number → shorter calculation, possibly less accurate result.", 
-                "Significant points",
-                0, new ImageIcon(getClass().getResource("/points.png")));
-    }//GEN-LAST:event_infoPointsMouseClicked
-
-    /**
-     * Shows details about minimum angle cosine parameter
-     * 
-     * @param evt 
-     */
-    private void infoMinAngleCosMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_infoMinAngleCosMouseClicked
-        JOptionPane.showMessageDialog(frameMain,
-                "Entered number represents how large the angle between normal vector of candidate plane and the vector\n"
-                        + "of two vertices can be to take into account these vertices while counting the approximate symmetry.\n\n"
-                        
-                        + "Higher number → fewer pairs of vertices satisfy the criterion → shorter calculation, possibly less accurate result.\n"
-                        + "Lower number → more pairs of vertices satisfy the criterion → longer calculation, possibly more accurate result.",
-                "Minimum angle",
-                0, new ImageIcon(getClass().getResource("/angle.png")));
-    }//GEN-LAST:event_infoMinAngleCosMouseClicked
-
-    /**
-     * Shows details about minimum normal angle cosine parameter
-     * 
-     * @param evt 
-     */
-    private void infoNormalAngleMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_infoNormalAngleMouseClicked
-        JOptionPane.showMessageDialog(frameMain,
-                "Entered number represents how large the angle between normal vector of candidate plane and vector\n"
-                        + "from subtraction of normal vectors of two vertices can be to take into account these vertices while counting the approximate symmetry.\n\n"
-                        
-                        + "Higher number → fewer pairs of vertices satisfy the criterion → shorter calculation, possibly less accurate result.\n"
-                        + "Lower number → more pairs of vertices satisfy the criterion → longer calculation, possibly more accurate result.",
-                "Minimum normal angle",
-                0, new ImageIcon(getClass().getResource("/angle.png")));
-    }//GEN-LAST:event_infoNormalAngleMouseClicked
-
-
-    // Variables declaration - do not modify//GEN-BEGIN:variables
-    private javax.swing.JSlider angleCosineSlider;
-    private javax.swing.JCheckBox averagingCheckBox;
-    private javax.swing.JSlider curavatureSlider;
-    private javax.swing.JLabel defaultValues;
-    private javax.swing.JTextField distanceTextField;
-    private javax.swing.JLabel infoMinAngleCos;
-    private javax.swing.JLabel infoMinCurv;
-    private javax.swing.JLabel infoNormalAngle;
-    private javax.swing.JLabel infoPoints;
-    private javax.swing.JLabel infoRelDist;
-    private javax.swing.JLabel jLabel1;
-    private javax.swing.JLabel minCurvatio;
-    private javax.swing.JLabel minCurvatio2;
-    private javax.swing.JLabel minCurvatio3;
-    private javax.swing.JLabel minCurvatio4;
-    private javax.swing.JLabel minCurvatio8;
-    private javax.swing.JSlider normalAngleSlider;
-    private javax.swing.JTextField normalTextField;
-    private javax.swing.JLabel originalModelButton;
-    private javax.swing.JSlider relativeDistanceSlider;
-    private javax.swing.JLabel showPlaneLabel;
-    private javax.swing.JLabel significantPointLabel;
-    private javax.swing.JSlider significantPointSlider;
-    private javax.swing.JTextField significantTextField;
-    private javax.swing.JLabel symetryButton;
-    private javax.swing.JPanel symetrySpecificationPanel;
-    private javax.swing.JTextField textFieldCurvature;
-    private javax.swing.JTextField textFieldMinCos;
-    // End of variables declaration//GEN-END:variables
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/TestInterface.java b/GUI/src/main/java/cz/fidentis/analyst/gui/TestInterface.java
deleted file mode 100644
index 1d67ec08a6aee2dd6775cba7e0cd4c1e5f433e18..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/TestInterface.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package cz.fidentis.analyst.gui;
-
-import cz.fidentis.analyst.face.HumanFace;
-import cz.fidentis.analyst.mesh.io.ModelFileFilter;
-
-import javax.swing.*;
-import java.awt.*;
-import java.io.File;
-import java.io.IOException;
-
-/**
- * @author Daniel Sokol
- * <p>
- * Temporary interface to test rendering heatmap.
- */
-
-
-public class TestInterface {
-    private static final JFrame testFrame = new JFrame();
-    private static HumanFace comparedModel;
-
-    public static void main(String[] args) {
-
-        JButton addButton = new JButton("Load face to compare");
-        JButton compareButton = new JButton("Show differences");
-
-        Canvas testCanvas = new Canvas();
-        ComparisonGLEventListener colorListener = new ComparisonGLEventListener(testCanvas);
-        testCanvas.setListener(colorListener);
-        JColorChooser colorChooserMin = new JColorChooser(Color.BLUE);
-        JColorChooser colorChooserMax = new JColorChooser(Color.RED);
-
-        JButton color1 = new JButton("Pick color for smallest distances");
-        JFrame colorMinFrame = new JFrame();
-        colorMinFrame.add(colorChooserMin);
-        colorMinFrame.pack();
-
-        JButton color2 = new JButton("Pick color for largest distances");
-        JFrame colorMaxFrame = new JFrame();
-        colorMaxFrame.add(colorChooserMax);
-        colorMaxFrame.pack();
-
-        addButton.addActionListener(e -> {
-                    try {
-                        JFileChooser jFileChooser1 = new JFileChooser();
-                        jFileChooser1.setPreferredSize(new Dimension(800, 500));
-                        jFileChooser1.addChoosableFileFilter(new ModelFileFilter(new String[]{"obj", "OBJ"}, "*.obj"));
-                        jFileChooser1.showOpenDialog(testFrame);
-                        if (jFileChooser1.getSelectedFile() == null) {
-                            System.out.print("No file chosen.");
-                        } else {
-                            comparedModel = new HumanFace(new File(jFileChooser1.getSelectedFile().getPath()));
-                            colorListener.setComparedFace(comparedModel);
-                            addButton.setBackground(new Color(50, 200, 20));
-
-                        }
-                    } catch (IOException ioException) {
-                        ioException.printStackTrace();
-                    }
-                }
-        );
-
-        compareButton.addActionListener(e -> colorListener.compare(colorChooserMin.getColor(), colorChooserMax.getColor()));
-
-        color1.addActionListener(e -> colorMinFrame.setVisible(true));
-
-        color2.addActionListener(e -> colorMaxFrame.setVisible(true));
-
-        testFrame.setLayout(new GridBagLayout());
-        testFrame.setVisible(true);
-        testFrame.setSize(1200, 700);
-
-        GridBagConstraints c = new GridBagConstraints();
-        c.fill = GridBagConstraints.BOTH;
-        c.gridx = 0;
-        c.gridy = 0;
-        c.weighty = 1;
-        c.weightx = 1;
-
-        c.gridheight = 6;
-        c.gridwidth = 4;
-        c.weightx = 4;
-        testFrame.add(testCanvas, c);
-        c.gridheight = 1;
-        c.gridwidth = 2;
-        c.gridx = 4;
-        c.weightx = 2;
-        testFrame.add(addButton, c);
-        c.gridy = 1;
-        testFrame.add(compareButton, c);
-        c.gridy = 2;
-        c.gridwidth = 1;
-        c.weightx = 1;
-        testFrame.add(color1, c);
-        c.gridx = 5;
-        testFrame.add(color2, c);
-
-    }
-}
-
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/UserInterface.form b/GUI/src/main/java/cz/fidentis/analyst/gui/UserInterface.form
deleted file mode 100644
index 32e21d509eecc227098c5c444f58235a3bf4cc9a..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/UserInterface.form
+++ /dev/null
@@ -1,956 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
-  <Properties>
-    <Property name="defaultCloseOperation" type="int" value="3"/>
-    <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-      <Color blue="a3" green="ae" red="0" type="rgb"/>
-    </Property>
-    <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-      <Color id="Default Cursor"/>
-    </Property>
-    <Property name="locationByPlatform" type="boolean" value="true"/>
-  </Properties>
-  <SyntheticProperties>
-    <SyntheticProperty name="formSizePolicy" type="int" value="1"/>
-    <SyntheticProperty name="generateCenter" type="boolean" value="true"/>
-  </SyntheticProperties>
-  <AuxValues>
-    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
-    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
-    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
-    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
-    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
-  </AuxValues>
-
-  <Layout>
-    <DimensionLayout dim="0">
-      <Group type="103" groupAlignment="0" attributes="0">
-          <Component id="topPanel" max="32767" attributes="0"/>
-          <Component id="jPanel1" alignment="1" max="32767" attributes="0"/>
-          <Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
-              <Component id="jPanel2" alignment="0" max="32767" attributes="0"/>
-          </Group>
-      </Group>
-    </DimensionLayout>
-    <DimensionLayout dim="1">
-      <Group type="103" groupAlignment="0" attributes="0">
-          <Group type="102" alignment="0" attributes="0">
-              <Component id="jPanel1" min="-2" pref="52" max="-2" attributes="0"/>
-              <EmptySpace type="unrelated" max="-2" attributes="0"/>
-              <Component id="topPanel" min="-2" pref="239" max="-2" attributes="0"/>
-              <EmptySpace min="0" pref="565" max="32767" attributes="0"/>
-          </Group>
-          <Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
-              <Component id="jPanel2" alignment="1" max="32767" attributes="0"/>
-          </Group>
-      </Group>
-    </DimensionLayout>
-  </Layout>
-  <SubComponents>
-    <Container class="javax.swing.JPanel" name="jPanel1">
-      <Properties>
-        <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-          <Color blue="69" green="72" red="14" type="rgb"/>
-        </Property>
-        <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-          <Dimension value="[1200, 77]"/>
-        </Property>
-      </Properties>
-      <Events>
-        <EventHandler event="mouseDragged" listener="java.awt.event.MouseMotionListener" parameters="java.awt.event.MouseEvent" handler="jPanel1MouseDragged"/>
-        <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="jPanel1MousePressed"/>
-      </Events>
-
-      <Layout>
-        <DimensionLayout dim="0">
-          <Group type="103" groupAlignment="0" attributes="0">
-              <Group type="102" alignment="0" attributes="0">
-                  <EmptySpace max="-2" attributes="0"/>
-                  <Component id="homeButton" min="-2" max="-2" attributes="0"/>
-                  <EmptySpace max="-2" attributes="0"/>
-                  <Component id="newProject" min="-2" pref="149" max="-2" attributes="0"/>
-                  <EmptySpace max="-2" attributes="0"/>
-                  <Component id="wiredModelButton" min="-2" pref="134" max="-2" attributes="0"/>
-                  <EmptySpace max="32767" attributes="0"/>
-              </Group>
-          </Group>
-        </DimensionLayout>
-        <DimensionLayout dim="1">
-          <Group type="103" groupAlignment="0" attributes="0">
-              <Component id="wiredModelButton" alignment="0" max="32767" attributes="0"/>
-              <Component id="newProject" max="32767" attributes="0"/>
-              <Component id="homeButton" alignment="0" pref="52" max="32767" attributes="0"/>
-          </Group>
-        </DimensionLayout>
-      </Layout>
-      <SubComponents>
-        <Component class="javax.swing.JLabel" name="newProject">
-          <Properties>
-            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="69" green="72" red="14" type="rgb"/>
-            </Property>
-            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
-              <Font name="Neue Haas Unica Pro" size="18" style="0"/>
-            </Property>
-            <Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="ff" green="ff" red="ff" type="rgb"/>
-            </Property>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/newP.png"/>
-            </Property>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-            <Property name="opaque" type="boolean" value="true"/>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseMoved" listener="java.awt.event.MouseMotionListener" parameters="java.awt.event.MouseEvent" handler="newProjectMouseMoved"/>
-            <EventHandler event="mouseExited" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="newProjectMouseExited"/>
-            <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="newProjectMousePressed"/>
-          </Events>
-        </Component>
-        <Component class="javax.swing.JLabel" name="wiredModelButton">
-          <Properties>
-            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="69" green="72" red="14" type="rgb"/>
-            </Property>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/wireframe2.png"/>
-            </Property>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-            <Property name="opaque" type="boolean" value="true"/>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="wiredModelButtonMouseClicked"/>
-          </Events>
-        </Component>
-        <Component class="javax.swing.JLabel" name="homeButton">
-          <Properties>
-            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="69" green="72" red="14" type="rgb"/>
-            </Property>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/home.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Home"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-            <Property name="opaque" type="boolean" value="true"/>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseMoved" listener="java.awt.event.MouseMotionListener" parameters="java.awt.event.MouseEvent" handler="homeButtonMouseMoved"/>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="homeButtonMouseClicked"/>
-            <EventHandler event="mouseExited" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="homeButtonMouseExited"/>
-          </Events>
-        </Component>
-      </SubComponents>
-    </Container>
-    <Container class="javax.swing.JPanel" name="topPanel">
-      <Properties>
-        <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-          <Color blue="69" green="72" red="14" type="rgb"/>
-        </Property>
-        <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-          <Dimension value="[1200, 266]"/>
-        </Property>
-      </Properties>
-      <AccessibilityProperties>
-        <Property name="AccessibleContext.accessibleName" type="java.lang.String" value=""/>
-      </AccessibilityProperties>
-
-      <Layout>
-        <DimensionLayout dim="0">
-          <Group type="103" groupAlignment="0" attributes="0">
-              <Group type="102" alignment="0" attributes="0">
-                  <EmptySpace pref="99" max="32767" attributes="0"/>
-                  <Component id="compareTwo" min="-2" max="-2" attributes="0"/>
-                  <EmptySpace min="-2" pref="105" max="-2" attributes="0"/>
-                  <Component id="compareDB" min="-2" max="-2" attributes="0"/>
-                  <EmptySpace min="-2" pref="94" max="-2" attributes="0"/>
-                  <Component id="batchProcessing" min="-2" max="-2" attributes="0"/>
-                  <EmptySpace min="-2" pref="94" max="-2" attributes="0"/>
-                  <Component id="symetryEstimator" min="-2" max="-2" attributes="0"/>
-                  <EmptySpace pref="98" max="32767" attributes="0"/>
-              </Group>
-          </Group>
-        </DimensionLayout>
-        <DimensionLayout dim="1">
-          <Group type="103" groupAlignment="0" attributes="0">
-              <Group type="102" attributes="0">
-                  <EmptySpace min="-2" pref="52" max="-2" attributes="0"/>
-                  <Group type="103" groupAlignment="0" attributes="0">
-                      <Component id="symetryEstimator" alignment="1" max="32767" attributes="0"/>
-                      <Component id="compareDB" alignment="1" max="32767" attributes="0"/>
-                      <Group type="102" alignment="1" attributes="0">
-                          <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
-                          <Component id="compareTwo" min="-2" max="-2" attributes="0"/>
-                      </Group>
-                      <Component id="batchProcessing" alignment="1" max="32767" attributes="0"/>
-                  </Group>
-              </Group>
-          </Group>
-        </DimensionLayout>
-      </Layout>
-      <SubComponents>
-        <Container class="javax.swing.JPanel" name="compareTwo">
-          <Properties>
-            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="69" green="72" red="14" type="rgb"/>
-            </Property>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-
-          <Layout>
-            <DimensionLayout dim="0">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <Group type="102" alignment="0" attributes="0">
-                      <EmptySpace max="-2" attributes="0"/>
-                      <Component id="jLabel1" max="32767" attributes="0"/>
-                      <EmptySpace max="-2" attributes="0"/>
-                  </Group>
-              </Group>
-            </DimensionLayout>
-            <DimensionLayout dim="1">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <Group type="102" attributes="0">
-                      <EmptySpace min="-2" pref="30" max="-2" attributes="0"/>
-                      <Component id="jLabel1" max="32767" attributes="0"/>
-                      <EmptySpace min="-2" pref="28" max="-2" attributes="0"/>
-                  </Group>
-              </Group>
-            </DimensionLayout>
-          </Layout>
-          <SubComponents>
-            <Component class="javax.swing.JLabel" name="jLabel1">
-              <Properties>
-                <Property name="horizontalAlignment" type="int" value="0"/>
-                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-                  <Image iconType="3" name="/compareTwoStart.png"/>
-                </Property>
-                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-                  <Color id="Default Cursor"/>
-                </Property>
-              </Properties>
-            </Component>
-          </SubComponents>
-        </Container>
-        <Container class="javax.swing.JPanel" name="compareDB">
-          <Properties>
-            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="69" green="72" red="14" type="rgb"/>
-            </Property>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-
-          <Layout>
-            <DimensionLayout dim="0">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <Component id="jLabel3" alignment="1" max="32767" attributes="0"/>
-              </Group>
-            </DimensionLayout>
-            <DimensionLayout dim="1">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <Component id="jLabel3" alignment="1" max="32767" attributes="0"/>
-              </Group>
-            </DimensionLayout>
-          </Layout>
-          <SubComponents>
-            <Component class="javax.swing.JLabel" name="jLabel3">
-              <Properties>
-                <Property name="horizontalAlignment" type="int" value="0"/>
-                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-                  <Image iconType="3" name="/batchProcessingStart.png"/>
-                </Property>
-                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-                  <Color id="Default Cursor"/>
-                </Property>
-              </Properties>
-            </Component>
-          </SubComponents>
-        </Container>
-        <Container class="javax.swing.JPanel" name="batchProcessing">
-          <Properties>
-            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="69" green="72" red="14" type="rgb"/>
-            </Property>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-
-          <Layout>
-            <DimensionLayout dim="0">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <Group type="102" attributes="0">
-                      <EmptySpace min="-2" pref="26" max="-2" attributes="0"/>
-                      <Component id="jLabel2" max="32767" attributes="0"/>
-                  </Group>
-              </Group>
-            </DimensionLayout>
-            <DimensionLayout dim="1">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <Group type="102" alignment="1" attributes="0">
-                      <EmptySpace max="-2" attributes="0"/>
-                      <Component id="jLabel2" max="32767" attributes="0"/>
-                  </Group>
-              </Group>
-            </DimensionLayout>
-          </Layout>
-          <SubComponents>
-            <Component class="javax.swing.JLabel" name="jLabel2">
-              <Properties>
-                <Property name="horizontalAlignment" type="int" value="0"/>
-                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-                  <Image iconType="3" name="/copareWithDatabaseStart.png"/>
-                </Property>
-                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-                  <Color id="Default Cursor"/>
-                </Property>
-              </Properties>
-            </Component>
-          </SubComponents>
-        </Container>
-        <Container class="javax.swing.JPanel" name="symetryEstimator">
-          <Properties>
-            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="69" green="72" red="14" type="rgb"/>
-            </Property>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="symetryEstimatorMouseClicked"/>
-          </Events>
-
-          <Layout>
-            <DimensionLayout dim="0">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <Group type="102" alignment="1" attributes="0">
-                      <EmptySpace max="-2" attributes="0"/>
-                      <Component id="jLabel4" max="32767" attributes="0"/>
-                      <EmptySpace max="-2" attributes="0"/>
-                  </Group>
-              </Group>
-            </DimensionLayout>
-            <DimensionLayout dim="1">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <Group type="102" alignment="1" attributes="0">
-                      <EmptySpace max="32767" attributes="0"/>
-                      <Component id="jLabel4" min="-2" pref="137" max="-2" attributes="0"/>
-                      <EmptySpace min="-2" pref="36" max="-2" attributes="0"/>
-                  </Group>
-              </Group>
-            </DimensionLayout>
-          </Layout>
-          <SubComponents>
-            <Component class="javax.swing.JLabel" name="jLabel4">
-              <Properties>
-                <Property name="horizontalAlignment" type="int" value="0"/>
-                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-                  <Image iconType="3" name="/symetryStartP.png"/>
-                </Property>
-                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-                  <Color id="Hand Cursor"/>
-                </Property>
-              </Properties>
-              <Events>
-                <EventHandler event="mouseMoved" listener="java.awt.event.MouseMotionListener" parameters="java.awt.event.MouseEvent" handler="jLabel4MouseMoved1"/>
-                <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="jLabel4MouseClicked"/>
-                <EventHandler event="mouseExited" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="jLabel4MouseExited"/>
-              </Events>
-            </Component>
-          </SubComponents>
-        </Container>
-      </SubComponents>
-    </Container>
-    <Container class="javax.swing.JPanel" name="jPanel2">
-      <Properties>
-        <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-          <Color blue="a3" green="ae" red="0" type="rgb"/>
-        </Property>
-        <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
-          <Font name="Arial" size="13" style="1"/>
-        </Property>
-        <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
-          <Connection component="Form" name="preferredSize" type="property"/>
-        </Property>
-      </Properties>
-
-      <Layout class="org.netbeans.modules.form.compat2.layouts.DesignCardLayout"/>
-      <SubComponents>
-        <Container class="javax.swing.JPanel" name="startingPanel">
-          <Properties>
-            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="a3" green="ae" red="0" type="rgb"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value=""/>
-            <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-              <Dimension value="[0, 0]"/>
-            </Property>
-            <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-              <Dimension value="[1200, 800]"/>
-            </Property>
-            <Property name="requestFocusEnabled" type="boolean" value="false"/>
-          </Properties>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
-              <CardConstraints cardName="card3"/>
-            </Constraint>
-          </Constraints>
-
-          <Layout>
-            <DimensionLayout dim="0">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <Group type="102" attributes="0">
-                      <EmptySpace pref="81" max="32767" attributes="0"/>
-                      <Group type="103" groupAlignment="0" attributes="0">
-                          <Component id="jPanel3" min="-2" max="-2" attributes="0"/>
-                          <Group type="102" alignment="1" attributes="0">
-                              <Component id="logo" min="-2" pref="218" max="-2" attributes="0"/>
-                              <EmptySpace min="-2" pref="400" max="-2" attributes="0"/>
-                          </Group>
-                      </Group>
-                      <EmptySpace pref="81" max="32767" attributes="0"/>
-                  </Group>
-              </Group>
-            </DimensionLayout>
-            <DimensionLayout dim="1">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <Group type="102" attributes="0">
-                      <EmptySpace pref="133" max="32767" attributes="0"/>
-                      <Component id="logo" min="-2" pref="124" max="-2" attributes="0"/>
-                      <EmptySpace type="unrelated" max="-2" attributes="0"/>
-                      <Component id="jPanel3" min="-2" max="-2" attributes="0"/>
-                      <EmptySpace pref="136" max="32767" attributes="0"/>
-                  </Group>
-              </Group>
-            </DimensionLayout>
-          </Layout>
-          <SubComponents>
-            <Component class="javax.swing.JLabel" name="logo">
-              <Properties>
-                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-                  <Image iconType="3" name="/logo3.png"/>
-                </Property>
-              </Properties>
-              <AuxValues>
-                <AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
-                <AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
-              </AuxValues>
-            </Component>
-            <Container class="javax.swing.JPanel" name="jPanel3">
-              <Properties>
-                <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-                  <Color blue="a3" green="ae" red="0" type="rgb"/>
-                </Property>
-                <Property name="toolTipText" type="java.lang.String" value=""/>
-              </Properties>
-
-              <Layout>
-                <DimensionLayout dim="0">
-                  <Group type="103" groupAlignment="0" attributes="0">
-                      <Group type="102" alignment="0" attributes="0">
-                          <EmptySpace pref="17" max="32767" attributes="0"/>
-                          <Component id="viewerButton" min="-2" pref="323" max="-2" attributes="0"/>
-                          <EmptySpace type="separate" max="-2" attributes="0"/>
-                          <Group type="103" groupAlignment="0" attributes="0">
-                              <Component id="compareTwoMain" alignment="1" min="-2" max="-2" attributes="0"/>
-                              <Component id="compareTwoMain1" alignment="1" min="-2" max="-2" attributes="0"/>
-                          </Group>
-                          <EmptySpace min="-2" max="-2" attributes="0"/>
-                          <Group type="103" groupAlignment="0" attributes="0">
-                              <Group type="102" attributes="0">
-                                  <Component id="JLabel8" max="32767" attributes="0"/>
-                                  <EmptySpace min="-2" pref="62" max="-2" attributes="0"/>
-                              </Group>
-                              <Group type="102" attributes="0">
-                                  <Component id="JLabel9" min="-2" pref="196" max="-2" attributes="0"/>
-                                  <EmptySpace max="32767" attributes="0"/>
-                              </Group>
-                          </Group>
-                          <Group type="103" groupAlignment="0" attributes="0">
-                              <Component id="batchMain" min="-2" max="-2" attributes="0"/>
-                              <Group type="102" attributes="0">
-                                  <EmptySpace min="12" pref="12" max="-2" attributes="0"/>
-                                  <Component id="symetryMain" min="-2" max="-2" attributes="0"/>
-                              </Group>
-                          </Group>
-                          <EmptySpace pref="42" max="32767" attributes="0"/>
-                      </Group>
-                  </Group>
-                </DimensionLayout>
-                <DimensionLayout dim="1">
-                  <Group type="103" groupAlignment="0" attributes="0">
-                      <Group type="102" attributes="0">
-                          <Group type="103" groupAlignment="0" attributes="0">
-                              <Group type="102" alignment="1" attributes="0">
-                                  <EmptySpace max="-2" attributes="0"/>
-                                  <Group type="103" groupAlignment="1" attributes="0">
-                                      <Group type="103" alignment="1" groupAlignment="0" attributes="0">
-                                          <Component id="JLabel8" min="-2" pref="142" max="-2" attributes="0"/>
-                                          <Component id="compareTwoMain" min="-2" max="-2" attributes="0"/>
-                                      </Group>
-                                      <Group type="102" alignment="1" attributes="0">
-                                          <Component id="batchMain" min="-2" pref="173" max="-2" attributes="0"/>
-                                          <EmptySpace min="-2" pref="28" max="-2" attributes="0"/>
-                                      </Group>
-                                  </Group>
-                                  <Group type="103" groupAlignment="0" attributes="0">
-                                      <Component id="compareTwoMain1" alignment="1" min="-2" max="-2" attributes="0"/>
-                                      <Component id="symetryMain" alignment="1" min="-2" max="-2" attributes="0"/>
-                                  </Group>
-                              </Group>
-                              <Group type="102" alignment="0" attributes="0">
-                                  <EmptySpace min="-2" pref="296" max="-2" attributes="0"/>
-                                  <Component id="JLabel9" max="32767" attributes="0"/>
-                                  <EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
-                              </Group>
-                          </Group>
-                          <EmptySpace max="-2" attributes="0"/>
-                      </Group>
-                      <Group type="102" alignment="1" attributes="0">
-                          <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
-                          <Component id="viewerButton" min="-2" max="-2" attributes="0"/>
-                          <EmptySpace min="-2" pref="41" max="-2" attributes="0"/>
-                      </Group>
-                  </Group>
-                </DimensionLayout>
-              </Layout>
-              <SubComponents>
-                <Container class="javax.swing.JPanel" name="compareTwoMain">
-                  <Properties>
-                    <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-                      <Color blue="a3" green="ae" red="0" type="rgb"/>
-                    </Property>
-                  </Properties>
-
-                  <Layout>
-                    <DimensionLayout dim="0">
-                      <Group type="103" groupAlignment="0" attributes="0">
-                          <EmptySpace min="0" pref="177" max="32767" attributes="0"/>
-                      </Group>
-                    </DimensionLayout>
-                    <DimensionLayout dim="1">
-                      <Group type="103" groupAlignment="0" attributes="0">
-                          <EmptySpace min="0" pref="170" max="32767" attributes="0"/>
-                      </Group>
-                    </DimensionLayout>
-                  </Layout>
-                </Container>
-                <Container class="javax.swing.JPanel" name="compareTwoMain1">
-                  <Properties>
-                    <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-                      <Color blue="a3" green="ae" red="0" type="rgb"/>
-                    </Property>
-                  </Properties>
-
-                  <Layout>
-                    <DimensionLayout dim="0">
-                      <Group type="103" groupAlignment="0" attributes="0">
-                          <EmptySpace min="0" pref="220" max="32767" attributes="0"/>
-                      </Group>
-                    </DimensionLayout>
-                    <DimensionLayout dim="1">
-                      <Group type="103" groupAlignment="0" attributes="0">
-                          <EmptySpace min="0" pref="169" max="32767" attributes="0"/>
-                      </Group>
-                    </DimensionLayout>
-                  </Layout>
-                </Container>
-                <Container class="javax.swing.JPanel" name="batchMain">
-                  <Properties>
-                    <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-                      <Color blue="a3" green="ae" red="0" type="rgb"/>
-                    </Property>
-                  </Properties>
-
-                  <Layout>
-                    <DimensionLayout dim="0">
-                      <Group type="103" groupAlignment="0" attributes="0">
-                          <Group type="102" alignment="0" attributes="0">
-                              <EmptySpace max="-2" attributes="0"/>
-                              <Component id="JLabel10" min="-2" max="-2" attributes="0"/>
-                              <EmptySpace max="32767" attributes="0"/>
-                          </Group>
-                      </Group>
-                    </DimensionLayout>
-                    <DimensionLayout dim="1">
-                      <Group type="103" groupAlignment="0" attributes="0">
-                          <Group type="102" alignment="0" attributes="0">
-                              <EmptySpace min="-2" pref="25" max="-2" attributes="0"/>
-                              <Component id="JLabel10" min="-2" max="-2" attributes="0"/>
-                              <EmptySpace max="32767" attributes="0"/>
-                          </Group>
-                      </Group>
-                    </DimensionLayout>
-                  </Layout>
-                  <SubComponents>
-                    <Component class="javax.swing.JLabel" name="JLabel10">
-                      <Properties>
-                        <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-                          <Image iconType="3" name="/batchProcessingStart.png"/>
-                        </Property>
-                      </Properties>
-                    </Component>
-                  </SubComponents>
-                </Container>
-                <Container class="javax.swing.JPanel" name="symetryMain">
-                  <Properties>
-                    <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-                      <Color blue="a3" green="ae" red="0" type="rgb"/>
-                    </Property>
-                  </Properties>
-
-                  <Layout>
-                    <DimensionLayout dim="0">
-                      <Group type="103" groupAlignment="0" attributes="0">
-                          <Component id="JLabel11" alignment="1" pref="189" max="32767" attributes="0"/>
-                      </Group>
-                    </DimensionLayout>
-                    <DimensionLayout dim="1">
-                      <Group type="103" groupAlignment="0" attributes="0">
-                          <Group type="102" alignment="1" attributes="0">
-                              <EmptySpace min="-2" max="-2" attributes="0"/>
-                              <Component id="JLabel11" pref="167" max="32767" attributes="0"/>
-                          </Group>
-                      </Group>
-                    </DimensionLayout>
-                  </Layout>
-                  <SubComponents>
-                    <Component class="javax.swing.JLabel" name="JLabel11">
-                      <Properties>
-                        <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-                          <Color blue="a3" green="ae" red="0" type="rgb"/>
-                        </Property>
-                        <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-                          <Image iconType="3" name="/symetryStart.png"/>
-                        </Property>
-                        <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-                          <Color id="Hand Cursor"/>
-                        </Property>
-                      </Properties>
-                      <Events>
-                        <EventHandler event="mouseMoved" listener="java.awt.event.MouseMotionListener" parameters="java.awt.event.MouseEvent" handler="JLabel11MouseMoved"/>
-                        <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="JLabel11MouseClicked"/>
-                        <EventHandler event="mouseExited" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="JLabel11MouseExited"/>
-                      </Events>
-                    </Component>
-                  </SubComponents>
-                </Container>
-                <Component class="javax.swing.JLabel" name="viewerButton">
-                  <Properties>
-                    <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-                      <Image iconType="3" name="/modelView.png"/>
-                    </Property>
-                    <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-                      <Color id="Hand Cursor"/>
-                    </Property>
-                  </Properties>
-                  <Events>
-                    <EventHandler event="mouseMoved" listener="java.awt.event.MouseMotionListener" parameters="java.awt.event.MouseEvent" handler="viewerButtonMouseMoved"/>
-                    <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="viewerButtonMouseClicked"/>
-                    <EventHandler event="mouseExited" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="viewerButtonMouseExited"/>
-                  </Events>
-                </Component>
-                <Component class="javax.swing.JLabel" name="JLabel8">
-                  <Properties>
-                    <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-                      <Image iconType="3" name="/compareTwoStart.png"/>
-                    </Property>
-                  </Properties>
-                </Component>
-                <Component class="javax.swing.JLabel" name="JLabel9">
-                  <Properties>
-                    <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-                      <Color blue="a3" green="ae" red="0" type="rgb"/>
-                    </Property>
-                    <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-                      <Image iconType="3" name="/copareWithDatabaseStart.png"/>
-                    </Property>
-                  </Properties>
-                </Component>
-              </SubComponents>
-            </Container>
-          </SubComponents>
-        </Container>
-        <Container class="javax.swing.JPanel" name="symetryPanel">
-          <Properties>
-            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="a3" green="ae" red="0" type="rgb"/>
-            </Property>
-            <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-              <Dimension value="[1200, 800]"/>
-            </Property>
-          </Properties>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
-              <CardConstraints cardName="card3"/>
-            </Constraint>
-          </Constraints>
-
-          <Layout>
-            <DimensionLayout dim="0">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <Group type="102" alignment="0" attributes="0">
-                      <EmptySpace pref="78" max="32767" attributes="0"/>
-                      <Component id="viewerPanel" min="-2" max="-2" attributes="0"/>
-                      <EmptySpace min="-2" pref="72" max="-2" attributes="0"/>
-                      <Group type="103" groupAlignment="0" attributes="0">
-                          <Component id="exportModelButton" alignment="0" min="-2" max="-2" attributes="0"/>
-                          <Component id="reloadModelButton" min="-2" max="-2" attributes="0"/>
-                          <Component id="symmetryPanel1" alignment="0" min="-2" pref="461" max="-2" attributes="0"/>
-                      </Group>
-                      <EmptySpace max="32767" attributes="0"/>
-                  </Group>
-                  <Component id="filler1" alignment="1" max="32767" attributes="0"/>
-                  <Component id="filler2" alignment="0" max="32767" attributes="0"/>
-              </Group>
-            </DimensionLayout>
-            <DimensionLayout dim="1">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <Group type="102" alignment="0" attributes="0">
-                      <Component id="filler2" min="-2" pref="58" max="-2" attributes="0"/>
-                      <EmptySpace pref="46" max="32767" attributes="0"/>
-                      <Group type="103" groupAlignment="0" max="-2" attributes="0">
-                          <Group type="102" attributes="0">
-                              <Component id="symmetryPanel1" min="-2" max="-2" attributes="0"/>
-                              <EmptySpace max="32767" attributes="0"/>
-                              <Component id="exportModelButton" min="-2" max="-2" attributes="0"/>
-                              <EmptySpace type="separate" max="-2" attributes="0"/>
-                              <Component id="reloadModelButton" min="-2" max="-2" attributes="0"/>
-                          </Group>
-                          <Component id="viewerPanel" min="-2" max="-2" attributes="0"/>
-                      </Group>
-                      <EmptySpace max="-2" attributes="0"/>
-                      <Component id="filler1" min="-2" pref="51" max="-2" attributes="0"/>
-                      <EmptySpace min="-2" pref="93" max="-2" attributes="0"/>
-                  </Group>
-              </Group>
-            </DimensionLayout>
-          </Layout>
-          <SubComponents>
-            <Container class="javax.swing.JPanel" name="viewerPanel">
-
-              <Layout>
-                <DimensionLayout dim="0">
-                  <Group type="103" groupAlignment="0" attributes="0">
-                      <Group type="102" alignment="0" attributes="0">
-                          <EmptySpace max="-2" attributes="0"/>
-                          <Component id="canvasSymmetryPanel" pref="553" max="32767" attributes="0"/>
-                          <EmptySpace max="-2" attributes="0"/>
-                      </Group>
-                  </Group>
-                </DimensionLayout>
-                <DimensionLayout dim="1">
-                  <Group type="103" groupAlignment="0" attributes="0">
-                      <Group type="102" alignment="0" attributes="0">
-                          <EmptySpace max="-2" attributes="0"/>
-                          <Component id="canvasSymmetryPanel" pref="588" max="32767" attributes="0"/>
-                          <EmptySpace max="-2" attributes="0"/>
-                      </Group>
-                  </Group>
-                </DimensionLayout>
-              </Layout>
-              <SubComponents>
-                <Component class="cz.fidentis.analyst.gui.Canvas" name="canvasSymmetryPanel">
-                </Component>
-              </SubComponents>
-            </Container>
-            <Component class="javax.swing.JLabel" name="reloadModelButton">
-              <Properties>
-                <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-                  <Color blue="a3" green="ae" red="0" type="rgb"/>
-                </Property>
-                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-                  <Image iconType="3" name="/loadModel.png"/>
-                </Property>
-                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-                  <Color id="Hand Cursor"/>
-                </Property>
-                <Property name="opaque" type="boolean" value="true"/>
-              </Properties>
-              <Events>
-                <EventHandler event="mouseMoved" listener="java.awt.event.MouseMotionListener" parameters="java.awt.event.MouseEvent" handler="reloadModelButtonMouseMoved"/>
-                <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="reloadModelButtonMouseClicked"/>
-                <EventHandler event="mouseExited" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="reloadModelButtonMouseExited"/>
-              </Events>
-            </Component>
-            <Component class="javax.swing.JLabel" name="exportModelButton">
-              <Properties>
-                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-                  <Image iconType="3" name="/exportModel.png"/>
-                </Property>
-                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-                  <Color id="Hand Cursor"/>
-                </Property>
-              </Properties>
-              <Events>
-                <EventHandler event="mouseMoved" listener="java.awt.event.MouseMotionListener" parameters="java.awt.event.MouseEvent" handler="exportModelButtonMouseMoved"/>
-                <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="exportModelButtonMouseClicked"/>
-                <EventHandler event="mouseExited" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="exportModelButtonMouseExited"/>
-              </Events>
-            </Component>
-            <Component class="cz.fidentis.analyst.gui.SymmetryPanel" name="symmetryPanel1">
-              <Properties>
-                <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-                  <Color blue="e2" green="e6" red="b0" type="rgb"/>
-                </Property>
-              </Properties>
-            </Component>
-            <Component class="javax.swing.Box$Filler" name="filler1">
-              <Properties>
-                <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-                  <Dimension value="[0, 32767]"/>
-                </Property>
-              </Properties>
-              <AuxValues>
-                <AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalGlue"/>
-              </AuxValues>
-            </Component>
-            <Component class="javax.swing.Box$Filler" name="filler2">
-              <Properties>
-                <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-                  <Dimension value="[0, 32767]"/>
-                </Property>
-              </Properties>
-              <AuxValues>
-                <AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalGlue"/>
-              </AuxValues>
-            </Component>
-          </SubComponents>
-        </Container>
-        <Container class="javax.swing.JPanel" name="modelViewPanel">
-          <Properties>
-            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="a3" green="ae" red="0" type="rgb"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value=""/>
-            <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-              <Dimension value="[1200, 800]"/>
-            </Property>
-          </Properties>
-          <AccessibilityProperties>
-            <Property name="AccessibleContext.accessibleName" type="java.lang.String" value=""/>
-          </AccessibilityProperties>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
-              <CardConstraints cardName="card4"/>
-            </Constraint>
-          </Constraints>
-
-          <Layout>
-            <DimensionLayout dim="0">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <Component id="filler3" alignment="1" max="32767" attributes="0"/>
-                  <Group type="102" alignment="1" attributes="0">
-                      <EmptySpace pref="87" max="32767" attributes="0"/>
-                      <Component id="jPanel4" min="-2" max="-2" attributes="0"/>
-                      <EmptySpace type="separate" max="-2" attributes="0"/>
-                      <Component id="reloadModelButton1" min="-2" max="-2" attributes="0"/>
-                      <EmptySpace pref="95" max="32767" attributes="0"/>
-                  </Group>
-                  <Component id="filler4" alignment="0" max="32767" attributes="0"/>
-              </Group>
-            </DimensionLayout>
-            <DimensionLayout dim="1">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <Group type="102" attributes="0">
-                      <Component id="filler3" min="-2" pref="73" max="-2" attributes="0"/>
-                      <EmptySpace pref="87" max="32767" attributes="0"/>
-                      <Group type="103" groupAlignment="1" attributes="0">
-                          <Component id="jPanel4" min="-2" pref="579" max="-2" attributes="0"/>
-                          <Component id="reloadModelButton1" min="-2" max="-2" attributes="0"/>
-                      </Group>
-                      <EmptySpace max="-2" attributes="0"/>
-                      <Component id="filler4" min="-2" pref="31" max="-2" attributes="0"/>
-                      <EmptySpace pref="92" max="32767" attributes="0"/>
-                  </Group>
-              </Group>
-            </DimensionLayout>
-          </Layout>
-          <SubComponents>
-            <Component class="javax.swing.JLabel" name="reloadModelButton1">
-              <Properties>
-                <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-                  <Color blue="a3" green="ae" red="0" type="rgb"/>
-                </Property>
-                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-                  <Image iconType="3" name="/loadModel.png"/>
-                </Property>
-                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-                  <Color id="Hand Cursor"/>
-                </Property>
-                <Property name="opaque" type="boolean" value="true"/>
-              </Properties>
-              <Events>
-                <EventHandler event="mouseMoved" listener="java.awt.event.MouseMotionListener" parameters="java.awt.event.MouseEvent" handler="reloadModelButton1MouseMoved"/>
-                <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="reloadModelButton1MouseClicked"/>
-                <EventHandler event="mouseExited" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="reloadModelButton1MouseExited"/>
-              </Events>
-            </Component>
-            <Container class="javax.swing.JPanel" name="jPanel4">
-
-              <Layout>
-                <DimensionLayout dim="0">
-                  <Group type="103" groupAlignment="0" attributes="0">
-                      <Group type="102" alignment="0" attributes="0">
-                          <EmptySpace max="-2" attributes="0"/>
-                          <Component id="canvasModelView" min="-2" pref="795" max="-2" attributes="0"/>
-                          <EmptySpace max="32767" attributes="0"/>
-                      </Group>
-                  </Group>
-                </DimensionLayout>
-                <DimensionLayout dim="1">
-                  <Group type="103" groupAlignment="0" attributes="0">
-                      <Group type="102" alignment="1" attributes="0">
-                          <EmptySpace max="32767" attributes="0"/>
-                          <Component id="canvasModelView" min="-2" pref="553" max="-2" attributes="0"/>
-                          <EmptySpace min="-2" pref="98" max="-2" attributes="0"/>
-                      </Group>
-                  </Group>
-                </DimensionLayout>
-              </Layout>
-              <SubComponents>
-                <Component class="cz.fidentis.analyst.gui.Canvas" name="canvasModelView">
-                </Component>
-              </SubComponents>
-            </Container>
-            <Component class="javax.swing.Box$Filler" name="filler3">
-              <Properties>
-                <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-                  <Dimension value="[0, 32767]"/>
-                </Property>
-              </Properties>
-              <AuxValues>
-                <AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalGlue"/>
-              </AuxValues>
-            </Component>
-            <Component class="javax.swing.Box$Filler" name="filler4">
-              <Properties>
-                <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-                  <Dimension value="[0, 32767]"/>
-                </Property>
-              </Properties>
-              <AuxValues>
-                <AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalGlue"/>
-              </AuxValues>
-            </Component>
-          </SubComponents>
-        </Container>
-      </SubComponents>
-    </Container>
-  </SubComponents>
-</Form>
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/UserInterface.java b/GUI/src/main/java/cz/fidentis/analyst/gui/UserInterface.java
deleted file mode 100644
index ee3b9d80afdc1ec3f64c0493f9578c15969397cb..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/UserInterface.java
+++ /dev/null
@@ -1,1109 +0,0 @@
-package cz.fidentis.analyst.gui;
-
-import cz.fidentis.analyst.mesh.io.MeshObjExporter;
-import java.awt.Color;
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.swing.ImageIcon;
-import javax.swing.JFileChooser;
-import javax.swing.JFrame;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.UIManager;
-import javax.swing.UnsupportedLookAndFeelException;
-
-/**
- *
- * @author Natália Bebjaková
- * 
- * Main window of the applicaion
- */
-
-public class UserInterface extends javax.swing.JFrame {
-    /**
-     * Flag for backround color of the new project button
-     */
-    boolean pressedNewProject = false;
-    /**
-     * Flag for whether model should be displayed as wire-frame 
-     */
-    boolean wiredModelClicked = false;
-    /**
-     * Panel that is actualy displayed on the window
-     */
-    private JPanel actualPanel;
-    /**
-     * Main frame of the application
-     */
-    public static JFrame frameMain; 
-    /**
-     * x coordinate of the mouse 
-     */
-    int xMouse;
-    /**
-     * y coordinate of the mouse
-     */
-    int yMouse;
-    
-    /**
-    * Creates new form Interface
-     */
-    public UserInterface() {
-        initComponents();
-        topPanel.setVisible(false);
-        actualPanel = startingPanel;
-        symmetryPanel1.setCanvas(canvasSymmetryPanel);
-        this.setExtendedState(JFrame.MAXIMIZED_BOTH);
-    }
-
-    /**
-     * 
-     * @return JPanel for estimating symmetry of the model
-     */
-    public SymmetryPanel getSymmetryPanel1() {
-        return symmetryPanel1;
-    }
-    
-    /**
-     * Enables to switch between panels
-     * @param panel New panel that will be visible
-     */
-    private void switchPanelOnMainPanel(JPanel panel) {
-        actualPanel = panel;
-        jPanel2.removeAll();
-        jPanel2.repaint();
-        jPanel2.revalidate();
-        jPanel2.add(panel);
-        jPanel2.repaint();
-        jPanel2.revalidate();
-        panel.add(jPanel1);
-        jPanel1.setVisible(true);
-    }
-    
-    /**
-     * Changes backround of labels to darker green color
-     * @param jl label of which backround changes 
-     */
-    public void setLabelBackround(JLabel jl) {
-        jl.setBackground(new Color(11,56,49));
-    }
-    
-    /**
-     * Changes backround of the label back to original
-     * @param jl label of which backround is return to original
-     */
-    public void resetLabelBackround(JLabel jl) {
-        jl.setBackground(new Color(20,114,105));
-    }
-    
-    /**
-     * This method is called from within the constructor to initialize the form.
-     * WARNING: Do NOT modify this code. The content of this method is always
-     * regenerated by the Form Editor.
-     * 
-     * Code generated by NetBeans
-     */
-    @SuppressWarnings("unchecked")
-    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
-    private void initComponents() {
-
-        jPanel1 = new javax.swing.JPanel();
-        newProject = new javax.swing.JLabel();
-        wiredModelButton = new javax.swing.JLabel();
-        homeButton = new javax.swing.JLabel();
-        topPanel = new javax.swing.JPanel();
-        compareTwo = new javax.swing.JPanel();
-        jLabel1 = new javax.swing.JLabel();
-        compareDB = new javax.swing.JPanel();
-        jLabel3 = new javax.swing.JLabel();
-        batchProcessing = new javax.swing.JPanel();
-        jLabel2 = new javax.swing.JLabel();
-        symetryEstimator = new javax.swing.JPanel();
-        jLabel4 = new javax.swing.JLabel();
-        jPanel2 = new javax.swing.JPanel();
-        startingPanel = new javax.swing.JPanel();
-        javax.swing.JLabel logo = new javax.swing.JLabel();
-        jPanel3 = new javax.swing.JPanel();
-        compareTwoMain = new javax.swing.JPanel();
-        compareTwoMain1 = new javax.swing.JPanel();
-        batchMain = new javax.swing.JPanel();
-        JLabel10 = new javax.swing.JLabel();
-        symetryMain = new javax.swing.JPanel();
-        JLabel11 = new javax.swing.JLabel();
-        viewerButton = new javax.swing.JLabel();
-        JLabel8 = new javax.swing.JLabel();
-        JLabel9 = new javax.swing.JLabel();
-        symetryPanel = new javax.swing.JPanel();
-        viewerPanel = new javax.swing.JPanel();
-        canvasSymmetryPanel = new cz.fidentis.analyst.gui.Canvas();
-        reloadModelButton = new javax.swing.JLabel();
-        exportModelButton = new javax.swing.JLabel();
-        symmetryPanel1 = new cz.fidentis.analyst.gui.SymmetryPanel();
-        filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767));
-        filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767));
-        modelViewPanel = new javax.swing.JPanel();
-        reloadModelButton1 = new javax.swing.JLabel();
-        jPanel4 = new javax.swing.JPanel();
-        canvasModelView = new cz.fidentis.analyst.gui.Canvas();
-        filler3 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767));
-        filler4 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767));
-
-        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
-        setBackground(new java.awt.Color(0, 174, 163));
-        setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
-        setLocationByPlatform(true);
-
-        jPanel1.setBackground(new java.awt.Color(20, 114, 105));
-        jPanel1.setPreferredSize(new java.awt.Dimension(1200, 77));
-        jPanel1.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
-            public void mouseDragged(java.awt.event.MouseEvent evt) {
-                jPanel1MouseDragged(evt);
-            }
-        });
-        jPanel1.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mousePressed(java.awt.event.MouseEvent evt) {
-                jPanel1MousePressed(evt);
-            }
-        });
-
-        newProject.setBackground(new java.awt.Color(20, 114, 105));
-        newProject.setFont(new java.awt.Font("Neue Haas Unica Pro", 0, 18)); // NOI18N
-        newProject.setForeground(new java.awt.Color(255, 255, 255));
-        newProject.setIcon(new javax.swing.ImageIcon(getClass().getResource("/newP.png"))); // NOI18N
-        newProject.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        newProject.setOpaque(true);
-        newProject.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
-            public void mouseMoved(java.awt.event.MouseEvent evt) {
-                newProjectMouseMoved(evt);
-            }
-        });
-        newProject.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseExited(java.awt.event.MouseEvent evt) {
-                newProjectMouseExited(evt);
-            }
-            public void mousePressed(java.awt.event.MouseEvent evt) {
-                newProjectMousePressed(evt);
-            }
-        });
-
-        wiredModelButton.setBackground(new java.awt.Color(20, 114, 105));
-        wiredModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/wireframe2.png"))); // NOI18N
-        wiredModelButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        wiredModelButton.setOpaque(true);
-        wiredModelButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                wiredModelButtonMouseClicked(evt);
-            }
-        });
-
-        homeButton.setBackground(new java.awt.Color(20, 114, 105));
-        homeButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/home.png"))); // NOI18N
-        homeButton.setToolTipText("Home");
-        homeButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        homeButton.setOpaque(true);
-        homeButton.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
-            public void mouseMoved(java.awt.event.MouseEvent evt) {
-                homeButtonMouseMoved(evt);
-            }
-        });
-        homeButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                homeButtonMouseClicked(evt);
-            }
-            public void mouseExited(java.awt.event.MouseEvent evt) {
-                homeButtonMouseExited(evt);
-            }
-        });
-
-        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
-        jPanel1.setLayout(jPanel1Layout);
-        jPanel1Layout.setHorizontalGroup(
-            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(jPanel1Layout.createSequentialGroup()
-                .addContainerGap()
-                .addComponent(homeButton)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                .addComponent(newProject, javax.swing.GroupLayout.PREFERRED_SIZE, 149, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                .addComponent(wiredModelButton, javax.swing.GroupLayout.PREFERRED_SIZE, 134, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
-        );
-        jPanel1Layout.setVerticalGroup(
-            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addComponent(wiredModelButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-            .addComponent(newProject, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-            .addComponent(homeButton, javax.swing.GroupLayout.DEFAULT_SIZE, 52, Short.MAX_VALUE)
-        );
-
-        topPanel.setBackground(new java.awt.Color(20, 114, 105));
-        topPanel.setPreferredSize(new java.awt.Dimension(1200, 266));
-
-        compareTwo.setBackground(new java.awt.Color(20, 114, 105));
-        compareTwo.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-
-        jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
-        jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/compareTwoStart.png"))); // NOI18N
-        jLabel1.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
-
-        javax.swing.GroupLayout compareTwoLayout = new javax.swing.GroupLayout(compareTwo);
-        compareTwo.setLayout(compareTwoLayout);
-        compareTwoLayout.setHorizontalGroup(
-            compareTwoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(compareTwoLayout.createSequentialGroup()
-                .addContainerGap()
-                .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                .addContainerGap())
-        );
-        compareTwoLayout.setVerticalGroup(
-            compareTwoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(compareTwoLayout.createSequentialGroup()
-                .addGap(30, 30, 30)
-                .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                .addGap(28, 28, 28))
-        );
-
-        compareDB.setBackground(new java.awt.Color(20, 114, 105));
-        compareDB.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-
-        jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
-        jLabel3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/batchProcessingStart.png"))); // NOI18N
-        jLabel3.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
-
-        javax.swing.GroupLayout compareDBLayout = new javax.swing.GroupLayout(compareDB);
-        compareDB.setLayout(compareDBLayout);
-        compareDBLayout.setHorizontalGroup(
-            compareDBLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-        );
-        compareDBLayout.setVerticalGroup(
-            compareDBLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-        );
-
-        batchProcessing.setBackground(new java.awt.Color(20, 114, 105));
-        batchProcessing.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-
-        jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
-        jLabel2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/copareWithDatabaseStart.png"))); // NOI18N
-        jLabel2.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
-
-        javax.swing.GroupLayout batchProcessingLayout = new javax.swing.GroupLayout(batchProcessing);
-        batchProcessing.setLayout(batchProcessingLayout);
-        batchProcessingLayout.setHorizontalGroup(
-            batchProcessingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(batchProcessingLayout.createSequentialGroup()
-                .addGap(26, 26, 26)
-                .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
-        );
-        batchProcessingLayout.setVerticalGroup(
-            batchProcessingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, batchProcessingLayout.createSequentialGroup()
-                .addContainerGap()
-                .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
-        );
-
-        symetryEstimator.setBackground(new java.awt.Color(20, 114, 105));
-        symetryEstimator.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        symetryEstimator.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                symetryEstimatorMouseClicked(evt);
-            }
-        });
-
-        jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
-        jLabel4.setIcon(new javax.swing.ImageIcon(getClass().getResource("/symetryStartP.png"))); // NOI18N
-        jLabel4.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        jLabel4.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
-            public void mouseMoved(java.awt.event.MouseEvent evt) {
-                jLabel4MouseMoved1(evt);
-            }
-        });
-        jLabel4.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                jLabel4MouseClicked(evt);
-            }
-            public void mouseExited(java.awt.event.MouseEvent evt) {
-                jLabel4MouseExited(evt);
-            }
-        });
-
-        javax.swing.GroupLayout symetryEstimatorLayout = new javax.swing.GroupLayout(symetryEstimator);
-        symetryEstimator.setLayout(symetryEstimatorLayout);
-        symetryEstimatorLayout.setHorizontalGroup(
-            symetryEstimatorLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, symetryEstimatorLayout.createSequentialGroup()
-                .addContainerGap()
-                .addComponent(jLabel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                .addContainerGap())
-        );
-        symetryEstimatorLayout.setVerticalGroup(
-            symetryEstimatorLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, symetryEstimatorLayout.createSequentialGroup()
-                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                .addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 137, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addGap(36, 36, 36))
-        );
-
-        javax.swing.GroupLayout topPanelLayout = new javax.swing.GroupLayout(topPanel);
-        topPanel.setLayout(topPanelLayout);
-        topPanelLayout.setHorizontalGroup(
-            topPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(topPanelLayout.createSequentialGroup()
-                .addContainerGap(99, Short.MAX_VALUE)
-                .addComponent(compareTwo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addGap(105, 105, 105)
-                .addComponent(compareDB, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addGap(94, 94, 94)
-                .addComponent(batchProcessing, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addGap(94, 94, 94)
-                .addComponent(symetryEstimator, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addContainerGap(98, Short.MAX_VALUE))
-        );
-        topPanelLayout.setVerticalGroup(
-            topPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(topPanelLayout.createSequentialGroup()
-                .addGap(52, 52, 52)
-                .addGroup(topPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                    .addComponent(symetryEstimator, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                    .addComponent(compareDB, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, topPanelLayout.createSequentialGroup()
-                        .addGap(0, 0, Short.MAX_VALUE)
-                        .addComponent(compareTwo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
-                    .addComponent(batchProcessing, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
-        );
-
-        jPanel2.setBackground(new java.awt.Color(0, 174, 163));
-        jPanel2.setFont(new java.awt.Font("Arial", 1, 13)); // NOI18N
-        jPanel2.setPreferredSize(getPreferredSize());
-        jPanel2.setLayout(new java.awt.CardLayout());
-
-        startingPanel.setBackground(new java.awt.Color(0, 174, 163));
-        startingPanel.setToolTipText("");
-        startingPanel.setMaximumSize(new java.awt.Dimension(0, 0));
-        startingPanel.setPreferredSize(new java.awt.Dimension(1200, 800));
-        startingPanel.setRequestFocusEnabled(false);
-
-        logo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/logo3.png"))); // NOI18N
-
-        jPanel3.setBackground(new java.awt.Color(0, 174, 163));
-        jPanel3.setToolTipText("");
-
-        compareTwoMain.setBackground(new java.awt.Color(0, 174, 163));
-
-        javax.swing.GroupLayout compareTwoMainLayout = new javax.swing.GroupLayout(compareTwoMain);
-        compareTwoMain.setLayout(compareTwoMainLayout);
-        compareTwoMainLayout.setHorizontalGroup(
-            compareTwoMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGap(0, 177, Short.MAX_VALUE)
-        );
-        compareTwoMainLayout.setVerticalGroup(
-            compareTwoMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGap(0, 170, Short.MAX_VALUE)
-        );
-
-        compareTwoMain1.setBackground(new java.awt.Color(0, 174, 163));
-
-        javax.swing.GroupLayout compareTwoMain1Layout = new javax.swing.GroupLayout(compareTwoMain1);
-        compareTwoMain1.setLayout(compareTwoMain1Layout);
-        compareTwoMain1Layout.setHorizontalGroup(
-            compareTwoMain1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGap(0, 220, Short.MAX_VALUE)
-        );
-        compareTwoMain1Layout.setVerticalGroup(
-            compareTwoMain1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGap(0, 169, Short.MAX_VALUE)
-        );
-
-        batchMain.setBackground(new java.awt.Color(0, 174, 163));
-
-        JLabel10.setIcon(new javax.swing.ImageIcon(getClass().getResource("/batchProcessingStart.png"))); // NOI18N
-
-        javax.swing.GroupLayout batchMainLayout = new javax.swing.GroupLayout(batchMain);
-        batchMain.setLayout(batchMainLayout);
-        batchMainLayout.setHorizontalGroup(
-            batchMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(batchMainLayout.createSequentialGroup()
-                .addContainerGap()
-                .addComponent(JLabel10)
-                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
-        );
-        batchMainLayout.setVerticalGroup(
-            batchMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(batchMainLayout.createSequentialGroup()
-                .addGap(25, 25, 25)
-                .addComponent(JLabel10)
-                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
-        );
-
-        symetryMain.setBackground(new java.awt.Color(0, 174, 163));
-
-        JLabel11.setBackground(new java.awt.Color(0, 174, 163));
-        JLabel11.setIcon(new javax.swing.ImageIcon(getClass().getResource("/symetryStart.png"))); // NOI18N
-        JLabel11.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        JLabel11.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
-            public void mouseMoved(java.awt.event.MouseEvent evt) {
-                JLabel11MouseMoved(evt);
-            }
-        });
-        JLabel11.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                JLabel11MouseClicked(evt);
-            }
-            public void mouseExited(java.awt.event.MouseEvent evt) {
-                JLabel11MouseExited(evt);
-            }
-        });
-
-        javax.swing.GroupLayout symetryMainLayout = new javax.swing.GroupLayout(symetryMain);
-        symetryMain.setLayout(symetryMainLayout);
-        symetryMainLayout.setHorizontalGroup(
-            symetryMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addComponent(JLabel11, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 189, Short.MAX_VALUE)
-        );
-        symetryMainLayout.setVerticalGroup(
-            symetryMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, symetryMainLayout.createSequentialGroup()
-                .addContainerGap()
-                .addComponent(JLabel11, javax.swing.GroupLayout.DEFAULT_SIZE, 167, Short.MAX_VALUE))
-        );
-
-        viewerButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/modelView.png"))); // NOI18N
-        viewerButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        viewerButton.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
-            public void mouseMoved(java.awt.event.MouseEvent evt) {
-                viewerButtonMouseMoved(evt);
-            }
-        });
-        viewerButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                viewerButtonMouseClicked(evt);
-            }
-            public void mouseExited(java.awt.event.MouseEvent evt) {
-                viewerButtonMouseExited(evt);
-            }
-        });
-
-        JLabel8.setIcon(new javax.swing.ImageIcon(getClass().getResource("/compareTwoStart.png"))); // NOI18N
-
-        JLabel9.setBackground(new java.awt.Color(0, 174, 163));
-        JLabel9.setIcon(new javax.swing.ImageIcon(getClass().getResource("/copareWithDatabaseStart.png"))); // NOI18N
-
-        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
-        jPanel3.setLayout(jPanel3Layout);
-        jPanel3Layout.setHorizontalGroup(
-            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(jPanel3Layout.createSequentialGroup()
-                .addContainerGap(17, Short.MAX_VALUE)
-                .addComponent(viewerButton, javax.swing.GroupLayout.PREFERRED_SIZE, 323, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addGap(18, 18, 18)
-                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                    .addComponent(compareTwoMain, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                    .addComponent(compareTwoMain1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                    .addGroup(jPanel3Layout.createSequentialGroup()
-                        .addComponent(JLabel8, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                        .addGap(62, 62, 62))
-                    .addGroup(jPanel3Layout.createSequentialGroup()
-                        .addComponent(JLabel9, javax.swing.GroupLayout.PREFERRED_SIZE, 196, javax.swing.GroupLayout.PREFERRED_SIZE)
-                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
-                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                    .addComponent(batchMain, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                    .addGroup(jPanel3Layout.createSequentialGroup()
-                        .addGap(12, 12, 12)
-                        .addComponent(symetryMain, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
-                .addContainerGap(42, Short.MAX_VALUE))
-        );
-        jPanel3Layout.setVerticalGroup(
-            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(jPanel3Layout.createSequentialGroup()
-                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
-                        .addContainerGap()
-                        .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
-                            .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                                .addComponent(JLabel8, javax.swing.GroupLayout.PREFERRED_SIZE, 142, javax.swing.GroupLayout.PREFERRED_SIZE)
-                                .addComponent(compareTwoMain, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
-                            .addGroup(jPanel3Layout.createSequentialGroup()
-                                .addComponent(batchMain, javax.swing.GroupLayout.PREFERRED_SIZE, 173, javax.swing.GroupLayout.PREFERRED_SIZE)
-                                .addGap(28, 28, 28)))
-                        .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                            .addComponent(compareTwoMain1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                            .addComponent(symetryMain, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
-                    .addGroup(jPanel3Layout.createSequentialGroup()
-                        .addGap(296, 296, 296)
-                        .addComponent(JLabel9, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                        .addGap(8, 8, 8)))
-                .addContainerGap())
-            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
-                .addGap(0, 0, Short.MAX_VALUE)
-                .addComponent(viewerButton)
-                .addGap(41, 41, 41))
-        );
-
-        javax.swing.GroupLayout startingPanelLayout = new javax.swing.GroupLayout(startingPanel);
-        startingPanel.setLayout(startingPanelLayout);
-        startingPanelLayout.setHorizontalGroup(
-            startingPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(startingPanelLayout.createSequentialGroup()
-                .addContainerGap(81, Short.MAX_VALUE)
-                .addGroup(startingPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                    .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, startingPanelLayout.createSequentialGroup()
-                        .addComponent(logo, javax.swing.GroupLayout.PREFERRED_SIZE, 218, javax.swing.GroupLayout.PREFERRED_SIZE)
-                        .addGap(400, 400, 400)))
-                .addContainerGap(81, Short.MAX_VALUE))
-        );
-        startingPanelLayout.setVerticalGroup(
-            startingPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(startingPanelLayout.createSequentialGroup()
-                .addContainerGap(133, Short.MAX_VALUE)
-                .addComponent(logo, javax.swing.GroupLayout.PREFERRED_SIZE, 124, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
-                .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addContainerGap(136, Short.MAX_VALUE))
-        );
-
-        jPanel2.add(startingPanel, "card3");
-
-        symetryPanel.setBackground(new java.awt.Color(0, 174, 163));
-        symetryPanel.setPreferredSize(new java.awt.Dimension(1200, 800));
-
-        javax.swing.GroupLayout viewerPanelLayout = new javax.swing.GroupLayout(viewerPanel);
-        viewerPanel.setLayout(viewerPanelLayout);
-        viewerPanelLayout.setHorizontalGroup(
-            viewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(viewerPanelLayout.createSequentialGroup()
-                .addContainerGap()
-                .addComponent(canvasSymmetryPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 553, Short.MAX_VALUE)
-                .addContainerGap())
-        );
-        viewerPanelLayout.setVerticalGroup(
-            viewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(viewerPanelLayout.createSequentialGroup()
-                .addContainerGap()
-                .addComponent(canvasSymmetryPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 588, Short.MAX_VALUE)
-                .addContainerGap())
-        );
-
-        reloadModelButton.setBackground(new java.awt.Color(0, 174, 163));
-        reloadModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/loadModel.png"))); // NOI18N
-        reloadModelButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        reloadModelButton.setOpaque(true);
-        reloadModelButton.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
-            public void mouseMoved(java.awt.event.MouseEvent evt) {
-                reloadModelButtonMouseMoved(evt);
-            }
-        });
-        reloadModelButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                reloadModelButtonMouseClicked(evt);
-            }
-            public void mouseExited(java.awt.event.MouseEvent evt) {
-                reloadModelButtonMouseExited(evt);
-            }
-        });
-
-        exportModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/exportModel.png"))); // NOI18N
-        exportModelButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        exportModelButton.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
-            public void mouseMoved(java.awt.event.MouseEvent evt) {
-                exportModelButtonMouseMoved(evt);
-            }
-        });
-        exportModelButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                exportModelButtonMouseClicked(evt);
-            }
-            public void mouseExited(java.awt.event.MouseEvent evt) {
-                exportModelButtonMouseExited(evt);
-            }
-        });
-
-        symmetryPanel1.setBackground(new java.awt.Color(176, 230, 226));
-
-        javax.swing.GroupLayout symetryPanelLayout = new javax.swing.GroupLayout(symetryPanel);
-        symetryPanel.setLayout(symetryPanelLayout);
-        symetryPanelLayout.setHorizontalGroup(
-            symetryPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(symetryPanelLayout.createSequentialGroup()
-                .addContainerGap(78, Short.MAX_VALUE)
-                .addComponent(viewerPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addGap(72, 72, 72)
-                .addGroup(symetryPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                    .addComponent(exportModelButton)
-                    .addComponent(reloadModelButton)
-                    .addComponent(symmetryPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 461, javax.swing.GroupLayout.PREFERRED_SIZE))
-                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
-            .addComponent(filler1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-            .addComponent(filler2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-        );
-        symetryPanelLayout.setVerticalGroup(
-            symetryPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(symetryPanelLayout.createSequentialGroup()
-                .addComponent(filler2, javax.swing.GroupLayout.PREFERRED_SIZE, 58, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 46, Short.MAX_VALUE)
-                .addGroup(symetryPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
-                    .addGroup(symetryPanelLayout.createSequentialGroup()
-                        .addComponent(symmetryPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                        .addComponent(exportModelButton)
-                        .addGap(18, 18, 18)
-                        .addComponent(reloadModelButton))
-                    .addComponent(viewerPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                .addComponent(filler1, javax.swing.GroupLayout.PREFERRED_SIZE, 51, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addGap(93, 93, 93))
-        );
-
-        jPanel2.add(symetryPanel, "card3");
-
-        modelViewPanel.setBackground(new java.awt.Color(0, 174, 163));
-        modelViewPanel.setToolTipText("");
-        modelViewPanel.setPreferredSize(new java.awt.Dimension(1200, 800));
-
-        reloadModelButton1.setBackground(new java.awt.Color(0, 174, 163));
-        reloadModelButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/loadModel.png"))); // NOI18N
-        reloadModelButton1.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        reloadModelButton1.setOpaque(true);
-        reloadModelButton1.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
-            public void mouseMoved(java.awt.event.MouseEvent evt) {
-                reloadModelButton1MouseMoved(evt);
-            }
-        });
-        reloadModelButton1.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                reloadModelButton1MouseClicked(evt);
-            }
-            public void mouseExited(java.awt.event.MouseEvent evt) {
-                reloadModelButton1MouseExited(evt);
-            }
-        });
-
-        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
-        jPanel4.setLayout(jPanel4Layout);
-        jPanel4Layout.setHorizontalGroup(
-            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(jPanel4Layout.createSequentialGroup()
-                .addContainerGap()
-                .addComponent(canvasModelView, javax.swing.GroupLayout.PREFERRED_SIZE, 795, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
-        );
-        jPanel4Layout.setVerticalGroup(
-            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel4Layout.createSequentialGroup()
-                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                .addComponent(canvasModelView, javax.swing.GroupLayout.PREFERRED_SIZE, 553, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addGap(98, 98, 98))
-        );
-
-        javax.swing.GroupLayout modelViewPanelLayout = new javax.swing.GroupLayout(modelViewPanel);
-        modelViewPanel.setLayout(modelViewPanelLayout);
-        modelViewPanelLayout.setHorizontalGroup(
-            modelViewPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addComponent(filler3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, modelViewPanelLayout.createSequentialGroup()
-                .addContainerGap(87, Short.MAX_VALUE)
-                .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addGap(18, 18, 18)
-                .addComponent(reloadModelButton1)
-                .addContainerGap(95, Short.MAX_VALUE))
-            .addComponent(filler4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-        );
-        modelViewPanelLayout.setVerticalGroup(
-            modelViewPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(modelViewPanelLayout.createSequentialGroup()
-                .addComponent(filler3, javax.swing.GroupLayout.PREFERRED_SIZE, 73, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 87, Short.MAX_VALUE)
-                .addGroup(modelViewPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
-                    .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, 579, javax.swing.GroupLayout.PREFERRED_SIZE)
-                    .addComponent(reloadModelButton1))
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                .addComponent(filler4, javax.swing.GroupLayout.PREFERRED_SIZE, 31, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addContainerGap(92, Short.MAX_VALUE))
-        );
-
-        jPanel2.add(modelViewPanel, "card4");
-        modelViewPanel.getAccessibleContext().setAccessibleName("");
-
-        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
-        getContentPane().setLayout(layout);
-        layout.setHorizontalGroup(
-            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addComponent(topPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-            .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
-        );
-        layout.setVerticalGroup(
-            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(layout.createSequentialGroup()
-                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
-                .addComponent(topPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 239, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addGap(0, 565, Short.MAX_VALUE))
-            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
-        );
-
-        topPanel.getAccessibleContext().setAccessibleName("");
-
-        pack();
-        setLocationRelativeTo(null);
-    }// </editor-fold>//GEN-END:initComponents
-
-    /**
-     * 
-     * @param evt Changes the backround of the new project button
-     */
-    private void newProjectMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_newProjectMouseMoved
-        setLabelBackround(newProject);
-    }//GEN-LAST:event_newProjectMouseMoved
-
-    /**
-     * 
-     * @param evt Changes back the backround of the new project button
-     */
-    private void newProjectMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_newProjectMouseExited
-        if (!pressedNewProject) {
-            resetLabelBackround(newProject);
-        }
-    }//GEN-LAST:event_newProjectMouseExited
-
-    /**
-     * 
-     * @param evt While moved with mouse, symmetry label changes 
-     */
-    private void jLabel4MouseMoved1(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jLabel4MouseMoved1
-        jLabel4.setIcon(new javax.swing.ImageIcon(getClass().getResource("/symetryStartPanel.png")));
-    }//GEN-LAST:event_jLabel4MouseMoved1
-
-    /**
-     * 
-     * @param evt Shows menu with icons for programs of the app
-     */
-    private void newProjectMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_newProjectMousePressed
-        if(pressedNewProject) {
-            topPanel.setVisible(false);
-            pressedNewProject = false;
-            switchPanelOnMainPanel(actualPanel);
-            newProject.setIcon(new javax.swing.ImageIcon(getClass().getResource("/newP.png")));
-        }else{
-            topPanel.setVisible(true);
-            topPanel.add(jPanel1);
-            pressedNewProject = true;
-            newProject.setIcon(new javax.swing.ImageIcon(getClass().getResource("/new_project_opened.png")));
-        }
-    }//GEN-LAST:event_newProjectMousePressed
-
-  
-    /**
-     * 
-     * @param evt Switch to symmetry panel
-     */
-    private void JLabel11MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_JLabel11MouseClicked
-        switchPanelOnMainPanel(symetryPanel);
-    }//GEN-LAST:event_JLabel11MouseClicked
-
-    /**
-     * 
-     * @param evt Switch to symmetry panel
-     */
-    private void symetryEstimatorMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_symetryEstimatorMouseClicked
-        switchPanelOnMainPanel(symetryPanel);
-        topPanel.setVisible(false);
-        ImageIcon icon = new ImageIcon(getClass().getResource("/newP.png"));
-        
-        newProject.setIcon(icon);
-        resetLabelBackround(newProject);
-    }//GEN-LAST:event_symetryEstimatorMouseClicked
-
-    /**
-     * 
-     * @param evt Enables to move with the window of the app
-     */
-    private void jPanel1MouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jPanel1MouseDragged
-        int x = evt.getXOnScreen();
-        int y = evt.getYOnScreen();
-        frameMain.setLocation(x - xMouse, y - yMouse);
-    }//GEN-LAST:event_jPanel1MouseDragged
-
-    /**
-     * 
-     * @param evt Enables to move with the window of the app
-     */
-    private void jPanel1MousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jPanel1MousePressed
-        xMouse  = evt.getX();
-        yMouse = evt.getY();
-    }//GEN-LAST:event_jPanel1MousePressed
-
-    /**
-     * 
-     * @param evt Changes the backround of the reload button
-     */
-    private void reloadModelButtonMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_reloadModelButtonMouseMoved
-        reloadModelButton.setBackground(new Color(176,230,226));
-    }//GEN-LAST:event_reloadModelButtonMouseMoved
-
-    /**
-     * 
-     * @param evt Changes the backround of the reload button
-     */
-    private void reloadModelButtonMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_reloadModelButtonMouseExited
-        reloadModelButton.setBackground(new Color(0,174,163));
-    }//GEN-LAST:event_reloadModelButtonMouseExited
-
-    /**
-     * 
-     * @param evt Loads the model that will be displayed
-     */
-    private void reloadModelButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_reloadModelButtonMouseClicked
-        canvasSymmetryPanel.loadModel();
-        if (canvasSymmetryPanel.isLoaded()) {
-            symmetryPanel1.showPlaneButtonsOnPanel(false);
-        } 
-    }//GEN-LAST:event_reloadModelButtonMouseClicked
-
-    /**
-     * letting know GLCanva if model will be displayed as wire-frame 
-     */
-    private void wiredModelButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_wiredModelButtonMouseClicked
-        if (wiredModelClicked) {
-            resetLabelBackround(wiredModelButton);
-            wiredModelClicked = false;
-            Canvas.setDrawWired(wiredModelClicked);
-            /*canvasSymmetryPanel.setDrawWired(wiredModelClicked);
-            canvasModelView.setDrawWired(wiredModelClicked);*/
-        } else {
-            setLabelBackround(wiredModelButton);
-            wiredModelClicked = true;
-            Canvas.setDrawWired(wiredModelClicked);
-            /*canvasSymmetryPanel.setDrawWired(wiredModelClicked);
-            canvasModelView.setDrawWired(wiredModelClicked);*/
-        }
-    }//GEN-LAST:event_wiredModelButtonMouseClicked
-
-    /**
-     * 
-     * @param evt Changes the backround of the home button
-     */
-    private void homeButtonMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_homeButtonMouseMoved
-        setLabelBackround(homeButton);
-    }//GEN-LAST:event_homeButtonMouseMoved
-
-    /**
-     * 
-     * @param evt Changes the backround of the home button
-     */
-    private void homeButtonMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_homeButtonMouseExited
-        resetLabelBackround(homeButton);
-    }//GEN-LAST:event_homeButtonMouseExited
-
-    /**
-     * 
-     * @param evt Returns to home panel of the app
-     */
-    private void homeButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_homeButtonMouseClicked
-        switchPanelOnMainPanel(startingPanel);
-    }//GEN-LAST:event_homeButtonMouseClicked
-
-    /**
-     * 
-     * @param evt Changes the backround of the reload button
-     */
-    private void reloadModelButton1MouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_reloadModelButton1MouseMoved
-        reloadModelButton1.setBackground(new Color(176,230,226));
-    }//GEN-LAST:event_reloadModelButton1MouseMoved
-
-    /**
-     * 
-     * @param evt Loads the model that will be displayed
-     */
-    private void reloadModelButton1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_reloadModelButton1MouseClicked
-        canvasModelView.loadModel();
-    }//GEN-LAST:event_reloadModelButton1MouseClicked
-
-    /**
-     * 
-     * @param evt Changes the backround of the reload button
-     */
-    private void reloadModelButton1MouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_reloadModelButton1MouseExited
-        reloadModelButton1.setBackground(new Color(0,174,163));
-    }//GEN-LAST:event_reloadModelButton1MouseExited
-
-    /**
-     * 
-     * @param evt Switch to panel for viewing the model
-     */
-    private void viewerButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_viewerButtonMouseClicked
-        switchPanelOnMainPanel(modelViewPanel);
-    }//GEN-LAST:event_viewerButtonMouseClicked
-
-    /**
-     * 
-     * @param evt Changes the backround of the symmetry button
-     */
-    private void JLabel11MouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_JLabel11MouseMoved
-        JLabel11.setIcon(new javax.swing.ImageIcon(getClass().getResource("/symetryStartMoved.png")));
-    }//GEN-LAST:event_JLabel11MouseMoved
-
-    /**
-     * 
-     * @param evt Changes the backround of the viewer panel button
-     */
-    private void viewerButtonMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_viewerButtonMouseMoved
-        viewerButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/modelViewMoved.png")));
-    }//GEN-LAST:event_viewerButtonMouseMoved
-
-    /**
-     * 
-     * @param evt Changes the backround of the viewer panel button
-     */
-    private void viewerButtonMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_viewerButtonMouseExited
-        viewerButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/modelView.png")));
-    }//GEN-LAST:event_viewerButtonMouseExited
-
-    /**
-     * 
-     * @param evt Changes the backround of the symmetry button
-     */
-    private void JLabel11MouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_JLabel11MouseExited
-        JLabel11.setIcon(new javax.swing.ImageIcon(getClass().getResource("/symetryStart.png")));
-    }//GEN-LAST:event_JLabel11MouseExited
-
-    /**
-     * 
-     * @param evt Switch to panel for symmetry
-     */
-    private void jLabel4MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jLabel4MouseClicked
-        switchPanelOnMainPanel(symetryPanel);
-        topPanel.setVisible(false);
-        newProject.setIcon(new javax.swing.ImageIcon(getClass().getResource("/newP.png")));
-        resetLabelBackround(newProject);
-    }//GEN-LAST:event_jLabel4MouseClicked
-
-    /**
-     * 
-     * @param evt Changes the backround of the export button
-     */
-    private void exportModelButtonMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_exportModelButtonMouseMoved
-        exportModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/exportModelPressed.png")));
-    }//GEN-LAST:event_exportModelButtonMouseMoved
-
-    /**
-     * 
-     * @param evt Changes the backround of the export button
-     */
-    private void exportModelButtonMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_exportModelButtonMouseExited
-        exportModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/exportModel.png")));
-    }//GEN-LAST:event_exportModelButtonMouseExited
-
-    /**
-     * When export button pressed, new directory is created and model is exported to it
-     * If there is not loaded model, user is warned
-     */
-    private void exportModelButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_exportModelButtonMouseClicked
-        if (canvasSymmetryPanel.getModel().getFacets().isEmpty()){
-            JOptionPane.showMessageDialog(frameMain, "You have to load the model.", "Model not loaded",
-                    0, new ImageIcon(getClass().getResource("/notLoadedModel.png")));
-        } else {
-            JFileChooser chooser = new JFileChooser();
-            chooser.showSaveDialog(symetryPanel);
-            
-            MeshObjExporter exporter = new MeshObjExporter(canvasSymmetryPanel.getModel());
-            try {
-                if (chooser.getSelectedFile() != null) {
-                    exporter.exportModelToObj(chooser.getSelectedFile());
-                    JOptionPane.showMessageDialog(frameMain, "Model exported into: " +
-                            chooser.getCurrentDirectory().toString() + "\\" + chooser.getSelectedFile().getName(), "Model exported",
-                            0, new ImageIcon(getClass().getResource("/exportedModel.png")));
-                }
-            } catch (IOException ex) {
-                Logger.getLogger(UserInterface.class.getName()).log(Level.SEVERE, null, ex);
-            }
-        }
-    }//GEN-LAST:event_exportModelButtonMouseClicked
-
-    /**
-     * 
-     * @param evt Changes the backround of the symmetry button
-     */
-    private void jLabel4MouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jLabel4MouseExited
-        jLabel4.setIcon(new javax.swing.ImageIcon(getClass().getResource("/symetryStartP.png")));
-    }//GEN-LAST:event_jLabel4MouseExited
-
-  
-    /**
-     * @param args the command line arguments
-     */
-    public static void main(String args[]) {
-        try {
-            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
-                if ("Nimbus".equals(info.getName())) {
-                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
-                    break;
-                }
-            }
-        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
-            java.util.logging.Logger.getLogger(UserInterface.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
-        }
-        java.awt.EventQueue.invokeLater(() -> {
-            frameMain = new UserInterface();
-            frameMain.setBackground(new Color(49,165,154));
-            frameMain.pack();
-            frameMain.setVisible(true);           
-            //enables to use design of operating system
-            try {
-                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
-            }catch(ClassNotFoundException | IllegalAccessException | InstantiationException | UnsupportedLookAndFeelException ex) {
-            }
-        });
-    }
-    
-
-    
-
-    // Variables declaration - do not modify//GEN-BEGIN:variables
-    private javax.swing.JLabel JLabel10;
-    private javax.swing.JLabel JLabel11;
-    private javax.swing.JLabel JLabel8;
-    private javax.swing.JLabel JLabel9;
-    private javax.swing.JPanel batchMain;
-    private javax.swing.JPanel batchProcessing;
-    private cz.fidentis.analyst.gui.Canvas canvasModelView;
-    private cz.fidentis.analyst.gui.Canvas canvasSymmetryPanel;
-    private javax.swing.JPanel compareDB;
-    private javax.swing.JPanel compareTwo;
-    private javax.swing.JPanel compareTwoMain;
-    private javax.swing.JPanel compareTwoMain1;
-    private javax.swing.JLabel exportModelButton;
-    private javax.swing.Box.Filler filler1;
-    private javax.swing.Box.Filler filler2;
-    private javax.swing.Box.Filler filler3;
-    private javax.swing.Box.Filler filler4;
-    private javax.swing.JLabel homeButton;
-    private javax.swing.JLabel jLabel1;
-    private javax.swing.JLabel jLabel2;
-    private javax.swing.JLabel jLabel3;
-    private javax.swing.JLabel jLabel4;
-    private javax.swing.JPanel jPanel1;
-    private javax.swing.JPanel jPanel2;
-    private javax.swing.JPanel jPanel3;
-    private javax.swing.JPanel jPanel4;
-    private javax.swing.JPanel modelViewPanel;
-    private javax.swing.JLabel newProject;
-    private javax.swing.JLabel reloadModelButton;
-    private javax.swing.JLabel reloadModelButton1;
-    private javax.swing.JPanel startingPanel;
-    private javax.swing.JPanel symetryEstimator;
-    private javax.swing.JPanel symetryMain;
-    private javax.swing.JPanel symetryPanel;
-    private cz.fidentis.analyst.gui.SymmetryPanel symmetryPanel1;
-    private javax.swing.JPanel topPanel;
-    private javax.swing.JLabel viewerButton;
-    private javax.swing.JPanel viewerPanel;
-    private javax.swing.JLabel wiredModelButton;
-    // End of variables declaration//GEN-END:variables
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/Wireframe.java b/GUI/src/main/java/cz/fidentis/analyst/gui/Wireframe.java
deleted file mode 100644
index a3e7abb5413c2a30d69d3f6acf15d36b4a16e581..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/Wireframe.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-package cz.fidentis.analyst.gui;
-
-import java.awt.Color;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import javax.swing.JLabel;
-import org.openide.awt.ActionID;
-import org.openide.awt.ActionReference;
-import org.openide.awt.ActionReferences;
-import org.openide.awt.ActionRegistration;
-import org.openide.util.NbBundle.Messages;
-
-/**
- *
- * @author Richard Pajerský
- * 
- * Wireframe button in toolbar and Edit
- */
-@ActionID(
-        category = "Edit",
-        id = "cz.fidentis.analyst.gui.Wireframe"
-)
-@ActionRegistration(
-        iconBase = "wireframe16x16.png",
-        displayName = "#CTL_Wireframe"
-)
-@ActionReferences({
-    @ActionReference(path = "Menu/Edit", position = 2600, separatorBefore = 2550),
-    @ActionReference(path = "Toolbars/File", position = 300)
-})
-@Messages("CTL_Wireframe=Wireframe")
-public final class Wireframe implements ActionListener {
-
-    /**
-     * Flag for whether model should be displayed as wire-frame 
-     */
-    boolean wiredModelClicked = false;
-    
-    @Override
-    public void actionPerformed(ActionEvent e) {
-        if (wiredModelClicked) {
-            //resetLabelBackround(wiredModelButton);
-            wiredModelClicked = false;
-            Canvas.setDrawWired(wiredModelClicked);
-            /*canvasSymmetryPanel.setDrawWired(wiredModelClicked);
-            canvasModelView.setDrawWired(wiredModelClicked);*/
-        } else {
-            //setLabelBackround(wiredModelButton);
-            wiredModelClicked = true;
-            Canvas.setDrawWired(wiredModelClicked);
-            /*canvasSymmetryPanel.setDrawWired(wiredModelClicked);
-            canvasModelView.setDrawWired(wiredModelClicked);*/
-        }
-    }
-
-    /**
-     * Changes backround of labels to darker green color
-     * @param jl label of which backround changes 
-     */
-    private void setLabelBackround(JLabel jl) {
-        jl.setBackground(new Color(11,56,49));
-    }
-
-    /**
-     * Changes backround of the label back to original
-     * @param jl label of which backround is return to original
-     */
-    private void resetLabelBackround(JLabel jl) {
-        jl.setBackground(new Color(20,114,105));
-    }
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/canvas/Canvas.form b/GUI/src/main/java/cz/fidentis/analyst/gui/canvas/Canvas.form
deleted file mode 100644
index 1c4273533b0c5a475555b30b37ca60567f472bfc..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/canvas/Canvas.form
+++ /dev/null
@@ -1,284 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<Form version="1.9" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
-  <Properties>
-    <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-      <Color blue="0" green="0" red="0" type="rgb"/>
-    </Property>
-  </Properties>
-  <AuxValues>
-    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
-    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
-    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
-    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
-    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
-    <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,93,0,0,1,-79"/>
-  </AuxValues>
-
-  <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
-  <SubComponents>
-    <Container class="javax.swing.JLayeredPane" name="jLayeredPane1">
-      <Properties>
-        <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-          <Color blue="28" green="28" red="28" type="rgb"/>
-        </Property>
-        <Property name="toolTipText" type="java.lang.String" value=""/>
-        <Property name="opaque" type="boolean" value="true"/>
-      </Properties>
-      <Events>
-        <EventHandler event="componentResized" listener="java.awt.event.ComponentListener" parameters="java.awt.event.ComponentEvent" handler="jLayeredPane1ComponentResized"/>
-        <EventHandler event="componentShown" listener="java.awt.event.ComponentListener" parameters="java.awt.event.ComponentEvent" handler="jLayeredPane1ComponentShown"/>
-      </Events>
-      <Constraints>
-        <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
-          <BorderConstraints direction="Center"/>
-        </Constraint>
-      </Constraints>
-
-      <Layout class="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout">
-        <Property name="useNullLayout" type="boolean" value="true"/>
-      </Layout>
-      <SubComponents>
-        <Component class="javax.swing.JLabel" name="resetButton">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/resetButton.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Reset position of model"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseMoved" listener="java.awt.event.MouseMotionListener" parameters="java.awt.event.MouseEvent" handler="resetButtonMouseMoved"/>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="resetButtonMouseClicked"/>
-            <EventHandler event="mouseExited" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="resetButtonMouseExited"/>
-          </Events>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="60" y="40" width="30" height="30"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="javax.swing.JButton" name="upNavigationButton">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/upButton.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Rotate up"/>
-            <Property name="borderPainted" type="boolean" value="false"/>
-            <Property name="contentAreaFilled" type="boolean" value="false"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="upNavigationButtonMousePressed"/>
-            <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="upNavigationButtonMouseReleased"/>
-          </Events>
-          <AuxValues>
-            <AuxValue name="JLayeredPane.layer" type="java.lang.Integer" value="200"/>
-          </AuxValues>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="60" y="10" width="30" height="30"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="javax.swing.JButton" name="leftNavigationButton">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/leftButton.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Rotate left"/>
-            <Property name="borderPainted" type="boolean" value="false"/>
-            <Property name="contentAreaFilled" type="boolean" value="false"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="leftNavigationButtonMousePressed"/>
-            <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="leftNavigationButtonMouseReleased"/>
-          </Events>
-          <AuxValues>
-            <AuxValue name="JLayeredPane.layer" type="java.lang.Integer" value="200"/>
-          </AuxValues>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="30" y="40" width="30" height="30"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="javax.swing.JButton" name="minusNavigationButton">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/minus.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Zoom out"/>
-            <Property name="borderPainted" type="boolean" value="false"/>
-            <Property name="contentAreaFilled" type="boolean" value="false"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="minusNavigationButtonMousePressed"/>
-            <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="minusNavigationButtonMouseReleased"/>
-          </Events>
-          <AuxValues>
-            <AuxValue name="JLayeredPane.layer" type="java.lang.Integer" value="200"/>
-          </AuxValues>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="90" y="90" width="30" height="30"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="javax.swing.JButton" name="downNavigationButton">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/downButton.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Rotate down"/>
-            <Property name="borderPainted" type="boolean" value="false"/>
-            <Property name="contentAreaFilled" type="boolean" value="false"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="downNavigationButtonMousePressed"/>
-            <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="downNavigationButtonMouseReleased"/>
-          </Events>
-          <AuxValues>
-            <AuxValue name="JLayeredPane.layer" type="java.lang.Integer" value="200"/>
-          </AuxValues>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="60" y="70" width="30" height="30"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="javax.swing.JButton" name="plusNavigationButton">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/plus.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Zoom in"/>
-            <Property name="borderPainted" type="boolean" value="false"/>
-            <Property name="contentAreaFilled" type="boolean" value="false"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="plusNavigationButtonMousePressed"/>
-            <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="plusNavigationButtonMouseReleased"/>
-          </Events>
-          <AuxValues>
-            <AuxValue name="JLayeredPane.layer" type="java.lang.Integer" value="200"/>
-          </AuxValues>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="30" y="90" width="30" height="30"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="javax.swing.JLabel" name="jLabel1">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/navigBackground.png"/>
-            </Property>
-          </Properties>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="30" y="10" width="90" height="90"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="javax.swing.JButton" name="rightNavigationButton1">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/rightButton.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Rotate right"/>
-            <Property name="borderPainted" type="boolean" value="false"/>
-            <Property name="contentAreaFilled" type="boolean" value="false"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="rightNavigationButton1MousePressed"/>
-            <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="rightNavigationButton1MouseReleased"/>
-          </Events>
-          <AuxValues>
-            <AuxValue name="JLayeredPane.layer" type="java.lang.Integer" value="200"/>
-          </AuxValues>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="90" y="40" width="30" height="30"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="javax.swing.JLabel" name="whiteBackroundButton">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/whiteBackroundCanvas.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="White backround"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="whiteBackroundButtonMouseClicked"/>
-          </Events>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="50" y="130" width="-1" height="-1"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Component class="javax.swing.JLabel" name="blackBackroundButton">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/blackBackroundCanvas.png"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" value="Dark background"/>
-            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-              <Color id="Hand Cursor"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="blackBackroundButtonMouseClicked"/>
-          </Events>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="50" y="190" width="-1" height="-1"/>
-            </Constraint>
-          </Constraints>
-        </Component>
-        <Container class="javax.swing.JPanel" name="jPanel1">
-          <Properties>
-            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="0" green="0" red="0" type="rgb"/>
-            </Property>
-          </Properties>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-              <AbsoluteConstraints x="0" y="0" width="-1" height="-1"/>
-            </Constraint>
-          </Constraints>
-
-          <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
-        </Container>
-      </SubComponents>
-    </Container>
-  </SubComponents>
-</Form>
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/canvas/Canvas.java b/GUI/src/main/java/cz/fidentis/analyst/gui/canvas/Canvas.java
deleted file mode 100644
index 81ce86d712057ffc40470216b5f060beefeff859..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/canvas/Canvas.java
+++ /dev/null
@@ -1,457 +0,0 @@
-package cz.fidentis.analyst.gui.canvas;
-
-import com.jogamp.opengl.GLCapabilities;
-import com.jogamp.opengl.GLProfile;
-import com.jogamp.opengl.awt.GLCanvas;
-import cz.fidentis.analyst.face.HumanFace;
-import cz.fidentis.analyst.gui.scene.Camera;
-import cz.fidentis.analyst.gui.scene.Scene;
-import cz.fidentis.analyst.gui.scene.SceneRenderer;
-
-import java.awt.Color;
-import java.awt.Cursor;
-
-/**
- * OpenGL canvas.
- * 
- * @author Natalia Bebjakova 
- * @author Radek Oslejsek
- */
-public class Canvas extends javax.swing.JPanel {
-    
-    private final GLCanvas glCanvas;
-    private final SceneRenderer sceneRenderer;
-    private final Camera camera = new Camera();
-    private Scene scene;
-    
-    // Listeners:
-    private final CanvasListener listener;
-    private final MouseRotationListener manipulator;
-    private final RotationAnimator animator;
-    
-    
-    /**
-     * Constructor.
-     */
-    public Canvas() {
-        initComponents();
-        
-        // gl version 2 is used
-        GLCapabilities capabilities = new GLCapabilities(GLProfile.get(GLProfile.GL2));
-        capabilities.setDoubleBuffered(true);
-       
-        // creates new glCanvas panel for displaying model
-        glCanvas = new GLCanvas(capabilities);
-        jPanel1.add(glCanvas);
-        glCanvas.setVisible(true);     
-        glCanvas.setBackground(Color.black);
-        
-        // enables glCanvas to react to events
-        glCanvas.requestFocusInWindow();        
-        glCanvas.setSize(getWidth() - getInsets().left - getInsets().right, getHeight() - getInsets().top - getInsets().bottom);
-       
-        sceneRenderer = new SceneRenderer();
-        
-        animator = new RotationAnimator(this.glCanvas, this.camera);
-        
-        listener = new CanvasListener(this);
-        glCanvas.addGLEventListener(listener);
-        
-        manipulator = new MouseRotationListener(this);
-        glCanvas.addMouseListener(manipulator);
-        glCanvas.addMouseMotionListener(manipulator);
-        glCanvas.addMouseWheelListener(manipulator);
-        
-        this.validate();   
-    }
-    
-    /**
-     * Initializes the scene for a single face. Can be called only once.
-     * 
-     * @param face Human face
-     * @throws UnsupportedOperationException the the scene is already initiated
-     * @throws IllegalArgumentException if the face is missing
-     */
-    public void initScene(HumanFace face) {
-        if (scene != null) {
-            throw new UnsupportedOperationException("Scene already exists");
-        }
-        this.scene = new Scene(face);
-    }
-    
-    /**
-     * Initializes the scene for the 1:1 comparison. Can be called only once.
-     * 
-     * @param face Human face
-     * @throws UnsupportedOperationException the the scene is already initiated
-     * @throws IllegalArgumentException if some face is missing
-     */
-    public void initScene(HumanFace primary, HumanFace secondary) {
-        if (scene != null) {
-            throw new UnsupportedOperationException("Scene already exists");
-        }
-        this.scene = new Scene(primary, secondary);
-    }
-   
-    /**
-     * Returns the scene
-     * @return the scene
-     */
-    public SceneRenderer getSceneRenderer() {
-        return sceneRenderer;
-    }
-    
-    public void renderScene() {
-        glCanvas.display();
-    }
-    
-    /**
-     * Returns the scene. 
-     * 
-     * @return the scene.
-     */
-    public Scene getScene() {
-        return scene;
-    }
-    
-    /**
-     * Returns camera. 
-     * 
-     * @return camera
-     */
-    public Camera getCamera() {
-        return camera;
-    }
-    
-    /**
-     * Returns the underlying OpenGL canvas.
-     * 
-     * @return the underlying OpenGL canvas.
-     */
-    /*
-    public GLCanvas getGLCanvas() {
-        return this.glCanvas;
-    }
-    */
-    
-    /**
-     * Changing the size of glCanvas
-     * 
-     * @param d New size of glCanvas
-     */
-    /*
-    public void resizeCanvas(Dimension d) {
-        jPanel1.setSize(d);
-        glCanvas.setSize(d);
-        this.validate();
-        this.repaint();
-    }
-    */
-    
-    /**
-     * This method is called from within the constructor to initialize the form.
-     * WARNING: Do NOT modify this code. The content of this method is always
-     * regenerated by the Form Editor.
-     * 
-     * Generated code from NetBeans
-     */
-    @SuppressWarnings("unchecked")
-    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
-    private void initComponents() {
-
-        jLayeredPane1 = new javax.swing.JLayeredPane();
-        resetButton = new javax.swing.JLabel();
-        upNavigationButton = new javax.swing.JButton();
-        leftNavigationButton = new javax.swing.JButton();
-        minusNavigationButton = new javax.swing.JButton();
-        downNavigationButton = new javax.swing.JButton();
-        plusNavigationButton = new javax.swing.JButton();
-        jLabel1 = new javax.swing.JLabel();
-        rightNavigationButton1 = new javax.swing.JButton();
-        whiteBackroundButton = new javax.swing.JLabel();
-        blackBackroundButton = new javax.swing.JLabel();
-        jPanel1 = new javax.swing.JPanel();
-
-        setBackground(new java.awt.Color(0, 0, 0));
-        setLayout(new java.awt.BorderLayout());
-
-        jLayeredPane1.setBackground(new java.awt.Color(40, 40, 40));
-        jLayeredPane1.setToolTipText("");
-        jLayeredPane1.setOpaque(true);
-        jLayeredPane1.addComponentListener(new java.awt.event.ComponentAdapter() {
-            public void componentResized(java.awt.event.ComponentEvent evt) {
-                jLayeredPane1ComponentResized(evt);
-            }
-            public void componentShown(java.awt.event.ComponentEvent evt) {
-                jLayeredPane1ComponentShown(evt);
-            }
-        });
-
-        resetButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resetButton.png"))); // NOI18N
-        resetButton.setToolTipText("Reset position of model");
-        resetButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        resetButton.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
-            public void mouseMoved(java.awt.event.MouseEvent evt) {
-                resetButtonMouseMoved(evt);
-            }
-        });
-        resetButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                resetButtonMouseClicked(evt);
-            }
-            public void mouseExited(java.awt.event.MouseEvent evt) {
-                resetButtonMouseExited(evt);
-            }
-        });
-        jLayeredPane1.add(resetButton);
-        resetButton.setBounds(60, 40, 30, 30);
-
-        upNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/upButton.png"))); // NOI18N
-        upNavigationButton.setToolTipText("Rotate up");
-        upNavigationButton.setBorderPainted(false);
-        upNavigationButton.setContentAreaFilled(false);
-        upNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        upNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mousePressed(java.awt.event.MouseEvent evt) {
-                upNavigationButtonMousePressed(evt);
-            }
-            public void mouseReleased(java.awt.event.MouseEvent evt) {
-                upNavigationButtonMouseReleased(evt);
-            }
-        });
-        jLayeredPane1.setLayer(upNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
-        jLayeredPane1.add(upNavigationButton);
-        upNavigationButton.setBounds(60, 10, 30, 30);
-
-        leftNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/leftButton.png"))); // NOI18N
-        leftNavigationButton.setToolTipText("Rotate left");
-        leftNavigationButton.setBorderPainted(false);
-        leftNavigationButton.setContentAreaFilled(false);
-        leftNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        leftNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mousePressed(java.awt.event.MouseEvent evt) {
-                leftNavigationButtonMousePressed(evt);
-            }
-            public void mouseReleased(java.awt.event.MouseEvent evt) {
-                leftNavigationButtonMouseReleased(evt);
-            }
-        });
-        jLayeredPane1.setLayer(leftNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
-        jLayeredPane1.add(leftNavigationButton);
-        leftNavigationButton.setBounds(30, 40, 30, 30);
-
-        minusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/minus.png"))); // NOI18N
-        minusNavigationButton.setToolTipText("Zoom out");
-        minusNavigationButton.setBorderPainted(false);
-        minusNavigationButton.setContentAreaFilled(false);
-        minusNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        minusNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mousePressed(java.awt.event.MouseEvent evt) {
-                minusNavigationButtonMousePressed(evt);
-            }
-            public void mouseReleased(java.awt.event.MouseEvent evt) {
-                minusNavigationButtonMouseReleased(evt);
-            }
-        });
-        jLayeredPane1.setLayer(minusNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
-        jLayeredPane1.add(minusNavigationButton);
-        minusNavigationButton.setBounds(90, 90, 30, 30);
-
-        downNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/downButton.png"))); // NOI18N
-        downNavigationButton.setToolTipText("Rotate down");
-        downNavigationButton.setBorderPainted(false);
-        downNavigationButton.setContentAreaFilled(false);
-        downNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        downNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mousePressed(java.awt.event.MouseEvent evt) {
-                downNavigationButtonMousePressed(evt);
-            }
-            public void mouseReleased(java.awt.event.MouseEvent evt) {
-                downNavigationButtonMouseReleased(evt);
-            }
-        });
-        jLayeredPane1.setLayer(downNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
-        jLayeredPane1.add(downNavigationButton);
-        downNavigationButton.setBounds(60, 70, 30, 30);
-
-        plusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/plus.png"))); // NOI18N
-        plusNavigationButton.setToolTipText("Zoom in");
-        plusNavigationButton.setBorderPainted(false);
-        plusNavigationButton.setContentAreaFilled(false);
-        plusNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        plusNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mousePressed(java.awt.event.MouseEvent evt) {
-                plusNavigationButtonMousePressed(evt);
-            }
-            public void mouseReleased(java.awt.event.MouseEvent evt) {
-                plusNavigationButtonMouseReleased(evt);
-            }
-        });
-        jLayeredPane1.setLayer(plusNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
-        jLayeredPane1.add(plusNavigationButton);
-        plusNavigationButton.setBounds(30, 90, 30, 30);
-
-        jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/navigBackground.png"))); // NOI18N
-        jLayeredPane1.add(jLabel1);
-        jLabel1.setBounds(30, 10, 90, 90);
-
-        rightNavigationButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/rightButton.png"))); // NOI18N
-        rightNavigationButton1.setToolTipText("Rotate right");
-        rightNavigationButton1.setBorderPainted(false);
-        rightNavigationButton1.setContentAreaFilled(false);
-        rightNavigationButton1.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        rightNavigationButton1.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mousePressed(java.awt.event.MouseEvent evt) {
-                rightNavigationButton1MousePressed(evt);
-            }
-            public void mouseReleased(java.awt.event.MouseEvent evt) {
-                rightNavigationButton1MouseReleased(evt);
-            }
-        });
-        jLayeredPane1.setLayer(rightNavigationButton1, javax.swing.JLayeredPane.MODAL_LAYER);
-        jLayeredPane1.add(rightNavigationButton1);
-        rightNavigationButton1.setBounds(90, 40, 30, 30);
-
-        whiteBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/whiteBackroundCanvas.png"))); // NOI18N
-        whiteBackroundButton.setToolTipText("White backround");
-        whiteBackroundButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        whiteBackroundButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                whiteBackroundButtonMouseClicked(evt);
-            }
-        });
-        jLayeredPane1.add(whiteBackroundButton);
-        whiteBackroundButton.setBounds(50, 130, 56, 56);
-
-        blackBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/blackBackroundCanvas.png"))); // NOI18N
-        blackBackroundButton.setToolTipText("Dark background");
-        blackBackroundButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        blackBackroundButton.addMouseListener(new java.awt.event.MouseAdapter() {
-            public void mouseClicked(java.awt.event.MouseEvent evt) {
-                blackBackroundButtonMouseClicked(evt);
-            }
-        });
-        jLayeredPane1.add(blackBackroundButton);
-        blackBackroundButton.setBounds(50, 190, 56, 56);
-
-        jPanel1.setBackground(new java.awt.Color(0, 0, 0));
-        jPanel1.setLayout(new java.awt.BorderLayout());
-        jLayeredPane1.add(jPanel1);
-        jPanel1.setBounds(0, 0, 0, 0);
-
-        add(jLayeredPane1, java.awt.BorderLayout.CENTER);
-    }// </editor-fold>//GEN-END:initComponents
-
-    private void jLayeredPane1ComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_jLayeredPane1ComponentResized
-        jPanel1.setBounds(0, 0, jLayeredPane1.getWidth(), jLayeredPane1.getHeight());
-        glCanvas.setBounds(jLayeredPane1.getX(), jLayeredPane1.getY(), jLayeredPane1.getWidth(), jLayeredPane1.getHeight());
-    }//GEN-LAST:event_jLayeredPane1ComponentResized
-
-    private void jLayeredPane1ComponentShown(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_jLayeredPane1ComponentShown
-        jPanel1.setBounds(0, 0, jLayeredPane1.getWidth(), jLayeredPane1.getHeight());
-        glCanvas.setBounds(jLayeredPane1.getX(), jLayeredPane1.getY(), jLayeredPane1.getWidth(), jLayeredPane1.getHeight());
-    }//GEN-LAST:event_jLayeredPane1ComponentShown
-
-    private void leftNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftNavigationButtonMousePressed
-        animator.startAnimation(RotationAnimator.Direction.ROTATE_LEFT);
-        leftNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/leftButtonPressed.png")));
-    }//GEN-LAST:event_leftNavigationButtonMousePressed
-
-    private void upNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_upNavigationButtonMousePressed
-        animator.startAnimation(RotationAnimator.Direction.ROTATE_UP);
-        upNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/upButtonPressed.png")));
-    }//GEN-LAST:event_upNavigationButtonMousePressed
-
-    private void downNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_downNavigationButtonMousePressed
-        animator.startAnimation(RotationAnimator.Direction.ROTATE_DOWN);
-        downNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/downButtonPressed.png")));
-    }//GEN-LAST:event_downNavigationButtonMousePressed
-
-    private void plusNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_plusNavigationButtonMousePressed
-        animator.startAnimation(RotationAnimator.Direction.ZOOM_IN);
-        plusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/plusPressed.png")));
-    }//GEN-LAST:event_plusNavigationButtonMousePressed
- 
-    private void minusNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_minusNavigationButtonMousePressed
-        animator.startAnimation(RotationAnimator.Direction.ZOOM_OUT);
-        minusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/minusPressed.png")));
-    }//GEN-LAST:event_minusNavigationButtonMousePressed
-
-    private void leftNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftNavigationButtonMouseReleased
-        animator.stopAnimation();
-        leftNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/leftButton.png")));
-    }//GEN-LAST:event_leftNavigationButtonMouseReleased
-
-    private void upNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_upNavigationButtonMouseReleased
-        animator.stopAnimation();
-        upNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/upButton.png")));
-    }//GEN-LAST:event_upNavigationButtonMouseReleased
-
-    private void downNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_downNavigationButtonMouseReleased
-        animator.stopAnimation();
-        downNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/downButton.png")));
-    }//GEN-LAST:event_downNavigationButtonMouseReleased
-
-    private void plusNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_plusNavigationButtonMouseReleased
-        animator.stopAnimation();
-        plusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/plus.png")));
-    }//GEN-LAST:event_plusNavigationButtonMouseReleased
-
-    private void minusNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_minusNavigationButtonMouseReleased
-        animator.stopAnimation();
-        minusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/minus.png")));
-    }//GEN-LAST:event_minusNavigationButtonMouseReleased
-
-    private void rightNavigationButton1MousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightNavigationButton1MousePressed
-        animator.startAnimation(RotationAnimator.Direction.ROTATE_RIGHT);
-        rightNavigationButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/rightButtonPressed.png")));
-    }//GEN-LAST:event_rightNavigationButton1MousePressed
-
-    private void rightNavigationButton1MouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightNavigationButton1MouseReleased
-        animator.stopAnimation();
-        rightNavigationButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/rightButton.png")));
-    }//GEN-LAST:event_rightNavigationButton1MouseReleased
-
-    private void resetButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_resetButtonMouseClicked
-        camera.initLocation();
-        renderScene();
-    }//GEN-LAST:event_resetButtonMouseClicked
-
-    private void resetButtonMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_resetButtonMouseMoved
-        resetButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resetButtonPressed.png")));
-        resetButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
-    }//GEN-LAST:event_resetButtonMouseMoved
-
-    private void resetButtonMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_resetButtonMouseExited
-        resetButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resetButton.png")));
-    }//GEN-LAST:event_resetButtonMouseExited
-
-    private void whiteBackroundButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_whiteBackroundButtonMouseClicked
-        sceneRenderer.setBrightBackground();
-        renderScene();
-        whiteBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/whiteBackroundCanvasPressed.png")));
-        blackBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/blackBackroundCanvas.png")));
-    }//GEN-LAST:event_whiteBackroundButtonMouseClicked
-
-    private void blackBackroundButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_blackBackroundButtonMouseClicked
-        sceneRenderer.setDarkBackground();
-        renderScene();
-        whiteBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/whiteBackroundCanvas.png")));
-        blackBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/blackBackroundCanvasPressed.png")));
-    }//GEN-LAST:event_blackBackroundButtonMouseClicked
-
-    // Variables declaration - do not modify//GEN-BEGIN:variables
-    private javax.swing.JLabel blackBackroundButton;
-    private javax.swing.JButton downNavigationButton;
-    private javax.swing.JLabel jLabel1;
-    private javax.swing.JLayeredPane jLayeredPane1;
-    private javax.swing.JPanel jPanel1;
-    private javax.swing.JButton leftNavigationButton;
-    private javax.swing.JButton minusNavigationButton;
-    private javax.swing.JButton plusNavigationButton;
-    private javax.swing.JLabel resetButton;
-    private javax.swing.JButton rightNavigationButton1;
-    private javax.swing.JButton upNavigationButton;
-    private javax.swing.JLabel whiteBackroundButton;
-    // End of variables declaration//GEN-END:variables
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/scene/DrawableMesh.java b/GUI/src/main/java/cz/fidentis/analyst/gui/scene/DrawableMesh.java
deleted file mode 100644
index 82ee9db24d6e7ef5225cf62368aee9d17f1b3c04..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/scene/DrawableMesh.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package cz.fidentis.analyst.gui.scene;
-
-import cz.fidentis.analyst.mesh.core.MeshFacet;
-import cz.fidentis.analyst.mesh.core.MeshModel;
-import java.util.List;
-
-/**
- * A drawable triangular mesh, i.e., a mesh model with drawing information like 
- * material, transparency, color, relative transformations in the scene etc. 
- * This class encapsulates rendering state and parameters,
- * 
- * @author Radek Oslejsek
- */
-public class DrawableMesh {
-    
-    private final MeshModel model;
-    
-    private boolean display = true;
-    
-    // TO DO - R. Pajersky: add transformation attributes and methods
-    
-    /**
-     * Constructor. 
-     * 
-     * @param model Drawable mesh model
-     * @throws IllegalArgumentException if the model is {@code null}
-     */
-    public DrawableMesh(MeshModel model) {
-        if (model == null) {
-            throw new IllegalArgumentException("model is null");
-        }
-        this.model = model;
-    }
-    
-    /**
-     * Returns list of individual facets.
-     * 
-     * @return list of individual facets.
-     */
-    public List<MeshFacet> getFacets() {
-        return model.getFacets();
-    }
-    
-    /**
-     * This drawable mesh is included in the rendered scene.
-     */
-    public void show() {
-        display = true;
-    }
-    
-    /**
-     * This drawable mesh is excluded from the rendered scene (skipped).
-     */
-    public void hide() {
-        display = false;
-    }
-    
-    /**
-     * 
-     * @return {@code true} if the object is included (rendered) in the scene.
-     */
-    public boolean isShown() {
-        return display;
-    }
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/scene/Scene.java b/GUI/src/main/java/cz/fidentis/analyst/gui/scene/Scene.java
deleted file mode 100644
index 0dd610263992e6b0a42292246d252ebf7b36dd41..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/scene/Scene.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package cz.fidentis.analyst.gui.scene;
-
-import cz.fidentis.analyst.face.HumanFace;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Abstract class for ...
- * 
- * @author Radek Oslejsek
- */
-public class Scene {
-    
-    private final HumanFace primaryFace;
-    
-    private final HumanFace secondaryFace ;
-    
-    private final List<DrawableMesh> drawables=  new ArrayList<>();
-    
-    /**
-     * Constructor for single face analysis.
-     * 
-     * @param face Human face to be analyzed
-     * @throws IllegalArgumentException if the {@code face} is {@code null}
-     */
-    public Scene(HumanFace face) {
-        if (face == null) {
-            throw new IllegalArgumentException("face");
-        }
-        this.primaryFace = face;
-        this.secondaryFace = null;
-        
-        drawables.add(new DrawableMesh(primaryFace.getMeshModel()));
-    }
-    
-    /**
-     * Constructor for one-to-one analysis.
-     * 
-     * @param primary Primary face to be analyzed
-     * @param primary Secondary face to be analyzed
-     * @throws IllegalArgumentException if some face is {@code null}
-     */
-    public Scene(HumanFace primary, HumanFace secondary) {
-        if (primary == null) {
-            throw new IllegalArgumentException("primary");
-        }
-        if (secondary == null) {
-            throw new IllegalArgumentException("secondary");
-        }
-        this.primaryFace = primary;
-        this.secondaryFace = secondary;
-        
-        drawables.add(new DrawableMesh(primaryFace.getMeshModel()));
-        drawables.add(new DrawableMesh(secondaryFace.getMeshModel()));
-    }
-    
-    /**
-     * Returns all drawable objects in a modifiable collection (should be refactored in the future).
-     * 
-     * @return all drawable objects 
-     */
-    public Collection<DrawableMesh> getDrawables() {
-        return this.drawables;
-    }
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/tab/SingleFaceTab.form b/GUI/src/main/java/cz/fidentis/analyst/gui/tab/SingleFaceTab.form
deleted file mode 100644
index cebe2c58f760e41ebae4086d6afc2f22201b7e1e..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/tab/SingleFaceTab.form
+++ /dev/null
@@ -1,80 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<!--
-
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing,
-    software distributed under the License is distributed on an
-    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-    KIND, either express or implied.  See the License for the
-    specific language governing permissions and limitations
-    under the License.
-
--->
-
-<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
-  <AuxValues>
-    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
-    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
-    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
-    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
-    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
-    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
-    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
-  </AuxValues>
-
-  <Layout>
-    <DimensionLayout dim="0">
-      <Group type="103" groupAlignment="0" attributes="0">
-          <Component id="jToolBar1" pref="685" max="32767" attributes="0"/>
-          <Component id="canvas1" alignment="0" max="32767" attributes="0"/>
-      </Group>
-    </DimensionLayout>
-    <DimensionLayout dim="1">
-      <Group type="103" groupAlignment="0" attributes="0">
-          <Group type="102" attributes="0">
-              <Component id="jToolBar1" min="-2" max="-2" attributes="0"/>
-              <EmptySpace max="-2" attributes="0"/>
-              <Component id="canvas1" pref="434" max="32767" attributes="0"/>
-          </Group>
-      </Group>
-    </DimensionLayout>
-  </Layout>
-  <SubComponents>
-    <Component class="cz.fidentis.analyst.gui.canvas.Canvas" name="canvas1">
-    </Component>
-    <Container class="javax.swing.JToolBar" name="jToolBar1">
-      <Properties>
-        <Property name="rollover" type="boolean" value="true"/>
-      </Properties>
-
-      <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>
-      <SubComponents>
-        <Component class="javax.swing.JButton" name="jButton1">
-          <Properties>
-            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-              <Image iconType="3" name="/wireframe16x1624.png"/>
-            </Property>
-            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-              <ResourceString bundle="cz/fidentis/analyst/newgui/swing/Bundle.properties" key="SingleFaceTab.jButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-            </Property>
-            <Property name="focusable" type="boolean" value="false"/>
-            <Property name="horizontalTextPosition" type="int" value="0"/>
-            <Property name="verticalTextPosition" type="int" value="3"/>
-          </Properties>
-        </Component>
-      </SubComponents>
-    </Container>
-  </SubComponents>
-</Form>
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/tab/SingleFaceTab.java b/GUI/src/main/java/cz/fidentis/analyst/gui/tab/SingleFaceTab.java
deleted file mode 100644
index 60e82105374ed069fdcaf4b5a0d33ac2bc84ca6d..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/tab/SingleFaceTab.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package cz.fidentis.analyst.gui.tab;
-
-import cz.fidentis.analyst.gui.canvas.Canvas;
-import org.netbeans.api.settings.ConvertAsProperties;
-import org.openide.windows.TopComponent;
-
-/**
- * The non-singleton window/tab for detail inspection of a single face.
- * For the discussion on crating non-singleton top component, 
- * see {@link http://netbeans.apache.org/wiki/DevFaqNonSingletonTopComponents.asciidoc}.
- *
- * @author Richard Pajersky
- */
-@ConvertAsProperties(
-        dtd = "-//cz.fidentis.analyst.gui.tab//SingleFaceTab//EN",
-        autostore = false
-)
-public final class SingleFaceTab extends TopComponent {
-
-    /**
-     * Constructor.
-     */
-    public SingleFaceTab() {
-        initComponents();
-    }
-    
-    @Override
-    public int getPersistenceType() {
-        return TopComponent.PERSISTENCE_NEVER; // TO DO: change to .PERSISTENCE_ONLY_OPENED when we can re-create the ProjectTC
-    }
-
-    /**
-     * This method is called from within the constructor to initialize the form.
-     * WARNING: Do NOT modify this code. The content of this method is always
-     * regenerated by the Form Editor.
-     */
-    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
-    private void initComponents() {
-
-        canvas1 = new cz.fidentis.analyst.gui.canvas.Canvas();
-        jToolBar1 = new javax.swing.JToolBar();
-        jButton1 = new javax.swing.JButton();
-
-        jToolBar1.setRollover(true);
-
-        jButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/wireframe16x1624.png"))); // NOI18N
-        org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(SingleFaceTab.class, "SingleFaceTab.jButton1.text")); // NOI18N
-        jButton1.setFocusable(false);
-        jButton1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
-        jButton1.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
-        jToolBar1.add(jButton1);
-
-        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
-        this.setLayout(layout);
-        layout.setHorizontalGroup(
-            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 685, Short.MAX_VALUE)
-            .addComponent(canvas1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-        );
-        layout.setVerticalGroup(
-            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(layout.createSequentialGroup()
-                .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                .addComponent(canvas1, javax.swing.GroupLayout.DEFAULT_SIZE, 434, Short.MAX_VALUE))
-        );
-    }// </editor-fold>//GEN-END:initComponents
-
-    // Variables declaration - do not modify//GEN-BEGIN:variables
-    private cz.fidentis.analyst.gui.canvas.Canvas canvas1;
-    private javax.swing.JButton jButton1;
-    private javax.swing.JToolBar jToolBar1;
-    // End of variables declaration//GEN-END:variables
-    @Override
-    public void componentOpened() {
-        // TODO add custom code on component opening
-    }
-
-    @Override
-    public void componentClosed() {
-        // TODO add custom code on component closing
-    }
-
-    void writeProperties(java.util.Properties p) {
-        // better to version settings since initial version as advocated at
-        // http://wiki.apidesign.org/wiki/PropertyFiles
-        p.setProperty("version", "1.0");
-        // TODO store your settings
-    }
-
-    void readProperties(java.util.Properties p) {
-        String version = p.getProperty("version");
-        // TODO read your settings according to their version
-    }
-    
-    public Canvas getCanvas() {
-        return canvas1;
-    }
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/options/TestOptionsPanelController.java b/GUI/src/main/java/cz/fidentis/analyst/options/TestOptionsPanelController.java
new file mode 100644
index 0000000000000000000000000000000000000000..f9e474f30e8d3b1eed05ff04484041b1a3c4594b
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/options/TestOptionsPanelController.java
@@ -0,0 +1,95 @@
+package cz.fidentis.analyst.options;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import javax.swing.JComponent;
+import javax.swing.SwingUtilities;
+import org.netbeans.spi.options.OptionsPanelController;
+import org.openide.util.HelpCtx;
+import org.openide.util.Lookup;
+
+/**
+ * Generated from NetBeans (secondary Option Panel).
+ * 
+ * @author Radek Oslejsek
+ */
+@OptionsPanelController.SubRegistration(
+        displayName = "#AdvancedOption_DisplayName_Test",
+        keywords = "#AdvancedOption_Keywords_Test",
+        keywordsCategory = "Advanced/Test"
+)
+@org.openide.util.NbBundle.Messages({"AdvancedOption_DisplayName_Test=Test", "AdvancedOption_Keywords_Test=test"})
+public final class TestOptionsPanelController extends OptionsPanelController {
+
+    private TestPanel panel;
+    private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
+    private boolean changed;
+
+    @Override
+    public void update() {
+        getPanel().load();
+        changed = false;
+    }
+
+    @Override
+    public void applyChanges() {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                getPanel().store();
+                changed = false;
+            }
+        });
+    }
+
+    @Override
+    public void cancel() {
+        // need not do anything special, if no changes have been persisted yet
+    }
+
+    @Override
+    public boolean isValid() {
+        return getPanel().valid();
+    }
+
+    @Override
+    public boolean isChanged() {
+        return changed;
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return null; // new HelpCtx("...ID") if you have a help set
+    }
+
+    @Override
+    public JComponent getComponent(Lookup masterLookup) {
+        return getPanel();
+    }
+
+    @Override
+    public void addPropertyChangeListener(PropertyChangeListener l) {
+        pcs.addPropertyChangeListener(l);
+    }
+
+    @Override
+    public void removePropertyChangeListener(PropertyChangeListener l) {
+        pcs.removePropertyChangeListener(l);
+    }
+
+    private TestPanel getPanel() {
+        if (panel == null) {
+            panel = new TestPanel(this);
+        }
+        return panel;
+    }
+
+    void changed() {
+        if (!changed) {
+            changed = true;
+            pcs.firePropertyChange(OptionsPanelController.PROP_CHANGED, false, true);
+        }
+        pcs.firePropertyChange(OptionsPanelController.PROP_VALID, null, null);
+    }
+
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/CanvasTopComponent.form b/GUI/src/main/java/cz/fidentis/analyst/options/TestPanel.form
similarity index 67%
rename from GUI/src/main/java/cz/fidentis/analyst/gui/CanvasTopComponent.form
rename to GUI/src/main/java/cz/fidentis/analyst/options/TestPanel.form
index 45c7d46376fe40d322bbbd95864b70b68d1d9fa4..1ebf417cc58919ab5d74b10cdb7c91ad2a4c5252 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/CanvasTopComponent.form
+++ b/GUI/src/main/java/cz/fidentis/analyst/options/TestPanel.form
@@ -21,7 +21,7 @@
 
 -->
 
-<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   <AuxValues>
     <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
     <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
@@ -37,31 +37,30 @@
   <Layout>
     <DimensionLayout dim="0">
       <Group type="103" groupAlignment="0" attributes="0">
-          <EmptySpace min="0" pref="575" max="32767" attributes="0"/>
-          <Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
-              <Group type="102" alignment="0" attributes="0">
-                  <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
-                  <Component id="canvas1" max="32767" attributes="0"/>
-                  <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
-              </Group>
+          <Group type="102" alignment="0" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
+              <EmptySpace pref="143" max="32767" attributes="0"/>
           </Group>
       </Group>
     </DimensionLayout>
     <DimensionLayout dim="1">
       <Group type="103" groupAlignment="0" attributes="0">
-          <EmptySpace min="0" pref="411" max="32767" attributes="0"/>
-          <Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
-              <Group type="102" alignment="0" attributes="0">
-                  <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
-                  <Component id="canvas1" max="32767" attributes="0"/>
-                  <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
-              </Group>
+          <Group type="102" alignment="0" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
+              <EmptySpace pref="38" max="32767" attributes="0"/>
           </Group>
       </Group>
     </DimensionLayout>
   </Layout>
   <SubComponents>
-    <Component class="cz.fidentis.analyst.gui.Canvas" name="canvas1">
+    <Component class="javax.swing.JLabel" name="jLabel1">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="cz/fidentis/analyst/options/Bundle.properties" key="TestPanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
     </Component>
   </SubComponents>
 </Form>
diff --git a/GUI/src/main/java/cz/fidentis/analyst/options/TestPanel.java b/GUI/src/main/java/cz/fidentis/analyst/options/TestPanel.java
new file mode 100644
index 0000000000000000000000000000000000000000..54c09e3c0fba88e5cc4447695f160c6a55212648
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/options/TestPanel.java
@@ -0,0 +1,77 @@
+package cz.fidentis.analyst.options;
+
+/**
+ * Test option panel. To be replaced with suitable implementation(s)
+ * Generated from NetBeans (secondary Option Panel)
+ * 
+ * @author Radek Oslejsek
+ */
+final class TestPanel extends javax.swing.JPanel {
+
+    private final TestOptionsPanelController controller;
+
+    TestPanel(TestOptionsPanelController controller) {
+        this.controller = controller;
+        initComponents();
+        // TODO listen to changes in form fields and call controller.changed()
+    }
+
+    /**
+     * This method is called from within the constructor to initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is always
+     * regenerated by the Form Editor.
+     */
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        jLabel1 = new javax.swing.JLabel();
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(TestPanel.class, "TestPanel.jLabel1.text")); // NOI18N
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addContainerGap()
+                .addComponent(jLabel1)
+                .addContainerGap(143, Short.MAX_VALUE))
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addContainerGap()
+                .addComponent(jLabel1)
+                .addContainerGap(38, Short.MAX_VALUE))
+        );
+    }// </editor-fold>//GEN-END:initComponents
+
+    void load() {
+        // TODO read settings and initialize GUI
+        // Example:        
+        // someCheckBox.setSelected(Preferences.userNodeForPackage(TestPanel.class).getBoolean("someFlag", false));
+        // or for org.openide.util with API spec. version >= 7.4:
+        // someCheckBox.setSelected(NbPreferences.forModule(TestPanel.class).getBoolean("someFlag", false));
+        // or:
+        // someTextField.setText(SomeSystemOption.getDefault().getSomeStringProperty());
+    }
+
+    void store() {
+        // TODO store modified settings
+        // Example:
+        // Preferences.userNodeForPackage(TestPanel.class).putBoolean("someFlag", someCheckBox.isSelected());
+        // or for org.openide.util with API spec. version >= 7.4:
+        // NbPreferences.forModule(TestPanel.class).putBoolean("someFlag", someCheckBox.isSelected());
+        // or:
+        // SomeSystemOption.getDefault().setSomeStringProperty(someTextField.getText());
+    }
+
+    boolean valid() {
+        // TODO check whether form is consistent and complete
+        return true;
+    }
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JLabel jLabel1;
+    // End of variables declaration//GEN-END:variables
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/options/package-info.java b/GUI/src/main/java/cz/fidentis/analyst/options/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..9a55e97db4cfb93c75b388e120d3f5c8edd78654
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/options/package-info.java
@@ -0,0 +1,9 @@
+/**
+ * FIDENTIS settings integrated into the Options window of the NetBean Platform.
+ */
+@OptionsPanelController.ContainerRegistration(id = "Fidentis", categoryName = "#OptionsCategory_Name_Fidentis", iconBase = "logo-28x32.png", keywords = "#OptionsCategory_Keywords_Fidentis", keywordsCategory = "Fidentis")
+@NbBundle.Messages(value = {"OptionsCategory_Name_Fidentis=Fidentis", "OptionsCategory_Keywords_Fidentis=fidentis"})
+package cz.fidentis.analyst.options;
+
+import org.netbeans.spi.options.OptionsPanelController;
+import org.openide.util.NbBundle;
diff --git a/GUI/src/main/java/cz/fidentis/analyst/registration/ModelRotationAnimator.java b/GUI/src/main/java/cz/fidentis/analyst/registration/ModelRotationAnimator.java
new file mode 100644
index 0000000000000000000000000000000000000000..af62ed7b220eaeb617aaf85207c97a640efc2552
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/registration/ModelRotationAnimator.java
@@ -0,0 +1,78 @@
+package cz.fidentis.analyst.registration;
+
+import cz.fidentis.analyst.canvas.Direction;
+import com.jogamp.opengl.util.FPSAnimator;
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * Animator used to animate transformations of model.
+ * Based on {@link cz.fidentis.analyst.canvas.RotationAnimator}.
+ * 
+ * @author Richard Pajersky
+ */
+public class ModelRotationAnimator {
+    
+    /**
+     * Frequency of the rotation or zoom animations
+     */
+    private static final int FPS = 60; 
+    
+    /**
+     * Animator used when the rotation or zoom buttons are pressed and held
+     */
+    private final FPSAnimator animator;
+    
+    /*
+     * Animation timer
+     */
+    private long startClickTime = 0;
+    private TimerTask task;
+    private Timer timer;
+    
+    private Direction direction = Direction.NONE;
+    
+    /**
+     * Constructor.
+     */
+    public ModelRotationAnimator() {
+        this.animator = new FPSAnimator(FPS, true);
+    }
+    
+    /**
+     * Starts model animation
+     * @param dir Transform direction
+     * @param panel Panel
+     */
+    public void startModelAnimation(Direction dir, RegistrationPanel panel) {
+        if (this.direction != Direction.NONE) {
+            throw new UnsupportedOperationException(); // this should no happen
+        }
+        
+        animator.start();
+        timer = new Timer();
+        startClickTime = System.currentTimeMillis();
+        task = new TimerTask() {
+            @Override
+            public void run() {
+                panel.transform(dir);
+            }
+        };
+        timer.schedule(task, 500, 100);
+        
+        this.direction = dir;        
+    }
+    
+    /**
+     * Stops the animation.
+     */
+    public void stopModelAnimation(RegistrationPanel panel) {
+        timer.cancel();
+        if ((System.currentTimeMillis() - startClickTime) < 500) {
+                panel.transform(direction);
+        }
+        startClickTime = 0;
+        animator.stop();
+        this.direction = Direction.NONE;
+    }    
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationAction.java b/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..c5a72da396397c0b800fcc7d7fcf4e409cae19d8
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationAction.java
@@ -0,0 +1,486 @@
+package cz.fidentis.analyst.registration;
+
+import cz.fidentis.analyst.canvas.Canvas;
+import cz.fidentis.analyst.core.ControlPanelAction;
+import cz.fidentis.analyst.core.OutputWindow;
+import cz.fidentis.analyst.face.HumanFace;
+import cz.fidentis.analyst.feature.FeaturePoint;
+import cz.fidentis.analyst.icp.IcpTransformation;
+import cz.fidentis.analyst.icp.IcpTransformer;
+import cz.fidentis.analyst.icp.NoUndersampling;
+import cz.fidentis.analyst.icp.RandomStrategy;
+import cz.fidentis.analyst.icp.UndersamplingStrategy;
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshPoint;
+import cz.fidentis.analyst.visitors.mesh.HausdorffDistance;
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+import java.util.List;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JFormattedTextField;
+import javax.swing.JSlider;
+import javax.swing.JTabbedPane;
+import javax.swing.JToggleButton;
+import javax.vecmath.Point3d;
+import javax.vecmath.Vector3d;
+
+/**
+ * Action listener for the curvature computation.
+ * 
+ * @author Richard Pajersky
+ * @author Radek Oslejsek
+ * @author Daniel Schramm
+ */
+public class RegistrationAction extends ControlPanelAction {
+    
+    /*
+     * Attributes handling the state
+     */
+    private boolean scale = true;
+    private int maxIterations = 10;
+    private double error = 0.3;
+    private UndersamplingStrategy undersampling = new RandomStrategy(200);
+    private HausdorffDistance hdVisitor = null;
+    private String strategy = RegistrationPanel.STRATEGY_POINT_TO_POINT;
+    private boolean relativeDist = false;
+    private boolean heatmapRender = false;
+    
+    /*
+     * Coloring threshold and statistical values of feature point distances:
+     */
+    private double fpThreshold = 5.0;
+
+    private final RegistrationPanel controlPanel;
+    
+    /**
+     * Constructor.
+     * 
+     * @param canvas OpenGL canvas
+     * @param topControlPanel Top component for placing control panels
+     */
+    public RegistrationAction(Canvas canvas, JTabbedPane topControlPanel) {
+        super(canvas, topControlPanel);
+        this.controlPanel = new RegistrationPanel(this);
+        
+        // Place control panel to the topControlPanel
+        topControlPanel.addTab(controlPanel.getName(), controlPanel.getIcon(), controlPanel);
+        topControlPanel.addChangeListener(e -> {
+            // If the registration panel is focused...
+            if (((JTabbedPane) e.getSource()).getSelectedComponent() instanceof RegistrationPanel) {
+                // ... display heatmap and feature points relevant to the registration
+                getCanvas().getScene().setDefaultColors();
+                calculateFeaturePoints();
+                setHeatmap();
+                getSecondaryDrawableFace().setRenderHeatmap(heatmapRender);
+            }
+        });
+        topControlPanel.setSelectedComponent(controlPanel); // Focus registration panel
+        calculateHausdorffDistance();
+    }
+    
+    @Override
+    public void actionPerformed(ActionEvent ae) {
+        double value;
+        String action = ae.getActionCommand();
+        
+        switch (action) {
+            case RegistrationPanel.ACTION_COMMAND_APPLY_ICP:
+                applyICP();
+                calculateFeaturePoints();
+                calculateHausdorffDistance();
+                this.hdVisitor = null; // recompute
+                setHeatmap();
+                break;
+            case RegistrationPanel.ACTION_COMMAND_SHIFT_X:
+                value = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).doubleValue();
+                getSecondaryDrawableFace().getTranslation().x = value;
+                if (getSecondaryFeaturePoints() != null) {
+                    getSecondaryFeaturePoints().getTranslation().x = value;
+                }
+                calculateFeaturePoints();
+                //calculateHausdorffDistance();
+                break;
+            case RegistrationPanel.ACTION_COMMAND_SHIFT_Y:
+                value = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).doubleValue();
+                getSecondaryDrawableFace().getTranslation().y = value;
+                if (getSecondaryFeaturePoints() != null) {
+                    getSecondaryFeaturePoints().getTranslation().y = value;
+                }
+                calculateFeaturePoints();
+                //calculateHausdorffDistance();
+                break;
+            case RegistrationPanel.ACTION_COMMAND_SHIFT_Z:
+                value = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).doubleValue();
+                getSecondaryDrawableFace().getTranslation().z = value;
+                if (getSecondaryFeaturePoints() != null) {
+                    getSecondaryFeaturePoints().getTranslation().z = value;
+                }
+                calculateFeaturePoints();
+                //calculateHausdorffDistance();
+                break;
+            case RegistrationPanel.ACTION_COMMAND_ROTATE_X:
+                value = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).doubleValue();
+                getSecondaryDrawableFace().getRotation().x = value;
+                if (getSecondaryFeaturePoints() != null) {
+                    getSecondaryFeaturePoints().getRotation().x = value;
+                }
+                calculateFeaturePoints();
+                //calculateHausdorffDistance();
+                break;
+            case RegistrationPanel.ACTION_COMMAND_ROTATE_Y:
+                value = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).doubleValue();
+                getSecondaryDrawableFace().getRotation().y = value;
+                if (getSecondaryFeaturePoints() != null) {
+                    getSecondaryFeaturePoints().getRotation().y = value;
+                }
+                calculateFeaturePoints();
+                //calculateHausdorffDistance();
+                break;
+            case RegistrationPanel.ACTION_COMMAND_ROTATE_Z:
+                value = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).doubleValue();
+                getSecondaryDrawableFace().getRotation().z = value;
+                if (getSecondaryFeaturePoints() != null) {
+                    getSecondaryFeaturePoints().getRotation().z = value;
+                }
+                calculateFeaturePoints();
+                //calculateHausdorffDistance();
+                break;
+            case RegistrationPanel.ACTION_COMMAND_SCALE:
+                value = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).doubleValue();
+                getSecondaryDrawableFace().getScale().x = value;
+                getSecondaryDrawableFace().getScale().y = value;
+                getSecondaryDrawableFace().getScale().z = value;
+                if (getSecondaryFeaturePoints() != null) {
+                    getSecondaryFeaturePoints().getScale().x = value;
+                    getSecondaryFeaturePoints().getScale().y = value;
+                    getSecondaryFeaturePoints().getScale().z = value;
+                }
+                calculateFeaturePoints();
+                //calculateHausdorffDistance();
+                break;
+            case RegistrationPanel.ACTION_COMMAND_FRONT_VIEW:
+                getCanvas().getCamera().initLocation();
+                break;
+            case RegistrationPanel.ACTION_COMMAND_SIDE_VIEW:
+                getCanvas().getCamera().initLocation();
+                getCanvas().getCamera().rotate(0, 90);
+                break;
+            case RegistrationPanel.ACTION_COMMAND_RESET_TRANSLATION:
+                getSecondaryDrawableFace().setTranslation(new Vector3d(0, 0, 0));
+                if (getSecondaryFeaturePoints() != null) {
+                    getSecondaryFeaturePoints().setTranslation(new Vector3d(0, 0, 0));
+                }
+                calculateFeaturePoints();
+                //calculateHausdorffDistance();
+                break;
+            case RegistrationPanel.ACTION_COMMAND_RESET_ROTATION:
+                getSecondaryDrawableFace().setRotation(new Vector3d(0, 0, 0));
+                if (getSecondaryFeaturePoints() != null) {
+                    getSecondaryFeaturePoints().setRotation(new Vector3d(0, 0, 0));
+                }
+                calculateFeaturePoints();
+                //calculateHausdorffDistance();
+                break;
+            case RegistrationPanel.ACTION_COMMAND_RESET_SCALE:
+                getSecondaryDrawableFace().setScale(new Vector3d(0, 0, 0));
+                if (getSecondaryFeaturePoints() != null) {
+                    getSecondaryFeaturePoints().setScale(new Vector3d(0, 0, 0));
+                }
+                calculateFeaturePoints();
+                //calculateHausdorffDistance();
+                break;
+            case RegistrationPanel.ACTION_COMMAND_APPLY_TRANSFORMATIONS:
+                transformFace();
+                getSecondaryDrawableFace().setTranslation(new Vector3d(0, 0, 0));
+                getSecondaryDrawableFace().setRotation(new Vector3d(0, 0, 0));
+                getSecondaryDrawableFace().setScale(new Vector3d(0, 0, 0));
+                if (getSecondaryFeaturePoints() != null) {
+                    getSecondaryFeaturePoints().setTranslation(new Vector3d(0, 0, 0));
+                    getSecondaryFeaturePoints().setRotation(new Vector3d(0, 0, 0));
+                    getSecondaryFeaturePoints().setScale(new Vector3d(0, 0, 0));
+                }
+                calculateHausdorffDistance();
+                break;
+            case RegistrationPanel.ACTION_COMMAND_TRANSPARENCY:
+                int transparency = ((JSlider) ae.getSource()).getValue();
+                setTransparency(transparency);
+                break;
+            case RegistrationPanel.ACTION_COMMAND_FP_CLOSENESS_THRESHOLD:
+                fpThreshold = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).doubleValue();
+                calculateFeaturePoints();
+                break;
+            case RegistrationPanel.ACTION_COMMAND_ICP_SCALE:
+                this.scale = ((JCheckBox) ae.getSource()).isSelected();
+                break;
+            case RegistrationPanel.ACTION_COMMAND_ICP_MAX_ITERATIONS:
+                maxIterations = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).intValue();
+                break;
+            case RegistrationPanel.ACTION_COMMAND_ICP_ERROR:
+                error = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).doubleValue();
+                break;
+            case RegistrationPanel.ACTION_COMMAND_ICP_UNDERSAMPLING:
+                String item = (String)((JComboBox) ae.getSource()).getSelectedItem();
+                switch (item) {
+                    case "None":
+                        this.undersampling = new NoUndersampling();
+                        break;
+                    case "Random 200":
+                        this.undersampling = new RandomStrategy(200);
+                        break;
+                    default:
+                        throw new UnsupportedOperationException(item);
+                }
+                break;
+            case RegistrationPanel.ACTION_COMMAND_HD_HEATMAP:
+                heatmapRender = ((JToggleButton) ae.getSource()).isSelected();
+                if (heatmapRender) {
+                    calculateHausdorffDistance();
+                    setHeatmap();
+                }
+                getSecondaryDrawableFace().setRenderHeatmap(heatmapRender);
+                break;
+            case RegistrationPanel.ACTION_COMMAND_HD_STRATEGY:
+                strategy = (String) ((JComboBox) ae.getSource()).getSelectedItem();
+                this.hdVisitor = null; // recompute
+                setHeatmap();
+                break;
+            case RegistrationPanel.ACTION_COMMAND_HD_RELATIVE_DIST:
+                this.relativeDist = ((JToggleButton) ae.getSource()).isSelected();
+                this.hdVisitor = null; // recompute
+                setHeatmap();
+                break;
+            default:
+                // to nothing
+        }
+        
+        renderScene();
+    }
+    
+    protected void applyICP() {
+        OutputWindow out = OutputWindow.measureTime();
+        
+        IcpTransformer visitor = new IcpTransformer(getPrimaryDrawableFace().getModel(), maxIterations, scale, error, undersampling);
+        getSecondaryDrawableFace().getModel().compute(visitor); // NOTE: the secondary face is physically transformed
+        for (List<IcpTransformation> trList: visitor.getTransformations().values()) {
+            for (IcpTransformation tr: trList) {
+                for (int i = 0; i < getSecondaryFeaturePoints().getFeaturePoints().size(); i++) {
+                    FeaturePoint fp = getSecondaryFeaturePoints().getFeaturePoints().get(i);
+                    Point3d trPoint = tr.transformPoint(fp.getPosition(), scale);
+                    getSecondaryFeaturePoints().getFeaturePoints().set(i, new FeaturePoint(trPoint.x, trPoint.y, trPoint.z, fp.getFeaturePointType()));
+                }
+            }
+        }
+        
+        out.printDuration("Computation of ICP for models with " 
+                + getPrimaryDrawableFace().getHumanFace().getMeshModel().getNumVertices()
+                + "/"
+                + getSecondaryDrawableFace().getHumanFace().getMeshModel().getNumVertices()
+                + " vertices"
+        );
+    }
+    
+    /**
+     * Sets the transparency of {@link #primaryFace} or {@link #secondaryFace}
+     * based on the inputed value and {@link #TRANSPARENCY_RANGE}
+     * @param value Value
+     */
+    private void setTransparency(int value) {
+        if (value == RegistrationPanel.TRANSPARENCY_RANGE) {
+            getPrimaryDrawableFace().setTransparency(1);
+            getSecondaryDrawableFace().setTransparency(1);
+        }
+        if (value < RegistrationPanel.TRANSPARENCY_RANGE) {
+            getPrimaryDrawableFace().setTransparency(value / 10f);
+            getSecondaryDrawableFace().setTransparency(1);
+        }
+        if (value > RegistrationPanel.TRANSPARENCY_RANGE) {
+            getPrimaryDrawableFace().setTransparency(1);
+            getSecondaryDrawableFace().setTransparency((2 * RegistrationPanel.TRANSPARENCY_RANGE - value) / 10f);
+        }
+    }
+    
+    /**
+     * Calculates feature points which are too far away
+     * and changes their color to green
+     * otherwise set color to default
+     */
+    private void calculateFeaturePoints() {
+        OutputWindow.print("Calculation of feature points");
+        
+        if (getPrimaryDrawableFace() == null) { // scene not yet initiated
+            return;
+        }
+        
+        if (getPrimaryFeaturePoints() == null || 
+                getSecondaryFeaturePoints() == null ||
+                getPrimaryFeaturePoints().getFeaturePoints().size() != getSecondaryFeaturePoints().getFeaturePoints().size()) {
+            return;
+        }
+         
+        double fpMaxDist = Double.NEGATIVE_INFINITY;
+        double fpMinDist = Double.POSITIVE_INFINITY;
+        double distSum = 0.0;
+        for (int i = 0; i < getPrimaryFeaturePoints().getFeaturePoints().size(); i++) {
+            FeaturePoint primary = getPrimaryFeaturePoints().getFeaturePoints().get(i);
+            FeaturePoint secondary = getSecondaryFeaturePoints().getFeaturePoints().get(i);
+            Point3d transformed = new Point3d(secondary.getX(), secondary.getY(), secondary.getZ());
+            transformPoint(transformed);
+            double distance = Math.sqrt(
+                Math.pow(transformed.x - primary.getX(), 2) + 
+                Math.pow(transformed.y - primary.getY(), 2) + 
+                Math.pow(transformed.z - primary.getZ(), 2));
+            if (distance > fpThreshold) {
+                getPrimaryFeaturePoints().resetColorToDefault(i);
+                getSecondaryFeaturePoints().resetColorToDefault(i);
+            } else {
+                getPrimaryFeaturePoints().setColor(i, Color.GREEN);
+                getSecondaryFeaturePoints().setColor(i, Color.GREEN);
+            }
+            fpMaxDist = Math.max(fpMaxDist, distance);
+            fpMinDist = Math.min(fpMinDist, distance);
+            distSum += distance;
+        }
+        double fpAvgDist = distSum / getPrimaryFeaturePoints().getFeaturePoints().size();
+        this.controlPanel.updateFPStats(fpAvgDist, fpMaxDist, fpMinDist);
+    }
+    
+    private void calculateHausdorffDistance() {
+        OutputWindow out = OutputWindow.measureTime();
+        
+        HumanFace primFace = getScene().getHumanFace(0);
+        primFace.computeKdTree(false);
+        HausdorffDistance hd = new HausdorffDistance(primFace.getKdTree(), HausdorffDistance.Strategy.POINT_TO_POINT_DISTANCE_ONLY, false, true);
+        getScene().getHumanFace(1).getMeshModel().compute(hd);
+        
+        out.printDuration("Computation of Hausdorff distance for models with " 
+                + getPrimaryDrawableFace().getHumanFace().getMeshModel().getNumVertices()
+                + "/"
+                + getSecondaryDrawableFace().getHumanFace().getMeshModel().getNumVertices()
+                + " vertices"
+        );
+        
+        double min = Double.POSITIVE_INFINITY;
+        double max = Double.NEGATIVE_INFINITY;
+        double sum = 0;
+        int    count = 0;
+        for (List<Double> distList: hd.getDistances().values()) {
+            for (double dist : distList) {
+                min = Math.min(min, dist);
+                max = Math.max(max, dist);
+                sum += dist;
+                count++;
+            }
+        }
+        
+        this.controlPanel.updateHDStats(sum/count, max, min);
+    }
+
+    /**
+     * Applies carried out transformations
+     * first on {@link #secondaryFace}
+     * and then on {@link #secondaryFace} feature points
+     */
+    private void transformFace() {
+        for (MeshFacet transformedFacet : getSecondaryDrawableFace().getFacets()) {
+            for (MeshPoint comparedPoint : transformedFacet.getVertices()) {
+                transformPoint(comparedPoint.getPosition());
+            }
+        }
+        for (int i = 0; i < getSecondaryFeaturePoints().getFeaturePoints().size(); i++) {
+            FeaturePoint point = getSecondaryFeaturePoints().getFeaturePoints().get(i);
+            Point3d transformed = new Point3d(point.getX(), point.getY(), point.getZ());
+            transformPoint(transformed);
+            point = new FeaturePoint(transformed.x, transformed.y, transformed.z, point.getFeaturePointType());
+            getSecondaryFeaturePoints().getFeaturePoints().set(i, point);
+        }
+    }
+    
+    /**
+     * Transforms point based on transformation info from {@link #secondaryFace}
+     * 
+     * @param point Point to transform
+     */
+    private void transformPoint(Point3d point) {
+        if (point == null) {
+            throw new IllegalArgumentException("point is null");
+        }
+
+        Point3d newPoint = new Point3d(0, 0, 0);
+        double quotient;
+
+        // rotate around X
+        quotient = Math.toRadians(getSecondaryDrawableFace().getRotation().x);
+        if (!Double.isNaN(quotient)) {
+            double cos = Math.cos(quotient);
+            double sin = Math.sin(quotient);
+            newPoint.y = point.y * cos - point.z * sin;
+            newPoint.z = point.z * cos + point.y * sin;
+            point.y = newPoint.y;
+            point.z = newPoint.z;
+        }
+
+        // rotate around Y
+        quotient = Math.toRadians(getSecondaryDrawableFace().getRotation().y);
+        if (!Double.isNaN(quotient)) {
+            double cos = Math.cos(quotient);
+            double sin = Math.sin(quotient);
+            newPoint.x = point.x * cos + point.z * sin;
+            newPoint.z = point.z * cos - point.x * sin;
+            point.x = newPoint.x;
+            point.z = newPoint.z;
+        }
+
+        // rotate around Z
+        quotient = Math.toRadians(getSecondaryDrawableFace().getRotation().z);
+        if (!Double.isNaN(quotient)) {
+            double cos = Math.cos(quotient);
+            double sin = Math.sin(quotient);
+            newPoint.x = point.x * cos - point.y * sin;
+            newPoint.y = point.y * cos + point.x * sin;
+            point.x = newPoint.x;
+            point.y = newPoint.y;
+        }
+
+        // translate
+        point.x += getSecondaryDrawableFace().getTranslation().x;
+        point.y += getSecondaryDrawableFace().getTranslation().y;
+        point.z += getSecondaryDrawableFace().getTranslation().z;
+
+        // scale
+        point.x *= 1 + getSecondaryDrawableFace().getScale().x;
+        point.y *= 1 + getSecondaryDrawableFace().getScale().y;
+        point.z *= 1 + getSecondaryDrawableFace().getScale().z;
+    }
+    
+    protected void setHeatmap() {
+        HausdorffDistance.Strategy useStrategy;
+        switch (strategy) {
+            case RegistrationPanel.STRATEGY_POINT_TO_POINT:
+                useStrategy = HausdorffDistance.Strategy.POINT_TO_POINT;
+                break;
+            case RegistrationPanel.STRATEGY_POINT_TO_TRIANGLE:
+                useStrategy = HausdorffDistance.Strategy.POINT_TO_TRIANGLE_APPROXIMATE;
+                break;
+            default:
+                throw new UnsupportedOperationException(strategy);
+        }
+        
+        if (hdVisitor == null) { 
+            OutputWindow out = OutputWindow.measureTime();
+            
+            this.hdVisitor = new HausdorffDistance(getPrimaryDrawableFace().getModel(), useStrategy, relativeDist, true);
+            getSecondaryDrawableFace().getModel().compute(hdVisitor);
+            
+            out.printDuration("Computation of Hausdorff distance for models with " 
+                    + getPrimaryDrawableFace().getHumanFace().getMeshModel().getNumVertices()
+                    + "/"
+                    + getSecondaryDrawableFace().getHumanFace().getMeshModel().getNumVertices()
+                    + " vertices"
+            );
+        }
+        
+        getSecondaryDrawableFace().setHeatMap(hdVisitor.getDistances());
+    }
+    
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.form b/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.form
new file mode 100644
index 0000000000000000000000000000000000000000..bbf03adfe438d8425abec868587cb67421c37b32
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.form
@@ -0,0 +1,2107 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <NonVisualComponents>
+    <Component class="javax.swing.ButtonGroup" name="primaryRenderModeGroup">
+    </Component>
+    <Component class="javax.swing.ButtonGroup" name="secondaryRenerModeGroup">
+    </Component>
+    <Component class="javax.swing.ButtonGroup" name="precisionGroup">
+    </Component>
+  </NonVisualComponents>
+  <Properties>
+    <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+      <Dimension value="[600, 600]"/>
+    </Property>
+    <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+      <Dimension value="[600, 600]"/>
+    </Property>
+  </Properties>
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <EmptySpace min="-2" pref="805" max="-2" attributes="0"/>
+              <Component id="jSeparator11" max="32767" attributes="0"/>
+          </Group>
+          <Group type="102" alignment="0" attributes="0">
+              <EmptySpace min="-2" pref="791" max="-2" attributes="0"/>
+              <Component id="jSeparator2" max="32767" attributes="0"/>
+              <EmptySpace min="-2" pref="450" max="-2" attributes="0"/>
+          </Group>
+          <Group type="102" attributes="0">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Component id="transformationPanel" alignment="0" min="-2" pref="692" max="-2" attributes="0"/>
+                  <Component id="jPanel4" alignment="0" min="-2" max="-2" attributes="0"/>
+                  <Component id="jPanel6" alignment="0" min="-2" max="-2" attributes="0"/>
+                  <Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
+                      <Component id="jPanel2" alignment="0" pref="624" max="32767" attributes="0"/>
+                      <Component id="jPanel1" alignment="0" max="32767" attributes="0"/>
+                  </Group>
+              </Group>
+              <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <Component id="jPanel1" min="-2" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jPanel2" min="-2" pref="77" max="-2" attributes="0"/>
+              <EmptySpace min="-2" max="-2" attributes="0"/>
+              <Component id="jPanel4" min="-2" pref="135" max="-2" attributes="0"/>
+              <EmptySpace min="-2" max="-2" attributes="0"/>
+              <Component id="transformationPanel" min="-2" pref="209" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jPanel6" min="-2" max="-2" attributes="0"/>
+              <EmptySpace min="-2" pref="77" max="-2" attributes="0"/>
+              <Component id="jSeparator11" min="-2" pref="10" max="-2" attributes="0"/>
+              <EmptySpace min="-2" pref="221" max="-2" attributes="0"/>
+              <Component id="jSeparator2" min="-2" pref="10" max="-2" attributes="0"/>
+              <EmptySpace max="32767" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Component class="javax.swing.JSeparator" name="jSeparator11">
+    </Component>
+    <Container class="javax.swing.JPanel" name="transformationPanel">
+      <Properties>
+        <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+          <Dimension value="[400, 400]"/>
+        </Property>
+      </Properties>
+
+      <Layout>
+        <DimensionLayout dim="0">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" attributes="0">
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Group type="102" attributes="0">
+                          <Component id="jSeparator5" max="32767" attributes="0"/>
+                          <EmptySpace min="-2" pref="474" max="-2" attributes="0"/>
+                      </Group>
+                      <Group type="102" alignment="0" attributes="0">
+                          <Group type="103" groupAlignment="1" attributes="0">
+                              <Component id="jSeparator4" alignment="1" min="-2" pref="589" max="-2" attributes="0"/>
+                              <Group type="103" groupAlignment="0" attributes="0">
+                                  <Group type="102" attributes="0">
+                                      <EmptySpace min="-2" pref="580" max="-2" attributes="0"/>
+                                      <Component id="shiftPanel" min="-2" max="-2" attributes="0"/>
+                                  </Group>
+                                  <Group type="102" attributes="0">
+                                      <EmptySpace min="-2" pref="349" max="-2" attributes="0"/>
+                                      <Component id="jSeparator10" min="-2" pref="15" max="-2" attributes="0"/>
+                                  </Group>
+                                  <Group type="102" alignment="0" attributes="0">
+                                      <EmptySpace max="-2" attributes="0"/>
+                                      <Group type="103" groupAlignment="0" attributes="0">
+                                          <Component id="translationPanel" alignment="0" min="-2" pref="227" max="-2" attributes="0"/>
+                                          <Group type="102" alignment="0" attributes="0">
+                                              <EmptySpace min="12" pref="12" max="-2" attributes="0"/>
+                                              <Component id="shiftLabel" min="-2" max="-2" attributes="0"/>
+                                              <EmptySpace max="-2" attributes="0"/>
+                                              <Component id="lowShiftRB" min="-2" max="-2" attributes="0"/>
+                                              <EmptySpace max="-2" attributes="0"/>
+                                              <Component id="highShiftRB" min="-2" max="-2" attributes="0"/>
+                                          </Group>
+                                      </Group>
+                                      <EmptySpace max="-2" attributes="0"/>
+                                      <Group type="103" groupAlignment="0" attributes="0">
+                                          <Group type="102" attributes="0">
+                                              <Component id="resetAllButton" min="-2" pref="128" max="-2" attributes="0"/>
+                                              <EmptySpace type="unrelated" max="-2" attributes="0"/>
+                                              <Component id="applyButton" min="-2" pref="128" max="-2" attributes="0"/>
+                                          </Group>
+                                          <Group type="102" attributes="0">
+                                              <Component id="rotationPanel" min="-2" pref="224" max="-2" attributes="0"/>
+                                              <EmptySpace max="-2" attributes="0"/>
+                                              <Component id="scalePanel" min="-2" pref="102" max="-2" attributes="0"/>
+                                          </Group>
+                                      </Group>
+                                  </Group>
+                                  <Group type="102" attributes="0">
+                                      <EmptySpace max="-2" attributes="0"/>
+                                      <Component id="jLabel2" min="-2" max="-2" attributes="0"/>
+                                  </Group>
+                              </Group>
+                          </Group>
+                          <EmptySpace min="0" pref="91" max="32767" attributes="0"/>
+                      </Group>
+                  </Group>
+                  <EmptySpace max="-2" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+        <DimensionLayout dim="1">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" attributes="0">
+                  <Component id="jSeparator4" min="-2" pref="10" max="-2" attributes="0"/>
+                  <EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
+                  <Component id="jLabel2" min="-2" max="-2" attributes="0"/>
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="1" attributes="0">
+                      <Group type="102" alignment="1" attributes="0">
+                          <Component id="scalePanel" max="32767" attributes="0"/>
+                          <EmptySpace min="1" pref="1" max="-2" attributes="0"/>
+                      </Group>
+                      <Component id="translationPanel" alignment="0" max="32767" attributes="0"/>
+                      <Component id="rotationPanel" max="32767" attributes="0"/>
+                  </Group>
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Component id="applyButton" alignment="0" min="-2" pref="26" max="-2" attributes="0"/>
+                      <Group type="103" groupAlignment="3" attributes="0">
+                          <Component id="shiftLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="lowShiftRB" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="highShiftRB" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="resetAllButton" alignment="3" min="-2" max="-2" attributes="0"/>
+                      </Group>
+                  </Group>
+                  <EmptySpace min="-2" pref="39" max="-2" attributes="0"/>
+                  <Component id="jSeparator10" min="-2" pref="62" max="-2" attributes="0"/>
+                  <EmptySpace min="-2" pref="25" max="-2" attributes="0"/>
+                  <Component id="shiftPanel" min="-2" max="-2" attributes="0"/>
+                  <EmptySpace max="32767" attributes="0"/>
+                  <Component id="jSeparator5" min="-2" pref="10" max="-2" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+      </Layout>
+      <SubComponents>
+        <Container class="javax.swing.JPanel" name="translationPanel">
+          <Properties>
+            <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+              <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                <TitledBorder title="translation">
+                  <ResourceString PropertyName="titleX" bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.translationPanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </TitledBorder>
+              </Border>
+            </Property>
+          </Properties>
+
+          <Layout>
+            <DimensionLayout dim="0">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" alignment="0" attributes="0">
+                      <Group type="103" groupAlignment="1" max="-2" attributes="0">
+                          <Group type="102" alignment="1" attributes="0">
+                              <EmptySpace min="-2" pref="31" max="-2" attributes="0"/>
+                              <Component id="translXLabel" min="-2" max="-2" attributes="0"/>
+                          </Group>
+                          <Group type="102" alignment="1" attributes="0">
+                              <EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
+                              <Component id="translationButton" min="-2" max="-2" attributes="0"/>
+                              <EmptySpace max="32767" attributes="0"/>
+                              <Group type="103" groupAlignment="0" attributes="0">
+                                  <Component id="translationXFTF" alignment="0" min="-2" pref="54" max="-2" attributes="0"/>
+                                  <Group type="102" alignment="0" attributes="0">
+                                      <Component id="leftTranslationXButton" min="-2" max="-2" attributes="0"/>
+                                      <EmptySpace max="-2" attributes="0"/>
+                                      <Component id="rightTranslationXButton" min="-2" max="-2" attributes="0"/>
+                                  </Group>
+                              </Group>
+                          </Group>
+                      </Group>
+                      <Group type="103" groupAlignment="0" attributes="0">
+                          <Group type="102" attributes="0">
+                              <EmptySpace min="-2" pref="7" max="-2" attributes="0"/>
+                              <Group type="103" groupAlignment="0" attributes="0">
+                                  <Group type="102" alignment="0" attributes="0">
+                                      <Component id="leftTranslationYButton" min="-2" max="-2" attributes="0"/>
+                                      <EmptySpace max="-2" attributes="0"/>
+                                      <Component id="rightTranslationYButton" min="-2" max="-2" attributes="0"/>
+                                  </Group>
+                                  <Component id="translationYFTF" min="-2" pref="54" max="-2" attributes="0"/>
+                              </Group>
+                          </Group>
+                          <Group type="102" alignment="0" attributes="0">
+                              <EmptySpace min="-2" pref="15" max="-2" attributes="0"/>
+                              <Component id="translYLabel" min="-2" max="-2" attributes="0"/>
+                          </Group>
+                      </Group>
+                      <EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
+                      <Group type="103" groupAlignment="0" attributes="0">
+                          <Group type="102" alignment="0" attributes="0">
+                              <EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
+                              <Group type="103" groupAlignment="0" attributes="0">
+                                  <Group type="102" alignment="0" attributes="0">
+                                      <Component id="leftTranslationZButton" min="-2" max="-2" attributes="0"/>
+                                      <EmptySpace max="-2" attributes="0"/>
+                                      <Component id="rightTranslationZButton" min="-2" max="-2" attributes="0"/>
+                                  </Group>
+                                  <Component id="translationZFTF" min="-2" pref="54" max="-2" attributes="0"/>
+                              </Group>
+                              <EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
+                          </Group>
+                          <Component id="translZLabel" alignment="1" min="-2" max="-2" attributes="0"/>
+                      </Group>
+                      <EmptySpace max="32767" attributes="0"/>
+                  </Group>
+              </Group>
+            </DimensionLayout>
+            <DimensionLayout dim="1">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" alignment="0" attributes="0">
+                      <EmptySpace min="-2" pref="7" max="-2" attributes="0"/>
+                      <Group type="103" groupAlignment="3" attributes="0">
+                          <Component id="translXLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="translYLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="translZLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+                      </Group>
+                      <EmptySpace min="-2" pref="9" max="-2" attributes="0"/>
+                      <Group type="103" groupAlignment="0" attributes="0">
+                          <Group type="102" alignment="0" attributes="0">
+                              <Group type="103" groupAlignment="1" attributes="0">
+                                  <Component id="rightTranslationXButton" alignment="0" min="-2" max="-2" attributes="0"/>
+                                  <Component id="leftTranslationXButton" alignment="0" min="-2" max="-2" attributes="0"/>
+                              </Group>
+                              <EmptySpace max="-2" attributes="0"/>
+                              <Group type="103" groupAlignment="0" attributes="0">
+                                  <Component id="translationXFTF" max="-2" attributes="0"/>
+                                  <Group type="102" alignment="1" attributes="0">
+                                      <Component id="translationButton" min="-2" max="-2" attributes="0"/>
+                                      <EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
+                                  </Group>
+                              </Group>
+                          </Group>
+                          <Group type="102" alignment="0" attributes="0">
+                              <Group type="103" groupAlignment="1" attributes="0">
+                                  <Component id="rightTranslationYButton" alignment="0" min="-2" max="-2" attributes="0"/>
+                                  <Component id="leftTranslationYButton" alignment="0" min="-2" max="-2" attributes="0"/>
+                              </Group>
+                              <EmptySpace max="-2" attributes="0"/>
+                              <Component id="translationYFTF" min="-2" max="-2" attributes="0"/>
+                          </Group>
+                          <Group type="102" alignment="0" attributes="0">
+                              <Group type="103" groupAlignment="1" attributes="0">
+                                  <Group type="102" alignment="1" attributes="0">
+                                      <Component id="rightTranslationZButton" min="-2" max="-2" attributes="0"/>
+                                      <EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
+                                  </Group>
+                                  <Group type="102" alignment="0" attributes="0">
+                                      <Component id="leftTranslationZButton" min="-2" max="-2" attributes="0"/>
+                                      <EmptySpace max="-2" attributes="0"/>
+                                  </Group>
+                              </Group>
+                              <Component id="translationZFTF" min="-2" max="-2" attributes="0"/>
+                          </Group>
+                      </Group>
+                      <EmptySpace min="10" pref="10" max="-2" attributes="0"/>
+                  </Group>
+              </Group>
+            </DimensionLayout>
+          </Layout>
+          <SubComponents>
+            <Component class="javax.swing.JButton" name="translationButton">
+              <Properties>
+                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+                  <Image iconType="3" name="/restart-line.png"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.translationButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.translationButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                    <TitledBorder/>
+                  </Border>
+                </Property>
+                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+                  <Color id="Default Cursor"/>
+                </Property>
+                <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
+                  <Insets value="[2, 2, 2, 2]"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="translationButtonMousePressed"/>
+              </Events>
+            </Component>
+            <Component class="javax.swing.JButton" name="rightTranslationXButton">
+              <Properties>
+                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+                  <Image iconType="3" name="/arrow-right-s-line.png"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.rightTranslationXButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                    <TitledBorder/>
+                  </Border>
+                </Property>
+                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+                  <Color id="Default Cursor"/>
+                </Property>
+                <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
+                  <Insets value="[2, 2, 2, 2]"/>
+                </Property>
+                <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+                <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+                <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="rightTranslationXButtonMousePressed"/>
+                <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="rightTranslationXButtonMouseReleased"/>
+              </Events>
+            </Component>
+            <Component class="javax.swing.JFormattedTextField" name="translationXFTF">
+              <Properties>
+                <Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.editors.AbstractFormatterFactoryEditor">
+                  <Format subtype="0" type="0"/>
+                </Property>
+                <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.translationXFTF.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+                  <Color id="Text Cursor"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JButton" name="leftTranslationYButton">
+              <Properties>
+                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+                  <Image iconType="3" name="/arrow-left-s-line.png"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.leftTranslationYButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                    <TitledBorder/>
+                  </Border>
+                </Property>
+                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+                  <Color id="Default Cursor"/>
+                </Property>
+                <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
+                  <Insets value="[2, 2, 2, 2]"/>
+                </Property>
+                <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="leftTranslationYButtonMousePressed"/>
+                <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="leftTranslationYButtonMouseReleased"/>
+              </Events>
+            </Component>
+            <Component class="javax.swing.JFormattedTextField" name="translationYFTF">
+              <Properties>
+                <Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.editors.AbstractFormatterFactoryEditor">
+                  <Format subtype="0" type="0"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JButton" name="rightTranslationYButton">
+              <Properties>
+                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+                  <Image iconType="3" name="/arrow-right-s-line.png"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.rightTranslationYButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                    <TitledBorder/>
+                  </Border>
+                </Property>
+                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+                  <Color id="Default Cursor"/>
+                </Property>
+                <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
+                  <Insets value="[2, 2, 2, 2]"/>
+                </Property>
+                <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="rightTranslationYButtonMousePressed"/>
+                <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="rightTranslationYButtonMouseReleased"/>
+              </Events>
+            </Component>
+            <Component class="javax.swing.JLabel" name="translXLabel">
+              <Properties>
+                <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+                  <Font name="Tahoma" size="11" style="0"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.translXLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JFormattedTextField" name="translationZFTF">
+              <Properties>
+                <Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.editors.AbstractFormatterFactoryEditor">
+                  <Format subtype="0" type="0"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JLabel" name="translZLabel">
+              <Properties>
+                <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+                  <Font name="Tahoma" size="11" style="0"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.translZLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JLabel" name="translYLabel">
+              <Properties>
+                <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+                  <Font name="Tahoma" size="11" style="0"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.translYLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JButton" name="rightTranslationZButton">
+              <Properties>
+                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+                  <Image iconType="3" name="/arrow-right-s-line.png"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.rightTranslationZButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                    <TitledBorder/>
+                  </Border>
+                </Property>
+                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+                  <Color id="Default Cursor"/>
+                </Property>
+                <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
+                  <Insets value="[2, 2, 2, 2]"/>
+                </Property>
+                <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="rightTranslationZButtonMousePressed"/>
+                <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="rightTranslationZButtonMouseReleased"/>
+              </Events>
+            </Component>
+            <Component class="javax.swing.JButton" name="leftTranslationXButton">
+              <Properties>
+                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+                  <Image iconType="3" name="/arrow-left-s-line.png"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.leftTranslationXButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                    <TitledBorder/>
+                  </Border>
+                </Property>
+                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+                  <Color id="Default Cursor"/>
+                </Property>
+                <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
+                  <Insets value="[2, 2, 2, 2]"/>
+                </Property>
+                <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+                <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+                <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="leftTranslationXButtonMousePressed"/>
+                <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="leftTranslationXButtonMouseReleased"/>
+              </Events>
+            </Component>
+            <Component class="javax.swing.JButton" name="leftTranslationZButton">
+              <Properties>
+                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+                  <Image iconType="3" name="/arrow-left-s-line.png"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.leftTranslationZButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                    <TitledBorder/>
+                  </Border>
+                </Property>
+                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+                  <Color id="Default Cursor"/>
+                </Property>
+                <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
+                  <Insets value="[2, 2, 2, 2]"/>
+                </Property>
+                <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="leftTranslationZButtonMousePressed"/>
+                <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="leftTranslationZButtonMouseReleased"/>
+              </Events>
+            </Component>
+          </SubComponents>
+        </Container>
+        <Container class="javax.swing.JPanel" name="rotationPanel">
+          <Properties>
+            <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+              <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                <TitledBorder title="rotation">
+                  <ResourceString PropertyName="titleX" bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.rotationPanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </TitledBorder>
+              </Border>
+            </Property>
+          </Properties>
+
+          <Layout>
+            <DimensionLayout dim="0">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" alignment="0" attributes="0">
+                      <EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
+                      <Group type="103" groupAlignment="0" attributes="0">
+                          <Group type="102" alignment="0" attributes="0">
+                              <Component id="rotationButton" min="-2" max="-2" attributes="0"/>
+                              <EmptySpace max="-2" attributes="0"/>
+                              <Group type="103" groupAlignment="0" attributes="0">
+                                  <Component id="rotationXFTF" min="-2" pref="54" max="-2" attributes="0"/>
+                                  <Group type="102" alignment="0" attributes="0">
+                                      <Component id="leftRotationXButton" min="-2" max="-2" attributes="0"/>
+                                      <EmptySpace max="-2" attributes="0"/>
+                                      <Component id="rightRotationXButton" min="-2" max="-2" attributes="0"/>
+                                  </Group>
+                              </Group>
+                          </Group>
+                          <Group type="102" alignment="0" attributes="0">
+                              <EmptySpace min="-2" pref="55" max="-2" attributes="0"/>
+                              <Component id="rotatXLabel" min="-2" pref="20" max="-2" attributes="0"/>
+                          </Group>
+                      </Group>
+                      <Group type="103" groupAlignment="0" attributes="0">
+                          <Group type="102" alignment="0" attributes="0">
+                              <EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
+                              <Group type="103" groupAlignment="0" max="-2" attributes="0">
+                                  <Group type="102" alignment="0" attributes="0">
+                                      <Component id="leftRotationYButton" min="-2" max="-2" attributes="0"/>
+                                      <EmptySpace max="-2" attributes="0"/>
+                                      <Component id="rightRotationYButton" min="-2" max="-2" attributes="0"/>
+                                  </Group>
+                                  <Component id="rotationYFTF" alignment="1" min="-2" pref="54" max="-2" attributes="0"/>
+                              </Group>
+                          </Group>
+                          <Group type="102" alignment="0" attributes="0">
+                              <EmptySpace min="-2" pref="29" max="-2" attributes="0"/>
+                              <Component id="rotatYLabel" min="-2" pref="17" max="-2" attributes="0"/>
+                          </Group>
+                      </Group>
+                      <Group type="103" groupAlignment="0" attributes="0">
+                          <Group type="102" alignment="0" attributes="0">
+                              <EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
+                              <Group type="103" groupAlignment="1" max="-2" attributes="0">
+                                  <Component id="rotationZFTF" alignment="0" min="-2" pref="54" max="-2" attributes="0"/>
+                                  <Group type="102" alignment="0" attributes="0">
+                                      <Component id="leftRotationZButton" min="-2" max="-2" attributes="0"/>
+                                      <EmptySpace max="-2" attributes="0"/>
+                                      <Component id="rightRotationZButton" min="-2" max="-2" attributes="0"/>
+                                  </Group>
+                              </Group>
+                          </Group>
+                          <Group type="102" alignment="0" attributes="0">
+                              <EmptySpace min="-2" pref="28" max="-2" attributes="0"/>
+                              <Component id="rotatZLabel" min="-2" pref="21" max="-2" attributes="0"/>
+                          </Group>
+                      </Group>
+                      <EmptySpace max="32767" attributes="0"/>
+                  </Group>
+              </Group>
+            </DimensionLayout>
+            <DimensionLayout dim="1">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" alignment="0" attributes="0">
+                      <EmptySpace min="-2" pref="7" max="-2" attributes="0"/>
+                      <Group type="103" groupAlignment="0" attributes="0">
+                          <Group type="102" alignment="0" attributes="0">
+                              <EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
+                              <Group type="103" groupAlignment="0" attributes="0">
+                                  <Component id="rotatZLabel" alignment="1" min="-2" max="-2" attributes="0"/>
+                                  <Component id="rotatXLabel" alignment="1" min="-2" max="-2" attributes="0"/>
+                              </Group>
+                          </Group>
+                          <Component id="rotatYLabel" alignment="0" min="-2" max="-2" attributes="0"/>
+                      </Group>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Group type="103" groupAlignment="1" attributes="0">
+                          <Group type="102" alignment="1" attributes="0">
+                              <Group type="103" groupAlignment="0" attributes="0">
+                                  <Component id="leftRotationZButton" alignment="0" min="-2" max="-2" attributes="0"/>
+                                  <Component id="rightRotationZButton" alignment="0" min="-2" max="-2" attributes="0"/>
+                              </Group>
+                              <EmptySpace max="-2" attributes="0"/>
+                              <Component id="rotationZFTF" min="-2" max="-2" attributes="0"/>
+                          </Group>
+                          <Group type="102" alignment="1" attributes="0">
+                              <Group type="103" groupAlignment="0" attributes="0">
+                                  <Component id="leftRotationXButton" min="-2" max="-2" attributes="0"/>
+                                  <Component id="rightRotationXButton" min="-2" max="-2" attributes="0"/>
+                              </Group>
+                              <EmptySpace max="-2" attributes="0"/>
+                              <Group type="103" groupAlignment="0" attributes="0">
+                                  <Group type="103" groupAlignment="3" attributes="0">
+                                      <Component id="rotationXFTF" alignment="3" min="-2" max="-2" attributes="0"/>
+                                      <Component id="rotationYFTF" alignment="3" min="-2" max="-2" attributes="0"/>
+                                  </Group>
+                                  <Group type="102" alignment="1" attributes="0">
+                                      <Component id="rotationButton" max="-2" attributes="0"/>
+                                      <EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
+                                  </Group>
+                              </Group>
+                          </Group>
+                          <Group type="102" alignment="1" attributes="0">
+                              <Group type="103" groupAlignment="0" attributes="0">
+                                  <Component id="rightRotationYButton" min="-2" max="-2" attributes="0"/>
+                                  <Component id="leftRotationYButton" alignment="0" min="-2" max="-2" attributes="0"/>
+                              </Group>
+                              <EmptySpace min="-2" pref="41" max="-2" attributes="0"/>
+                          </Group>
+                      </Group>
+                      <EmptySpace max="32767" attributes="0"/>
+                  </Group>
+              </Group>
+            </DimensionLayout>
+          </Layout>
+          <SubComponents>
+            <Component class="javax.swing.JButton" name="leftRotationYButton">
+              <Properties>
+                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+                  <Image iconType="3" name="/arrow-left-s-line.png"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.leftRotationYButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                    <TitledBorder/>
+                  </Border>
+                </Property>
+                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+                  <Color id="Default Cursor"/>
+                </Property>
+                <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
+                  <Insets value="[2, 2, 2, 2]"/>
+                </Property>
+                <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+                <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+                <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="leftRotationYButtonMousePressed"/>
+                <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="leftRotationYButtonMouseReleased"/>
+              </Events>
+            </Component>
+            <Component class="javax.swing.JButton" name="leftRotationXButton">
+              <Properties>
+                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+                  <Image iconType="3" name="/arrow-left-s-line.png"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.leftRotationXButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                    <TitledBorder/>
+                  </Border>
+                </Property>
+                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+                  <Color id="Default Cursor"/>
+                </Property>
+                <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
+                  <Insets value="[2, 2, 2, 2]"/>
+                </Property>
+                <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="leftRotationXButtonMousePressed"/>
+                <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="leftRotationXButtonMouseReleased"/>
+              </Events>
+            </Component>
+            <Component class="javax.swing.JLabel" name="rotatZLabel">
+              <Properties>
+                <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+                  <Font name="Tahoma" size="11" style="0"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.rotatZLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JLabel" name="rotatYLabel">
+              <Properties>
+                <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+                  <Font name="Tahoma" size="11" style="0"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.rotatYLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JLabel" name="rotatXLabel">
+              <Properties>
+                <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+                  <Font name="Tahoma" size="11" style="0"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.rotatXLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JButton" name="rotationButton">
+              <Properties>
+                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+                  <Image iconType="3" name="/restart-line.png"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.rotationButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.rotationButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                    <TitledBorder/>
+                  </Border>
+                </Property>
+                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+                  <Color id="Default Cursor"/>
+                </Property>
+                <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
+                  <Insets value="[2, 2, 2, 2]"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="rotationButtonMousePressed"/>
+              </Events>
+            </Component>
+            <Component class="javax.swing.JFormattedTextField" name="rotationZFTF">
+              <Properties>
+                <Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.editors.AbstractFormatterFactoryEditor">
+                  <Format subtype="0" type="0"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JFormattedTextField" name="rotationYFTF">
+              <Properties>
+                <Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.editors.AbstractFormatterFactoryEditor">
+                  <Format subtype="0" type="0"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JButton" name="rightRotationZButton">
+              <Properties>
+                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+                  <Image iconType="3" name="/arrow-right-s-line.png"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.rightRotationZButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                    <TitledBorder/>
+                  </Border>
+                </Property>
+                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+                  <Color id="Default Cursor"/>
+                </Property>
+                <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
+                  <Insets value="[2, 2, 2, 2]"/>
+                </Property>
+                <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+                <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+                <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="rightRotationZButtonMousePressed"/>
+                <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="rightRotationZButtonMouseReleased"/>
+              </Events>
+            </Component>
+            <Component class="javax.swing.JButton" name="rightRotationYButton">
+              <Properties>
+                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+                  <Image iconType="3" name="/arrow-right-s-line.png"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.rightRotationYButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                    <TitledBorder/>
+                  </Border>
+                </Property>
+                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+                  <Color id="Default Cursor"/>
+                </Property>
+                <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
+                  <Insets value="[2, 2, 2, 2]"/>
+                </Property>
+                <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+                <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+                <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="rightRotationYButtonMousePressed"/>
+                <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="rightRotationYButtonMouseReleased"/>
+              </Events>
+            </Component>
+            <Component class="javax.swing.JButton" name="leftRotationZButton">
+              <Properties>
+                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+                  <Image iconType="3" name="/arrow-left-s-line.png"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.leftRotationZButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                    <TitledBorder/>
+                  </Border>
+                </Property>
+                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+                  <Color id="Default Cursor"/>
+                </Property>
+                <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
+                  <Insets value="[2, 2, 2, 2]"/>
+                </Property>
+                <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+                <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+                <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="leftRotationZButtonMousePressed"/>
+                <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="leftRotationZButtonMouseReleased"/>
+              </Events>
+            </Component>
+            <Component class="javax.swing.JButton" name="rightRotationXButton">
+              <Properties>
+                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+                  <Image iconType="3" name="/arrow-right-s-line.png"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.rightRotationXButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                    <TitledBorder/>
+                  </Border>
+                </Property>
+                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+                  <Color id="Default Cursor"/>
+                </Property>
+                <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
+                  <Insets value="[2, 2, 2, 2]"/>
+                </Property>
+                <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+                <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+                <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="rightRotationXButtonMousePressed"/>
+                <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="rightRotationXButtonMouseReleased"/>
+              </Events>
+            </Component>
+            <Component class="javax.swing.JFormattedTextField" name="rotationXFTF">
+              <Properties>
+                <Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.editors.AbstractFormatterFactoryEditor">
+                  <Format subtype="0" type="0"/>
+                </Property>
+                <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.rotationXFTF.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+          </SubComponents>
+        </Container>
+        <Container class="javax.swing.JPanel" name="scalePanel">
+          <Properties>
+            <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+              <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                <TitledBorder title="scale">
+                  <ResourceString PropertyName="titleX" bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.scalePanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </TitledBorder>
+              </Border>
+            </Property>
+          </Properties>
+
+          <Layout>
+            <DimensionLayout dim="0">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" alignment="0" attributes="0">
+                      <EmptySpace min="-2" pref="32" max="-2" attributes="0"/>
+                      <Component id="scalePlusButton" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="scaleMinusButton" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
+                  </Group>
+                  <Group type="102" alignment="1" attributes="0">
+                      <EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
+                      <Component id="scaleButton" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace min="-2" pref="7" max="-2" attributes="0"/>
+                      <Component id="scaleFTF" min="-2" pref="54" max="-2" attributes="0"/>
+                      <EmptySpace max="32767" attributes="0"/>
+                  </Group>
+              </Group>
+            </DimensionLayout>
+            <DimensionLayout dim="1">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" alignment="1" attributes="0">
+                      <EmptySpace max="32767" attributes="0"/>
+                      <Group type="103" groupAlignment="0" attributes="0">
+                          <Component id="scalePlusButton" min="-2" max="-2" attributes="0"/>
+                          <Component id="scaleMinusButton" min="-2" max="-2" attributes="0"/>
+                      </Group>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Group type="103" groupAlignment="0" attributes="0">
+                          <Component id="scaleFTF" min="-2" max="-2" attributes="0"/>
+                          <Group type="102" alignment="1" attributes="0">
+                              <Component id="scaleButton" max="-2" attributes="0"/>
+                              <EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
+                          </Group>
+                      </Group>
+                      <EmptySpace max="-2" attributes="0"/>
+                  </Group>
+              </Group>
+            </DimensionLayout>
+          </Layout>
+          <SubComponents>
+            <Component class="javax.swing.JButton" name="scalePlusButton">
+              <Properties>
+                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+                  <Image iconType="3" name="/add-line.png"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.scalePlusButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                    <TitledBorder/>
+                  </Border>
+                </Property>
+                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+                  <Color id="Default Cursor"/>
+                </Property>
+                <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
+                  <Insets value="[2, 2, 2, 2]"/>
+                </Property>
+                <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+                <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+                <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="scalePlusButtonMousePressed"/>
+                <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="scalePlusButtonMouseReleased"/>
+              </Events>
+            </Component>
+            <Component class="javax.swing.JFormattedTextField" name="scaleFTF">
+              <Properties>
+                <Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.editors.AbstractFormatterFactoryEditor">
+                  <Format subtype="0" type="0"/>
+                </Property>
+                <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.scaleFTF.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="scaleFTFActionPerformed"/>
+              </Events>
+            </Component>
+            <Component class="javax.swing.JButton" name="scaleButton">
+              <Properties>
+                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+                  <Image iconType="3" name="/restart-line.png"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.scaleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.scaleButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                    <TitledBorder/>
+                  </Border>
+                </Property>
+                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+                  <Color id="Default Cursor"/>
+                </Property>
+                <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
+                  <Insets value="[2, 2, 2, 2]"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="scaleButtonMousePressed"/>
+              </Events>
+            </Component>
+            <Component class="javax.swing.JButton" name="scaleMinusButton">
+              <Properties>
+                <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+                  <Image iconType="3" name="/subtract-line.png"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.scaleMinusButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                    <TitledBorder/>
+                  </Border>
+                </Property>
+                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+                  <Color id="Default Cursor"/>
+                </Property>
+                <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
+                  <Insets value="[2, 2, 2, 2]"/>
+                </Property>
+                <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+                <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+                <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[24, 24]"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="scaleMinusButtonMousePressed"/>
+                <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="scaleMinusButtonMouseReleased"/>
+              </Events>
+            </Component>
+          </SubComponents>
+        </Container>
+        <Component class="javax.swing.JButton" name="resetAllButton">
+          <Properties>
+            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+              <Image iconType="3" name="/refresh-line.png"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.resetAllButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+            <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.resetAllButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+            <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+              <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                <TitledBorder/>
+              </Border>
+            </Property>
+            <Property name="focusPainted" type="boolean" value="false"/>
+          </Properties>
+          <Events>
+            <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="resetAllButtonMousePressed"/>
+          </Events>
+        </Component>
+        <Container class="javax.swing.JPanel" name="shiftPanel">
+
+          <Layout>
+            <DimensionLayout dim="0">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <EmptySpace min="0" pref="21" max="32767" attributes="0"/>
+              </Group>
+            </DimensionLayout>
+            <DimensionLayout dim="1">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <EmptySpace min="0" pref="84" max="32767" attributes="0"/>
+              </Group>
+            </DimensionLayout>
+          </Layout>
+        </Container>
+        <Component class="javax.swing.JSeparator" name="jSeparator10">
+          <Properties>
+            <Property name="orientation" type="int" value="1"/>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JButton" name="applyButton">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.applyButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+            <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.applyButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+            <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+              <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                <TitledBorder/>
+              </Border>
+            </Property>
+            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+              <Color id="Hand Cursor"/>
+            </Property>
+            <Property name="focusPainted" type="boolean" value="false"/>
+          </Properties>
+          <Events>
+            <EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="applyButtonMousePressed"/>
+          </Events>
+        </Component>
+        <Component class="javax.swing.JSeparator" name="jSeparator5">
+        </Component>
+        <Component class="javax.swing.JLabel" name="shiftLabel">
+          <Properties>
+            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+              <Font name="Ubuntu" size="15" style="1"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.shiftLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+            <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.shiftLabel.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JRadioButton" name="lowShiftRB">
+          <Properties>
+            <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
+              <ComponentRef name="precisionGroup"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.lowShiftRB.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+            <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.lowShiftRB.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="lowShiftRBActionPerformed"/>
+          </Events>
+        </Component>
+        <Component class="javax.swing.JRadioButton" name="highShiftRB">
+          <Properties>
+            <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
+              <ComponentRef name="precisionGroup"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.highShiftRB.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+            <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.highShiftRB.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="highShiftRBActionPerformed"/>
+          </Events>
+        </Component>
+        <Component class="javax.swing.JLabel" name="jLabel2">
+          <Properties>
+            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+              <Font name="Ubuntu" size="15" style="1"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JSeparator" name="jSeparator4">
+        </Component>
+      </SubComponents>
+    </Container>
+    <Component class="javax.swing.JSeparator" name="jSeparator2">
+    </Component>
+    <Container class="javax.swing.JPanel" name="jPanel1">
+      <Properties>
+        <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+          <Dimension value="[600, 32767]"/>
+        </Property>
+      </Properties>
+
+      <Layout>
+        <DimensionLayout dim="0">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" attributes="0">
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Group type="102" alignment="0" attributes="0">
+                          <Component id="jLabel3" min="-2" max="-2" attributes="0"/>
+                          <EmptySpace max="32767" attributes="0"/>
+                      </Group>
+                      <Group type="102" alignment="0" attributes="0">
+                          <Group type="103" groupAlignment="0" attributes="0">
+                              <Group type="102" alignment="0" attributes="0">
+                                  <Component id="jLabel8" min="-2" max="-2" attributes="0"/>
+                                  <EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
+                                  <Component id="jComboBox1" min="-2" pref="166" max="-2" attributes="0"/>
+                                  <EmptySpace max="32767" attributes="0"/>
+                              </Group>
+                              <Group type="102" alignment="0" attributes="0">
+                                  <Component id="jLabel7" min="-2" max="-2" attributes="0"/>
+                                  <EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
+                                  <Component id="jCheckBox1" min="-2" max="-2" attributes="0"/>
+                                  <EmptySpace max="32767" attributes="0"/>
+                                  <Component id="jLabel5" min="-2" max="-2" attributes="0"/>
+                                  <EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
+                                  <Component id="jFormattedTextField1" min="-2" pref="49" max="-2" attributes="0"/>
+                                  <EmptySpace min="-2" pref="57" max="-2" attributes="0"/>
+                              </Group>
+                          </Group>
+                          <Group type="103" groupAlignment="0" attributes="0">
+                              <Component id="jButton1" alignment="1" min="-2" max="-2" attributes="0"/>
+                              <Group type="102" alignment="1" attributes="0">
+                                  <Component id="jLabel6" min="-2" max="-2" attributes="0"/>
+                                  <EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
+                                  <Component id="jFormattedTextField2" min="-2" pref="53" max="-2" attributes="0"/>
+                              </Group>
+                          </Group>
+                          <EmptySpace min="-2" pref="54" max="-2" attributes="0"/>
+                      </Group>
+                  </Group>
+              </Group>
+          </Group>
+        </DimensionLayout>
+        <DimensionLayout dim="1">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="0" attributes="0">
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Component id="jLabel3" min="-2" max="-2" attributes="0"/>
+                  <EmptySpace type="unrelated" max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Component id="jLabel7" min="-2" max="-2" attributes="0"/>
+                      <Component id="jCheckBox1" min="-2" max="-2" attributes="0"/>
+                      <Group type="103" groupAlignment="3" attributes="0">
+                          <Component id="jFormattedTextField1" alignment="3" min="-2" pref="22" max="-2" attributes="0"/>
+                          <Component id="jLabel5" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="jLabel6" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="jFormattedTextField2" alignment="3" min="-2" pref="20" max="-2" attributes="0"/>
+                      </Group>
+                  </Group>
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Component id="jButton1" alignment="0" min="-2" max="-2" attributes="0"/>
+                      <Group type="103" groupAlignment="3" attributes="0">
+                          <Component id="jLabel8" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="jComboBox1" alignment="3" min="-2" pref="27" max="-2" attributes="0"/>
+                      </Group>
+                  </Group>
+                  <EmptySpace pref="13" max="32767" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+      </Layout>
+      <SubComponents>
+        <Component class="javax.swing.JLabel" name="jLabel3">
+          <Properties>
+            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+              <Font name="Ubuntu" size="15" style="1"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel3.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JLabel" name="jLabel7">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel7.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JCheckBox" name="jCheckBox1">
+          <Properties>
+            <Property name="selected" type="boolean" value="true"/>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jCheckBox1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jCheckBox1ActionPerformed"/>
+          </Events>
+        </Component>
+        <Component class="javax.swing.JLabel" name="jLabel5">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel5.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JFormattedTextField" name="jFormattedTextField1">
+          <Properties>
+            <Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.editors.AbstractFormatterFactoryEditor">
+              <Format subtype="0" type="0"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jFormattedTextField1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JLabel" name="jLabel6">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel6.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JFormattedTextField" name="jFormattedTextField2">
+          <Properties>
+            <Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.editors.AbstractFormatterFactoryEditor">
+              <Format subtype="1" type="0"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jFormattedTextField2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JLabel" name="jLabel8">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel8.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JComboBox" name="jComboBox1">
+          <Properties>
+            <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
+              <StringArray count="2">
+                <StringItem index="0" value="None"/>
+                <StringItem index="1" value="Random 200"/>
+              </StringArray>
+            </Property>
+          </Properties>
+          <AuxValues>
+            <AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
+          </AuxValues>
+        </Component>
+        <Component class="javax.swing.JButton" name="jButton1">
+          <Properties>
+            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+              <Font name="Ubuntu" size="15" style="1"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton1ActionPerformed"/>
+          </Events>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Container class="javax.swing.JPanel" name="jPanel2">
+      <Properties>
+        <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+          <Dimension value="[600, 74]"/>
+        </Property>
+      </Properties>
+
+      <Layout>
+        <DimensionLayout dim="0">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" attributes="0">
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Component id="jLabel4" alignment="0" min="-2" max="-2" attributes="0"/>
+                      <Component id="jSeparator1" alignment="0" min="-2" pref="600" max="-2" attributes="0"/>
+                      <Group type="102" alignment="0" attributes="0">
+                          <Component id="jLabel22" min="-2" max="-2" attributes="0"/>
+                          <EmptySpace max="-2" attributes="0"/>
+                          <Component id="jCheckBox2" min="-2" max="-2" attributes="0"/>
+                          <EmptySpace max="-2" attributes="0"/>
+                          <Component id="jLabel23" min="-2" max="-2" attributes="0"/>
+                          <EmptySpace max="-2" attributes="0"/>
+                          <Component id="jComboBox2" min="-2" pref="145" max="-2" attributes="0"/>
+                          <EmptySpace min="-2" pref="40" max="-2" attributes="0"/>
+                          <Component id="jToggleButton1" min="-2" max="-2" attributes="0"/>
+                      </Group>
+                  </Group>
+                  <EmptySpace max="32767" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+        <DimensionLayout dim="1">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="0" attributes="0">
+                  <Component id="jSeparator1" min="-2" pref="10" max="-2" attributes="0"/>
+                  <EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="1" attributes="0">
+                      <Group type="102" attributes="0">
+                          <Component id="jLabel4" min="-2" max="-2" attributes="0"/>
+                          <EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
+                          <Group type="103" groupAlignment="0" attributes="0">
+                              <Component id="jCheckBox2" alignment="0" min="-2" max="-2" attributes="0"/>
+                              <Component id="jLabel22" min="-2" max="-2" attributes="0"/>
+                          </Group>
+                      </Group>
+                      <Group type="103" groupAlignment="3" attributes="0">
+                          <Component id="jLabel23" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="jComboBox2" alignment="3" min="-2" pref="29" max="-2" attributes="0"/>
+                          <Component id="jToggleButton1" alignment="3" min="-2" max="-2" attributes="0"/>
+                      </Group>
+                  </Group>
+                  <EmptySpace max="32767" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+      </Layout>
+      <SubComponents>
+        <Component class="javax.swing.JLabel" name="jLabel4">
+          <Properties>
+            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+              <Font name="Ubuntu" size="15" style="1"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel4.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JSeparator" name="jSeparator1">
+        </Component>
+        <Component class="javax.swing.JLabel" name="jLabel22">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel22.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JCheckBox" name="jCheckBox2">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jCheckBox2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JLabel" name="jLabel23">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel23.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JComboBox" name="jComboBox2">
+          <Properties>
+            <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
+              <StringArray count="2">
+                <StringItem index="0" value="Point to point"/>
+                <StringItem index="1" value="Point to triangle"/>
+              </StringArray>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jComboBox2ActionPerformed"/>
+          </Events>
+          <AuxValues>
+            <AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
+          </AuxValues>
+        </Component>
+        <Component class="javax.swing.JToggleButton" name="jToggleButton1">
+          <Properties>
+            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+              <Font name="Ubuntu" size="15" style="1"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jToggleButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jToggleButton1ActionPerformed"/>
+          </Events>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Container class="javax.swing.JPanel" name="jPanel4">
+
+      <Layout>
+        <DimensionLayout dim="0">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" attributes="0">
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Component id="jSeparator3" alignment="1" max="32767" attributes="0"/>
+                      <Group type="102" attributes="0">
+                          <Group type="103" groupAlignment="1" max="-2" attributes="0">
+                              <Group type="102" attributes="0">
+                                  <Component id="featurePointsLabel" min="-2" max="-2" attributes="0"/>
+                                  <EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
+                                  <Component id="thersholdFTF" min="-2" pref="55" max="-2" attributes="0"/>
+                                  <EmptySpace max="-2" attributes="0"/>
+                                  <Component id="thersholdUpButton" min="-2" max="-2" attributes="0"/>
+                                  <EmptySpace max="-2" attributes="0"/>
+                                  <Component id="thresholdDownButton" min="-2" max="-2" attributes="0"/>
+                                  <EmptySpace max="32767" attributes="0"/>
+                                  <Component id="frontButton" min="-2" pref="85" max="-2" attributes="0"/>
+                                  <EmptySpace max="-2" attributes="0"/>
+                                  <Component id="profileButton" min="-2" pref="85" max="-2" attributes="0"/>
+                              </Group>
+                              <Group type="103" groupAlignment="0" attributes="0">
+                                  <Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
+                                  <Group type="102" alignment="0" attributes="0">
+                                      <Component id="visualizationLabel" min="-2" max="-2" attributes="0"/>
+                                      <EmptySpace max="-2" attributes="0"/>
+                                      <Component id="transparencySlider" min="-2" pref="344" max="-2" attributes="0"/>
+                                      <EmptySpace type="unrelated" max="-2" attributes="0"/>
+                                      <Component id="transparencyButton" min="-2" pref="72" max="-2" attributes="0"/>
+                                  </Group>
+                              </Group>
+                          </Group>
+                          <EmptySpace min="26" pref="34" max="32767" attributes="0"/>
+                      </Group>
+                  </Group>
+              </Group>
+          </Group>
+        </DimensionLayout>
+        <DimensionLayout dim="1">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="0" attributes="0">
+                  <Component id="jSeparator3" min="-2" pref="10" max="-2" attributes="0"/>
+                  <EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
+                  <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Component id="transparencySlider" min="-2" max="-2" attributes="0"/>
+                      <Group type="102" alignment="0" attributes="0">
+                          <EmptySpace type="separate" max="-2" attributes="0"/>
+                          <Component id="visualizationLabel" min="-2" max="-2" attributes="0"/>
+                      </Group>
+                      <Group type="102" alignment="0" attributes="0">
+                          <EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
+                          <Component id="transparencyButton" min="-2" max="-2" attributes="0"/>
+                      </Group>
+                  </Group>
+                  <EmptySpace type="unrelated" max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="1" attributes="0">
+                      <Group type="102" attributes="0">
+                          <Group type="103" groupAlignment="3" attributes="0">
+                              <Component id="featurePointsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+                              <Component id="thersholdFTF" alignment="3" min="-2" pref="27" max="-2" attributes="0"/>
+                          </Group>
+                          <EmptySpace min="-2" pref="55" max="-2" attributes="0"/>
+                      </Group>
+                      <Group type="102" alignment="0" attributes="0">
+                          <Group type="103" groupAlignment="1" max="-2" attributes="0">
+                              <Component id="profileButton" max="32767" attributes="0"/>
+                              <Component id="frontButton" alignment="0" max="32767" attributes="0"/>
+                              <Component id="thersholdUpButton" alignment="0" max="32767" attributes="0"/>
+                              <Component id="thresholdDownButton" alignment="0" max="32767" attributes="0"/>
+                          </Group>
+                          <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
+                      </Group>
+                  </Group>
+              </Group>
+          </Group>
+        </DimensionLayout>
+      </Layout>
+      <SubComponents>
+        <Component class="javax.swing.JLabel" name="jLabel1">
+          <Properties>
+            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+              <Font name="Ubuntu" size="15" style="1"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JLabel" name="visualizationLabel">
+          <Properties>
+            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+              <Font name="Tahoma" size="14" style="0"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.visualizationLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JSlider" name="transparencySlider">
+          <Properties>
+            <Property name="majorTickSpacing" type="int" value="5"/>
+            <Property name="maximum" type="int" value="20"/>
+            <Property name="minorTickSpacing" type="int" value="5"/>
+            <Property name="paintTicks" type="boolean" value="true"/>
+            <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.transparencySlider.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+            <Property name="value" type="int" value="10"/>
+            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+              <Color id="Hand Cursor"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="transparencySliderStateChanged"/>
+          </Events>
+        </Component>
+        <Component class="javax.swing.JButton" name="transparencyButton">
+          <Properties>
+            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+              <Font name="Ubuntu" size="14" style="0"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.transparencyButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+            <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.transparencyButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+            <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+              <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                <TitledBorder>
+                  <Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
+                    <EtchetBorder/>
+                  </Border>
+                </TitledBorder>
+              </Border>
+            </Property>
+            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+              <Color id="Default Cursor"/>
+            </Property>
+            <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+              <Dimension value="[100, 19]"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="transparencyButtonActionPerformed"/>
+          </Events>
+        </Component>
+        <Component class="javax.swing.JButton" name="frontButton">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.frontButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+            <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.frontButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+            <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+              <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                <TitledBorder>
+                  <Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
+                    <EtchetBorder/>
+                  </Border>
+                </TitledBorder>
+              </Border>
+            </Property>
+            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+              <Color id="Default Cursor"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="frontButtonActionPerformed"/>
+          </Events>
+        </Component>
+        <Component class="javax.swing.JButton" name="profileButton">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.profileButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+            <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.profileButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+            <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+              <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                <TitledBorder>
+                  <Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
+                    <EtchetBorder/>
+                  </Border>
+                </TitledBorder>
+              </Border>
+            </Property>
+            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+              <Color id="Default Cursor"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JLabel" name="featurePointsLabel">
+          <Properties>
+            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+              <Font name="Tahoma" size="14" style="0"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.featurePointsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JFormattedTextField" name="thersholdFTF">
+          <Properties>
+            <Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.editors.AbstractFormatterFactoryEditor">
+              <Format subtype="0" type="0"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JButton" name="thersholdUpButton">
+          <Properties>
+            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+              <Image iconType="3" name="/add-line.png"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.thersholdUpButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+            <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+              <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                <TitledBorder/>
+              </Border>
+            </Property>
+            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+              <Color id="Default Cursor"/>
+            </Property>
+            <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+              <Dimension value="[24, 24]"/>
+            </Property>
+            <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+              <Dimension value="[24, 24]"/>
+            </Property>
+            <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+              <Dimension value="[24, 24]"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="thersholdUpButtonActionPerformed"/>
+          </Events>
+        </Component>
+        <Component class="javax.swing.JButton" name="thresholdDownButton">
+          <Properties>
+            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+              <Image iconType="3" name="/subtract-line.png"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.thresholdDownButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+            <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+              <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                <TitledBorder/>
+              </Border>
+            </Property>
+            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+              <Color id="Default Cursor"/>
+            </Property>
+            <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+              <Dimension value="[24, 24]"/>
+            </Property>
+            <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+              <Dimension value="[24, 24]"/>
+            </Property>
+            <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+              <Dimension value="[24, 24]"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="thresholdDownButtonActionPerformed"/>
+          </Events>
+        </Component>
+        <Component class="javax.swing.JSeparator" name="jSeparator3">
+        </Component>
+      </SubComponents>
+    </Container>
+    <Container class="javax.swing.JPanel" name="jPanel6">
+
+      <Layout>
+        <DimensionLayout dim="0">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" attributes="0">
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" max="-2" attributes="0">
+                      <Group type="102" alignment="1" attributes="0">
+                          <Component id="jPanel5" min="-2" max="-2" attributes="0"/>
+                          <EmptySpace max="32767" attributes="0"/>
+                          <Component id="jPanel3" min="-2" max="-2" attributes="0"/>
+                          <EmptySpace min="-2" pref="22" max="-2" attributes="0"/>
+                      </Group>
+                      <Component id="jLabel9" min="-2" max="-2" attributes="0"/>
+                      <Component id="jSeparator6" min="-2" pref="587" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace max="32767" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+        <DimensionLayout dim="1">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="0" attributes="0">
+                  <Component id="jSeparator6" min="-2" pref="10" max="-2" attributes="0"/>
+                  <EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
+                  <Component id="jLabel9" min="-2" max="-2" attributes="0"/>
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Component id="jPanel5" min="-2" pref="50" max="-2" attributes="0"/>
+                      <Component id="jPanel3" min="-2" pref="50" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace min="0" pref="20" max="32767" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+      </Layout>
+      <SubComponents>
+        <Component class="javax.swing.JLabel" name="jLabel9">
+          <Properties>
+            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+              <Font name="Ubuntu" size="15" style="1"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel9.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Container class="javax.swing.JPanel" name="jPanel5">
+          <Properties>
+            <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+              <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                <TitledBorder title="distance of feature points">
+                  <ResourceString PropertyName="titleX" bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jPanel5.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </TitledBorder>
+              </Border>
+            </Property>
+          </Properties>
+
+          <Layout>
+            <DimensionLayout dim="0">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" alignment="0" attributes="0">
+                      <EmptySpace min="-2" pref="9" max="-2" attributes="0"/>
+                      <Component id="jLabel12" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="jLabel13" min="-2" pref="42" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="jLabel10" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="jLabel15" min="-2" pref="39" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="jLabel11" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="jLabel14" min="-2" pref="45" max="-2" attributes="0"/>
+                      <EmptySpace max="32767" attributes="0"/>
+                  </Group>
+              </Group>
+            </DimensionLayout>
+            <DimensionLayout dim="1">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" alignment="0" attributes="0">
+                      <EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
+                      <Group type="103" groupAlignment="3" attributes="0">
+                          <Component id="jLabel12" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="jLabel13" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="jLabel10" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="jLabel15" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="jLabel11" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="jLabel14" alignment="3" min="-2" max="-2" attributes="0"/>
+                      </Group>
+                      <EmptySpace max="32767" attributes="0"/>
+                  </Group>
+              </Group>
+            </DimensionLayout>
+          </Layout>
+          <SubComponents>
+            <Component class="javax.swing.JLabel" name="jLabel12">
+              <Properties>
+                <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+                  <Font name="Ubuntu" size="15" style="1"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel12.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JLabel" name="jLabel13">
+              <Properties>
+                <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+                  <Font name="Ubuntu" size="15" style="1"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel13.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JLabel" name="jLabel10">
+              <Properties>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel10.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JLabel" name="jLabel15">
+              <Properties>
+                <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+                  <Font name="Ubuntu" size="15" style="0"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel15.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JLabel" name="jLabel11">
+              <Properties>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel11.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JLabel" name="jLabel14">
+              <Properties>
+                <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+                  <Font name="Ubuntu" size="15" style="0"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel14.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+          </SubComponents>
+        </Container>
+        <Container class="javax.swing.JPanel" name="jPanel3">
+          <Properties>
+            <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+              <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+                <TitledBorder title="Hausdorff distance">
+                  <ResourceString PropertyName="titleX" bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jPanel3.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </TitledBorder>
+              </Border>
+            </Property>
+          </Properties>
+
+          <Layout>
+            <DimensionLayout dim="0">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" alignment="0" attributes="0">
+                      <EmptySpace min="-2" pref="9" max="-2" attributes="0"/>
+                      <Component id="jLabel16" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="jLabel17" min="-2" pref="40" max="-2" attributes="0"/>
+                      <EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
+                      <Component id="jLabel18" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="jLabel19" min="-2" pref="40" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="jLabel20" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="jLabel21" min="-2" pref="40" max="-2" attributes="0"/>
+                      <EmptySpace max="32767" attributes="0"/>
+                  </Group>
+              </Group>
+            </DimensionLayout>
+            <DimensionLayout dim="1">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" alignment="0" attributes="0">
+                      <EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
+                      <Group type="103" groupAlignment="3" attributes="0">
+                          <Component id="jLabel16" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="jLabel17" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="jLabel18" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="jLabel19" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="jLabel20" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="jLabel21" alignment="3" min="-2" max="-2" attributes="0"/>
+                      </Group>
+                      <EmptySpace max="32767" attributes="0"/>
+                  </Group>
+              </Group>
+            </DimensionLayout>
+          </Layout>
+          <SubComponents>
+            <Component class="javax.swing.JLabel" name="jLabel16">
+              <Properties>
+                <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+                  <Font name="Ubuntu" size="15" style="1"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel16.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JLabel" name="jLabel17">
+              <Properties>
+                <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+                  <Font name="Ubuntu" size="15" style="1"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel17.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JLabel" name="jLabel18">
+              <Properties>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel18.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JLabel" name="jLabel19">
+              <Properties>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel19.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JLabel" name="jLabel20">
+              <Properties>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel20.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Component class="javax.swing.JLabel" name="jLabel21">
+              <Properties>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jLabel21.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+          </SubComponents>
+        </Container>
+        <Component class="javax.swing.JSeparator" name="jSeparator6">
+        </Component>
+      </SubComponents>
+    </Container>
+  </SubComponents>
+</Form>
diff --git a/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.java b/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.java
new file mode 100644
index 0000000000000000000000000000000000000000..f0e8978a33c0f467a9bd2d3f5d1f7030303ece26
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.java
@@ -0,0 +1,1858 @@
+package cz.fidentis.analyst.registration;
+
+import cz.fidentis.analyst.canvas.Direction;
+import cz.fidentis.analyst.core.ControlPanel;
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import javax.swing.AbstractAction;
+import javax.swing.ImageIcon;
+import javax.swing.JFormattedTextField;
+import javax.swing.JLabel;
+
+/**
+ * Panel used to interactively visualize two face and adjust their registration.
+ * 
+ * @author Richard Pajersky
+ * @author Radek Oslejsek
+ */
+public class RegistrationPanel extends ControlPanel {
+    
+    /*
+     * Mandatory design elements
+     */
+    public static final String ICON = "registration28x28.png";
+    public static final String NAME = "Registration";
+    
+    /*
+     * External actions
+     */
+    public static final String ACTION_COMMAND_APPLY_ICP = "apply ICP";
+    
+    public static final String ACTION_COMMAND_SHIFT_X = "shift x";
+    public static final String ACTION_COMMAND_SHIFT_Y = "shift y";
+    public static final String ACTION_COMMAND_SHIFT_Z = "shift z";
+    public static final String ACTION_COMMAND_ROTATE_X = "rotate x";
+    public static final String ACTION_COMMAND_ROTATE_Y = "rotate y";
+    public static final String ACTION_COMMAND_ROTATE_Z = "rotate z";
+    public static final String ACTION_COMMAND_SCALE = "scale";
+    public static final String ACTION_COMMAND_RESET_ROTATION = "reset translation";
+    public static final String ACTION_COMMAND_RESET_TRANSLATION = "reset rotation";
+    public static final String ACTION_COMMAND_RESET_SCALE = "reset scale";
+    public static final String ACTION_COMMAND_APPLY_TRANSFORMATIONS = "apply transformations";
+    
+    public static final String ACTION_COMMAND_FRONT_VIEW = "front view";
+    public static final String ACTION_COMMAND_SIDE_VIEW = "side view";
+    public static final String ACTION_COMMAND_TRANSPARENCY = "transparency";
+    
+    public static final String ACTION_COMMAND_FP_CLOSENESS_THRESHOLD = "fp closeness treshold";
+    
+    public static final String ACTION_COMMAND_ICP_SCALE = "ICP scale";
+    public static final String ACTION_COMMAND_ICP_MAX_ITERATIONS = "ICP iterations";
+    public static final String ACTION_COMMAND_ICP_ERROR = "ICP error";
+    public static final String ACTION_COMMAND_ICP_UNDERSAMPLING = "ICP undersampling";
+    
+    public static final String ACTION_COMMAND_HD_HEATMAP = "show-hide heatmap";
+    public static final String ACTION_COMMAND_HD_STRATEGY = "set strategy";
+    public static final String ACTION_COMMAND_HD_RELATIVE_DIST = "switch abosulte-relative distance";
+    
+    /*
+     * Configuration of panel-specific GUI elements
+     */
+    public static final String  STRATEGY_POINT_TO_POINT= "Point to point";
+    public static final String  STRATEGY_POINT_TO_TRIANGLE= "Point to triangle";
+    
+    public static final double TRANSFORMATION_FINESS = 1.0;
+    
+    /**
+     * Range of transparency 
+     */
+    public static final int TRANSPARENCY_RANGE = 10;
+    
+    /**
+     * Transformation shift is higher 
+     */
+    public static final double HIGH_SHIFT_QUOTIENT = 1.0;
+    
+    /**
+     * Transformation shift is lower 
+     */
+    public static final double LOW_SHIFT_QUOTIENT = 0.1;
+    
+
+    /**
+     * Listener which translates executed actions 
+     * into {@link cz.fidentis.analyst.scene.DrawableMesh}
+     */
+    private final ActionListener listener;
+    
+    /**
+     * Animator which animates transformations
+     */
+    private final ModelRotationAnimator animator = new ModelRotationAnimator();
+    
+    private double moveModifier = LOW_SHIFT_QUOTIENT;
+    
+    /**
+     * Feature points statistics
+     */
+    private double fpMaxDist = Double.NEGATIVE_INFINITY;
+    private double fpMinDist = Double.POSITIVE_INFINITY;
+    private double fpAvgDist = 0.0;
+    
+    /**
+     * Constructor.
+     * @param action Action listener
+     */
+    public RegistrationPanel(ActionListener action) {
+        this.setName(NAME);
+        this.listener = action;
+        initComponents();
+        setDefaults();
+        
+        // connect GUI element with RegistrationAction listener:
+        jButton1.addActionListener(createListener(action, ACTION_COMMAND_APPLY_ICP));
+        translationXFTF.addActionListener(createListener(action, ACTION_COMMAND_SHIFT_X));
+        translationYFTF.addActionListener(createListener(action, ACTION_COMMAND_SHIFT_Y));
+        translationZFTF.addActionListener(createListener(action, ACTION_COMMAND_SHIFT_Z));
+        rotationXFTF.addActionListener(createListener(action, ACTION_COMMAND_ROTATE_X));
+        rotationYFTF.addActionListener(createListener(action, ACTION_COMMAND_ROTATE_Y));
+        rotationZFTF.addActionListener(createListener(action, ACTION_COMMAND_ROTATE_Z));
+        scaleFTF.addActionListener(createListener(action, ACTION_COMMAND_SCALE));
+        frontButton.addActionListener(createListener(action, ACTION_COMMAND_FRONT_VIEW));
+        profileButton.addActionListener(createListener(action, ACTION_COMMAND_SIDE_VIEW));
+        translationButton.addActionListener(createListener(action, ACTION_COMMAND_RESET_TRANSLATION));
+        rotationButton.addActionListener(createListener(action, ACTION_COMMAND_RESET_ROTATION));
+        scaleButton.addActionListener(createListener(action, ACTION_COMMAND_RESET_SCALE));
+        
+        resetAllButton.addActionListener(createListener(action, ACTION_COMMAND_RESET_TRANSLATION));
+        resetAllButton.addActionListener(createListener(action, ACTION_COMMAND_RESET_SCALE));
+        resetAllButton.addActionListener(createListener(action, ACTION_COMMAND_RESET_ROTATION));
+        
+        applyButton.addActionListener(createListener(action, ACTION_COMMAND_APPLY_TRANSFORMATIONS));
+        thersholdFTF.addActionListener(createListener(action, ACTION_COMMAND_FP_CLOSENESS_THRESHOLD));
+        jCheckBox1.addActionListener(createListener(action, ACTION_COMMAND_ICP_SCALE));
+        jFormattedTextField1.addActionListener(createListener(action, ACTION_COMMAND_ICP_ERROR));
+        jFormattedTextField2.addActionListener(createListener(action, ACTION_COMMAND_ICP_MAX_ITERATIONS));
+        jComboBox1.addActionListener(createListener(action, ACTION_COMMAND_ICP_UNDERSAMPLING));
+        
+        jCheckBox2.addActionListener(createListener(action, ACTION_COMMAND_HD_RELATIVE_DIST));
+        jComboBox2.addActionListener(createListener(action, ACTION_COMMAND_HD_STRATEGY));
+        jToggleButton1.addActionListener(createListener(action, ACTION_COMMAND_HD_HEATMAP));
+        
+        // Hide then re-compute HD when manipulating with the secondary face:
+        ActionListener heatmapOff = new AbstractAction() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                if (jToggleButton1.isSelected()) {
+                    jToggleButton1.doClick();
+                }
+                initHDStats();
+            }  
+        };        
+        translationXFTF.addActionListener(heatmapOff);
+        translationYFTF.addActionListener(heatmapOff);
+        translationZFTF.addActionListener(heatmapOff);
+        rotationXFTF.addActionListener(heatmapOff);
+        rotationYFTF.addActionListener(heatmapOff);
+        rotationZFTF.addActionListener(heatmapOff);
+        scaleFTF.addActionListener(heatmapOff);
+    }
+    
+    /**
+     * Sets given values as basic values that we aim to improve.
+     * 
+     * @param avg Average distance
+     * @param max Maximal distance
+     * @param min Minimal distance
+     */
+    public void initFPStats(double avg, double max, double min) {
+        fpMaxDist = max;
+        fpMinDist = min;
+        fpAvgDist = avg;        
+    }
+    
+    /**
+     * Updates statistics related to the distance of feature points
+     * @param avg Average distance
+     * @param max Maximal distance
+     * @param min Minimal distance
+     */
+    public void updateFPStats(double avg, double max, double min) {
+        if (fpMaxDist == Double.NEGATIVE_INFINITY) { // first calculation
+            initFPStats(avg, max, min);
+        }
+        
+        setStats(min, fpMinDist, jLabel15);
+        setStats(max, fpMaxDist, jLabel14);
+        setStats(avg, fpAvgDist, jLabel13);
+    }
+    
+    /**
+     * Updates statistics related to the Hausdorff distance.
+     * @param avg Average distance
+     * @param max Maximal distance
+     * @param min Minimal distance
+     */
+    public void updateHDStats(double avg, double max, double min) {
+        NumberFormat formatter = new DecimalFormat("#0.00"); 
+        jLabel19.setText(formatter.format(min));
+        jLabel21.setText(formatter.format(max));
+        jLabel17.setText(formatter.format(avg));
+    }
+    
+    private void initHDStats() {
+        updateHDStats(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
+    }
+    
+    private void setStats(double newVal, double oldVal, JLabel label) {
+        if (newVal < oldVal) {
+            label.setForeground(Color.GREEN);
+        } else if (newVal > oldVal) {
+            label.setForeground(Color.RED);
+        } else {
+            label.setForeground(Color.BLACK);
+        }
+        
+        NumberFormat formatter = new DecimalFormat("#0.00"); 
+        label.setText(formatter.format(newVal));
+    }
+    
+    /**
+     * Alters transformation based on move amount specified in listener
+     * by updating specific formatted field
+     * 
+     * @param dir Transformation direction
+     * @throws UnsupportedOperationException if {@code dir} is invalid
+     */
+    public void transform(Direction dir) {
+        switch (dir) {
+            case TRANSLATE_LEFT:
+                decreaseInputField(translationXFTF);
+                break;
+            case TRANSLATE_RIGHT:
+                increaseInputField(translationXFTF);
+                break;
+            case TRANSLATE_UP:
+                decreaseInputField(translationYFTF);
+                break;
+            case TRANSLATE_DOWN:
+                increaseInputField(translationYFTF);
+                break;
+            case TRANSLATE_IN:
+                decreaseInputField(translationZFTF);
+                break;
+            case TRANSLATE_OUT:
+                increaseInputField(translationZFTF);
+                break;
+            case ROTATE_LEFT:
+                decreaseInputField(rotationXFTF);
+                break;
+            case ROTATE_RIGHT:
+                increaseInputField(rotationXFTF);
+                break;
+            case ROTATE_UP:
+                increaseInputField(rotationYFTF);
+                break;
+            case ROTATE_DOWN:
+                decreaseInputField(rotationYFTF);
+                break;
+            case ROTATE_IN:
+                increaseInputField(rotationZFTF);
+                break;
+            case ROTATE_OUT:
+                decreaseInputField(rotationZFTF);
+                break;
+            case ZOOM_OUT:
+                decreaseInputField(scaleFTF);
+                break;
+            case ZOOM_IN:
+                increaseInputField(scaleFTF);
+                break;
+            default:
+                throw new UnsupportedOperationException();
+        }
+    }
+    
+    @Override
+    public ImageIcon getIcon() {
+        return getStaticIcon();
+    }
+    
+    /**
+     * Static implementation of the {@link #getIcon()} method.
+     * 
+     * @return Control panel icon
+     */
+    public static ImageIcon getStaticIcon() {
+        return new ImageIcon(RegistrationPanel.class.getClassLoader().getResource("/" + ICON));
+    }
+
+    /**
+     * Additional initialization of panel
+     */
+    private void setDefaults() {
+        lowShiftRB.setSelected(true);
+        thersholdFTF.setValue(5.0);
+        //resetAllButtonActionPerformed(null);
+        
+        rotationXFTF.setValue(0.0);
+        rotationYFTF.setValue(0.0);
+        rotationZFTF.setValue(0.0);
+        translationXFTF.setValue(0.0);
+        translationYFTF.setValue(0.0);
+        translationZFTF.setValue(0.0);
+        scaleFTF.setValue(0.0);
+        
+        initHDStats();
+    }
+    
+    private void increaseInputField(JFormattedTextField textField) {
+        double newValue = ((Number)textField.getValue()).doubleValue() + moveModifier;
+        newValue *= TRANSFORMATION_FINESS;
+        textField.setValue(newValue);
+        textField.postActionEvent();
+    }
+    
+    private void decreaseInputField(JFormattedTextField textField) {
+        double newValue = ((Number)textField.getValue()).doubleValue() - moveModifier;
+        newValue *= TRANSFORMATION_FINESS;
+        textField.setValue(newValue);
+        textField.postActionEvent();
+    }
+    
+    /**
+     * This method is called from within the constructor to initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is always
+     * regenerated by the Form Editor.
+     */
+    @SuppressWarnings("unchecked")
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        primaryRenderModeGroup = new javax.swing.ButtonGroup();
+        secondaryRenerModeGroup = new javax.swing.ButtonGroup();
+        precisionGroup = new javax.swing.ButtonGroup();
+        jSeparator11 = new javax.swing.JSeparator();
+        transformationPanel = new javax.swing.JPanel();
+        translationPanel = new javax.swing.JPanel();
+        translationButton = new javax.swing.JButton();
+        rightTranslationXButton = new javax.swing.JButton();
+        translationXFTF = new javax.swing.JFormattedTextField();
+        leftTranslationYButton = new javax.swing.JButton();
+        translationYFTF = new javax.swing.JFormattedTextField();
+        rightTranslationYButton = new javax.swing.JButton();
+        translXLabel = new javax.swing.JLabel();
+        translationZFTF = new javax.swing.JFormattedTextField();
+        translZLabel = new javax.swing.JLabel();
+        translYLabel = new javax.swing.JLabel();
+        rightTranslationZButton = new javax.swing.JButton();
+        leftTranslationXButton = new javax.swing.JButton();
+        leftTranslationZButton = new javax.swing.JButton();
+        rotationPanel = new javax.swing.JPanel();
+        leftRotationYButton = new javax.swing.JButton();
+        leftRotationXButton = new javax.swing.JButton();
+        rotatZLabel = new javax.swing.JLabel();
+        rotatYLabel = new javax.swing.JLabel();
+        rotatXLabel = new javax.swing.JLabel();
+        rotationButton = new javax.swing.JButton();
+        rotationZFTF = new javax.swing.JFormattedTextField();
+        rotationYFTF = new javax.swing.JFormattedTextField();
+        rightRotationZButton = new javax.swing.JButton();
+        rightRotationYButton = new javax.swing.JButton();
+        leftRotationZButton = new javax.swing.JButton();
+        rightRotationXButton = new javax.swing.JButton();
+        rotationXFTF = new javax.swing.JFormattedTextField();
+        scalePanel = new javax.swing.JPanel();
+        scalePlusButton = new javax.swing.JButton();
+        scaleFTF = new javax.swing.JFormattedTextField();
+        scaleButton = new javax.swing.JButton();
+        scaleMinusButton = new javax.swing.JButton();
+        resetAllButton = new javax.swing.JButton();
+        shiftPanel = new javax.swing.JPanel();
+        jSeparator10 = new javax.swing.JSeparator();
+        applyButton = new javax.swing.JButton();
+        jSeparator5 = new javax.swing.JSeparator();
+        shiftLabel = new javax.swing.JLabel();
+        lowShiftRB = new javax.swing.JRadioButton();
+        highShiftRB = new javax.swing.JRadioButton();
+        jLabel2 = new javax.swing.JLabel();
+        jSeparator4 = new javax.swing.JSeparator();
+        jSeparator2 = new javax.swing.JSeparator();
+        jPanel1 = new javax.swing.JPanel();
+        jLabel3 = new javax.swing.JLabel();
+        jLabel7 = new javax.swing.JLabel();
+        jCheckBox1 = new javax.swing.JCheckBox();
+        jLabel5 = new javax.swing.JLabel();
+        jFormattedTextField1 = new javax.swing.JFormattedTextField();
+        jLabel6 = new javax.swing.JLabel();
+        jFormattedTextField2 = new javax.swing.JFormattedTextField();
+        jLabel8 = new javax.swing.JLabel();
+        jComboBox1 = new javax.swing.JComboBox<>();
+        jButton1 = new javax.swing.JButton();
+        jPanel2 = new javax.swing.JPanel();
+        jLabel4 = new javax.swing.JLabel();
+        jSeparator1 = new javax.swing.JSeparator();
+        jLabel22 = new javax.swing.JLabel();
+        jCheckBox2 = new javax.swing.JCheckBox();
+        jLabel23 = new javax.swing.JLabel();
+        jComboBox2 = new javax.swing.JComboBox<>();
+        jToggleButton1 = new javax.swing.JToggleButton();
+        jPanel4 = new javax.swing.JPanel();
+        jLabel1 = new javax.swing.JLabel();
+        visualizationLabel = new javax.swing.JLabel();
+        transparencySlider = new javax.swing.JSlider();
+        transparencyButton = new javax.swing.JButton();
+        frontButton = new javax.swing.JButton();
+        profileButton = new javax.swing.JButton();
+        featurePointsLabel = new javax.swing.JLabel();
+        thersholdFTF = new javax.swing.JFormattedTextField();
+        thersholdUpButton = new javax.swing.JButton();
+        thresholdDownButton = new javax.swing.JButton();
+        jSeparator3 = new javax.swing.JSeparator();
+        jPanel6 = new javax.swing.JPanel();
+        jLabel9 = new javax.swing.JLabel();
+        jPanel5 = new javax.swing.JPanel();
+        jLabel12 = new javax.swing.JLabel();
+        jLabel13 = new javax.swing.JLabel();
+        jLabel10 = new javax.swing.JLabel();
+        jLabel15 = new javax.swing.JLabel();
+        jLabel11 = new javax.swing.JLabel();
+        jLabel14 = new javax.swing.JLabel();
+        jPanel3 = new javax.swing.JPanel();
+        jLabel16 = new javax.swing.JLabel();
+        jLabel17 = new javax.swing.JLabel();
+        jLabel18 = new javax.swing.JLabel();
+        jLabel19 = new javax.swing.JLabel();
+        jLabel20 = new javax.swing.JLabel();
+        jLabel21 = new javax.swing.JLabel();
+        jSeparator6 = new javax.swing.JSeparator();
+
+        setMinimumSize(new java.awt.Dimension(600, 600));
+        setPreferredSize(new java.awt.Dimension(600, 600));
+
+        transformationPanel.setPreferredSize(new java.awt.Dimension(400, 400));
+
+        translationPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.translationPanel.border.title"))); // NOI18N
+
+        translationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/restart-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(translationButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.translationButton.text")); // NOI18N
+        translationButton.setToolTipText(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.translationButton.toolTipText")); // NOI18N
+        translationButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        translationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        translationButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
+        translationButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                translationButtonMousePressed(evt);
+            }
+        });
+
+        rightTranslationXButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/arrow-right-s-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(rightTranslationXButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.rightTranslationXButton.text")); // NOI18N
+        rightTranslationXButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        rightTranslationXButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        rightTranslationXButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
+        rightTranslationXButton.setMaximumSize(new java.awt.Dimension(24, 24));
+        rightTranslationXButton.setMinimumSize(new java.awt.Dimension(24, 24));
+        rightTranslationXButton.setPreferredSize(new java.awt.Dimension(24, 24));
+        rightTranslationXButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                rightTranslationXButtonMousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                rightTranslationXButtonMouseReleased(evt);
+            }
+        });
+
+        translationXFTF.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter()));
+        translationXFTF.setToolTipText(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.translationXFTF.toolTipText")); // NOI18N
+        translationXFTF.setCursor(new java.awt.Cursor(java.awt.Cursor.TEXT_CURSOR));
+
+        leftTranslationYButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/arrow-left-s-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(leftTranslationYButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.leftTranslationYButton.text")); // NOI18N
+        leftTranslationYButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        leftTranslationYButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        leftTranslationYButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
+        leftTranslationYButton.setPreferredSize(new java.awt.Dimension(24, 24));
+        leftTranslationYButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                leftTranslationYButtonMousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                leftTranslationYButtonMouseReleased(evt);
+            }
+        });
+
+        translationYFTF.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter()));
+
+        rightTranslationYButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/arrow-right-s-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(rightTranslationYButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.rightTranslationYButton.text")); // NOI18N
+        rightTranslationYButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        rightTranslationYButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        rightTranslationYButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
+        rightTranslationYButton.setPreferredSize(new java.awt.Dimension(24, 24));
+        rightTranslationYButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                rightTranslationYButtonMousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                rightTranslationYButtonMouseReleased(evt);
+            }
+        });
+
+        translXLabel.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(translXLabel, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.translXLabel.text")); // NOI18N
+
+        translationZFTF.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter()));
+
+        translZLabel.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(translZLabel, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.translZLabel.text")); // NOI18N
+
+        translYLabel.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(translYLabel, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.translYLabel.text")); // NOI18N
+
+        rightTranslationZButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/arrow-right-s-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(rightTranslationZButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.rightTranslationZButton.text")); // NOI18N
+        rightTranslationZButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        rightTranslationZButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        rightTranslationZButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
+        rightTranslationZButton.setPreferredSize(new java.awt.Dimension(24, 24));
+        rightTranslationZButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                rightTranslationZButtonMousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                rightTranslationZButtonMouseReleased(evt);
+            }
+        });
+
+        leftTranslationXButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/arrow-left-s-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(leftTranslationXButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.leftTranslationXButton.text")); // NOI18N
+        leftTranslationXButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        leftTranslationXButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        leftTranslationXButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
+        leftTranslationXButton.setMaximumSize(new java.awt.Dimension(24, 24));
+        leftTranslationXButton.setMinimumSize(new java.awt.Dimension(24, 24));
+        leftTranslationXButton.setPreferredSize(new java.awt.Dimension(24, 24));
+        leftTranslationXButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                leftTranslationXButtonMousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                leftTranslationXButtonMouseReleased(evt);
+            }
+        });
+
+        leftTranslationZButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/arrow-left-s-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(leftTranslationZButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.leftTranslationZButton.text")); // NOI18N
+        leftTranslationZButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        leftTranslationZButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        leftTranslationZButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
+        leftTranslationZButton.setPreferredSize(new java.awt.Dimension(24, 24));
+        leftTranslationZButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                leftTranslationZButtonMousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                leftTranslationZButtonMouseReleased(evt);
+            }
+        });
+
+        javax.swing.GroupLayout translationPanelLayout = new javax.swing.GroupLayout(translationPanel);
+        translationPanel.setLayout(translationPanelLayout);
+        translationPanelLayout.setHorizontalGroup(
+            translationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(translationPanelLayout.createSequentialGroup()
+                .addGroup(translationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
+                    .addGroup(translationPanelLayout.createSequentialGroup()
+                        .addGap(31, 31, 31)
+                        .addComponent(translXLabel))
+                    .addGroup(translationPanelLayout.createSequentialGroup()
+                        .addGap(2, 2, 2)
+                        .addComponent(translationButton)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                        .addGroup(translationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                            .addComponent(translationXFTF, javax.swing.GroupLayout.PREFERRED_SIZE, 54, javax.swing.GroupLayout.PREFERRED_SIZE)
+                            .addGroup(translationPanelLayout.createSequentialGroup()
+                                .addComponent(leftTranslationXButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                                .addComponent(rightTranslationXButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))))
+                .addGroup(translationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(translationPanelLayout.createSequentialGroup()
+                        .addGap(7, 7, 7)
+                        .addGroup(translationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                            .addGroup(translationPanelLayout.createSequentialGroup()
+                                .addComponent(leftTranslationYButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                                .addComponent(rightTranslationYButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                            .addComponent(translationYFTF, javax.swing.GroupLayout.PREFERRED_SIZE, 54, javax.swing.GroupLayout.PREFERRED_SIZE)))
+                    .addGroup(translationPanelLayout.createSequentialGroup()
+                        .addGap(15, 15, 15)
+                        .addComponent(translYLabel)))
+                .addGap(5, 5, 5)
+                .addGroup(translationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(translationPanelLayout.createSequentialGroup()
+                        .addGap(1, 1, 1)
+                        .addGroup(translationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                            .addGroup(translationPanelLayout.createSequentialGroup()
+                                .addComponent(leftTranslationZButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                                .addComponent(rightTranslationZButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                            .addComponent(translationZFTF, javax.swing.GroupLayout.PREFERRED_SIZE, 54, javax.swing.GroupLayout.PREFERRED_SIZE))
+                        .addGap(2, 2, 2))
+                    .addComponent(translZLabel, javax.swing.GroupLayout.Alignment.TRAILING))
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+        translationPanelLayout.setVerticalGroup(
+            translationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(translationPanelLayout.createSequentialGroup()
+                .addGap(7, 7, 7)
+                .addGroup(translationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(translXLabel)
+                    .addComponent(translYLabel)
+                    .addComponent(translZLabel))
+                .addGap(9, 9, 9)
+                .addGroup(translationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(translationPanelLayout.createSequentialGroup()
+                        .addGroup(translationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+                            .addComponent(rightTranslationXButton, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                            .addComponent(leftTranslationXButton, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addGroup(translationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                            .addComponent(translationXFTF, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, translationPanelLayout.createSequentialGroup()
+                                .addComponent(translationButton)
+                                .addGap(6, 6, 6))))
+                    .addGroup(translationPanelLayout.createSequentialGroup()
+                        .addGroup(translationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+                            .addComponent(rightTranslationYButton, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                            .addComponent(leftTranslationYButton, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(translationYFTF, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                    .addGroup(translationPanelLayout.createSequentialGroup()
+                        .addGroup(translationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+                            .addGroup(translationPanelLayout.createSequentialGroup()
+                                .addComponent(rightTranslationZButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                .addGap(6, 6, 6))
+                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, translationPanelLayout.createSequentialGroup()
+                                .addComponent(leftTranslationZButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)))
+                        .addComponent(translationZFTF, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
+                .addGap(10, 10, 10))
+        );
+
+        rotationPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.rotationPanel.border.title"))); // NOI18N
+
+        leftRotationYButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/arrow-left-s-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(leftRotationYButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.leftRotationYButton.text")); // NOI18N
+        leftRotationYButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        leftRotationYButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        leftRotationYButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
+        leftRotationYButton.setMaximumSize(new java.awt.Dimension(24, 24));
+        leftRotationYButton.setMinimumSize(new java.awt.Dimension(24, 24));
+        leftRotationYButton.setPreferredSize(new java.awt.Dimension(24, 24));
+        leftRotationYButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                leftRotationYButtonMousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                leftRotationYButtonMouseReleased(evt);
+            }
+        });
+
+        leftRotationXButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/arrow-left-s-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(leftRotationXButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.leftRotationXButton.text")); // NOI18N
+        leftRotationXButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        leftRotationXButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        leftRotationXButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
+        leftRotationXButton.setPreferredSize(new java.awt.Dimension(24, 24));
+        leftRotationXButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                leftRotationXButtonMousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                leftRotationXButtonMouseReleased(evt);
+            }
+        });
+
+        rotatZLabel.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(rotatZLabel, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.rotatZLabel.text")); // NOI18N
+
+        rotatYLabel.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(rotatYLabel, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.rotatYLabel.text")); // NOI18N
+
+        rotatXLabel.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(rotatXLabel, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.rotatXLabel.text")); // NOI18N
+
+        rotationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/restart-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(rotationButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.rotationButton.text")); // NOI18N
+        rotationButton.setToolTipText(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.rotationButton.toolTipText")); // NOI18N
+        rotationButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        rotationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        rotationButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
+        rotationButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                rotationButtonMousePressed(evt);
+            }
+        });
+
+        rotationZFTF.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter()));
+
+        rotationYFTF.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter()));
+
+        rightRotationZButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/arrow-right-s-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(rightRotationZButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.rightRotationZButton.text")); // NOI18N
+        rightRotationZButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        rightRotationZButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        rightRotationZButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
+        rightRotationZButton.setMaximumSize(new java.awt.Dimension(24, 24));
+        rightRotationZButton.setMinimumSize(new java.awt.Dimension(24, 24));
+        rightRotationZButton.setPreferredSize(new java.awt.Dimension(24, 24));
+        rightRotationZButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                rightRotationZButtonMousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                rightRotationZButtonMouseReleased(evt);
+            }
+        });
+
+        rightRotationYButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/arrow-right-s-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(rightRotationYButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.rightRotationYButton.text")); // NOI18N
+        rightRotationYButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        rightRotationYButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        rightRotationYButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
+        rightRotationYButton.setMaximumSize(new java.awt.Dimension(24, 24));
+        rightRotationYButton.setMinimumSize(new java.awt.Dimension(24, 24));
+        rightRotationYButton.setPreferredSize(new java.awt.Dimension(24, 24));
+        rightRotationYButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                rightRotationYButtonMousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                rightRotationYButtonMouseReleased(evt);
+            }
+        });
+
+        leftRotationZButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/arrow-left-s-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(leftRotationZButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.leftRotationZButton.text")); // NOI18N
+        leftRotationZButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        leftRotationZButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        leftRotationZButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
+        leftRotationZButton.setMaximumSize(new java.awt.Dimension(24, 24));
+        leftRotationZButton.setMinimumSize(new java.awt.Dimension(24, 24));
+        leftRotationZButton.setPreferredSize(new java.awt.Dimension(24, 24));
+        leftRotationZButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                leftRotationZButtonMousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                leftRotationZButtonMouseReleased(evt);
+            }
+        });
+
+        rightRotationXButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/arrow-right-s-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(rightRotationXButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.rightRotationXButton.text")); // NOI18N
+        rightRotationXButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        rightRotationXButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        rightRotationXButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
+        rightRotationXButton.setMaximumSize(new java.awt.Dimension(24, 24));
+        rightRotationXButton.setMinimumSize(new java.awt.Dimension(24, 24));
+        rightRotationXButton.setPreferredSize(new java.awt.Dimension(24, 24));
+        rightRotationXButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                rightRotationXButtonMousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                rightRotationXButtonMouseReleased(evt);
+            }
+        });
+
+        rotationXFTF.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter()));
+        rotationXFTF.setToolTipText(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.rotationXFTF.toolTipText")); // NOI18N
+
+        javax.swing.GroupLayout rotationPanelLayout = new javax.swing.GroupLayout(rotationPanel);
+        rotationPanel.setLayout(rotationPanelLayout);
+        rotationPanelLayout.setHorizontalGroup(
+            rotationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(rotationPanelLayout.createSequentialGroup()
+                .addGap(2, 2, 2)
+                .addGroup(rotationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(rotationPanelLayout.createSequentialGroup()
+                        .addComponent(rotationButton)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addGroup(rotationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                            .addComponent(rotationXFTF, javax.swing.GroupLayout.PREFERRED_SIZE, 54, javax.swing.GroupLayout.PREFERRED_SIZE)
+                            .addGroup(rotationPanelLayout.createSequentialGroup()
+                                .addComponent(leftRotationXButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                                .addComponent(rightRotationXButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
+                    .addGroup(rotationPanelLayout.createSequentialGroup()
+                        .addGap(55, 55, 55)
+                        .addComponent(rotatXLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)))
+                .addGroup(rotationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(rotationPanelLayout.createSequentialGroup()
+                        .addGap(6, 6, 6)
+                        .addGroup(rotationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+                            .addGroup(rotationPanelLayout.createSequentialGroup()
+                                .addComponent(leftRotationYButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                                .addComponent(rightRotationYButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                            .addComponent(rotationYFTF, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 54, javax.swing.GroupLayout.PREFERRED_SIZE)))
+                    .addGroup(rotationPanelLayout.createSequentialGroup()
+                        .addGap(29, 29, 29)
+                        .addComponent(rotatYLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 17, javax.swing.GroupLayout.PREFERRED_SIZE)))
+                .addGroup(rotationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(rotationPanelLayout.createSequentialGroup()
+                        .addGap(6, 6, 6)
+                        .addGroup(rotationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
+                            .addComponent(rotationZFTF, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 54, javax.swing.GroupLayout.PREFERRED_SIZE)
+                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, rotationPanelLayout.createSequentialGroup()
+                                .addComponent(leftRotationZButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                                .addComponent(rightRotationZButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
+                    .addGroup(rotationPanelLayout.createSequentialGroup()
+                        .addGap(28, 28, 28)
+                        .addComponent(rotatZLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE)))
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+        rotationPanelLayout.setVerticalGroup(
+            rotationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(rotationPanelLayout.createSequentialGroup()
+                .addGap(7, 7, 7)
+                .addGroup(rotationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(rotationPanelLayout.createSequentialGroup()
+                        .addGap(1, 1, 1)
+                        .addGroup(rotationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                            .addComponent(rotatZLabel, javax.swing.GroupLayout.Alignment.TRAILING)
+                            .addComponent(rotatXLabel, javax.swing.GroupLayout.Alignment.TRAILING)))
+                    .addComponent(rotatYLabel))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(rotationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+                    .addGroup(rotationPanelLayout.createSequentialGroup()
+                        .addGroup(rotationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                            .addComponent(leftRotationZButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                            .addComponent(rightRotationZButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(rotationZFTF, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                    .addGroup(rotationPanelLayout.createSequentialGroup()
+                        .addGroup(rotationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                            .addComponent(leftRotationXButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                            .addComponent(rightRotationXButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addGroup(rotationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                            .addGroup(rotationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                                .addComponent(rotationXFTF, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                .addComponent(rotationYFTF, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, rotationPanelLayout.createSequentialGroup()
+                                .addComponent(rotationButton)
+                                .addGap(5, 5, 5))))
+                    .addGroup(rotationPanelLayout.createSequentialGroup()
+                        .addGroup(rotationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                            .addComponent(rightRotationYButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                            .addComponent(leftRotationYButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                        .addGap(41, 41, 41)))
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+
+        scalePanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.scalePanel.border.title"))); // NOI18N
+
+        scalePlusButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/add-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(scalePlusButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.scalePlusButton.text")); // NOI18N
+        scalePlusButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        scalePlusButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        scalePlusButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
+        scalePlusButton.setMaximumSize(new java.awt.Dimension(24, 24));
+        scalePlusButton.setMinimumSize(new java.awt.Dimension(24, 24));
+        scalePlusButton.setPreferredSize(new java.awt.Dimension(24, 24));
+        scalePlusButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                scalePlusButtonMousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                scalePlusButtonMouseReleased(evt);
+            }
+        });
+
+        scaleFTF.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter()));
+        scaleFTF.setToolTipText(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.scaleFTF.toolTipText")); // NOI18N
+        scaleFTF.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                scaleFTFActionPerformed(evt);
+            }
+        });
+
+        scaleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/restart-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(scaleButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.scaleButton.text")); // NOI18N
+        scaleButton.setToolTipText(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.scaleButton.toolTipText")); // NOI18N
+        scaleButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        scaleButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        scaleButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
+        scaleButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                scaleButtonMousePressed(evt);
+            }
+        });
+
+        scaleMinusButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/subtract-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(scaleMinusButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.scaleMinusButton.text")); // NOI18N
+        scaleMinusButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        scaleMinusButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        scaleMinusButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
+        scaleMinusButton.setMaximumSize(new java.awt.Dimension(24, 24));
+        scaleMinusButton.setMinimumSize(new java.awt.Dimension(24, 24));
+        scaleMinusButton.setPreferredSize(new java.awt.Dimension(24, 24));
+        scaleMinusButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                scaleMinusButtonMousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                scaleMinusButtonMouseReleased(evt);
+            }
+        });
+
+        javax.swing.GroupLayout scalePanelLayout = new javax.swing.GroupLayout(scalePanel);
+        scalePanel.setLayout(scalePanelLayout);
+        scalePanelLayout.setHorizontalGroup(
+            scalePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(scalePanelLayout.createSequentialGroup()
+                .addGap(32, 32, 32)
+                .addComponent(scalePlusButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(scaleMinusButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addGap(0, 0, Short.MAX_VALUE))
+            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, scalePanelLayout.createSequentialGroup()
+                .addGap(2, 2, 2)
+                .addComponent(scaleButton)
+                .addGap(7, 7, 7)
+                .addComponent(scaleFTF, javax.swing.GroupLayout.PREFERRED_SIZE, 54, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+        scalePanelLayout.setVerticalGroup(
+            scalePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, scalePanelLayout.createSequentialGroup()
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                .addGroup(scalePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(scalePlusButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addComponent(scaleMinusButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(scalePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(scaleFTF, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, scalePanelLayout.createSequentialGroup()
+                        .addComponent(scaleButton)
+                        .addGap(5, 5, 5)))
+                .addContainerGap())
+        );
+
+        resetAllButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/refresh-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(resetAllButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.resetAllButton.text")); // NOI18N
+        resetAllButton.setToolTipText(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.resetAllButton.toolTipText")); // NOI18N
+        resetAllButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        resetAllButton.setFocusPainted(false);
+        resetAllButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                resetAllButtonMousePressed(evt);
+            }
+        });
+
+        javax.swing.GroupLayout shiftPanelLayout = new javax.swing.GroupLayout(shiftPanel);
+        shiftPanel.setLayout(shiftPanelLayout);
+        shiftPanelLayout.setHorizontalGroup(
+            shiftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGap(0, 21, Short.MAX_VALUE)
+        );
+        shiftPanelLayout.setVerticalGroup(
+            shiftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGap(0, 84, Short.MAX_VALUE)
+        );
+
+        jSeparator10.setOrientation(javax.swing.SwingConstants.VERTICAL);
+
+        org.openide.awt.Mnemonics.setLocalizedText(applyButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.applyButton.text")); // NOI18N
+        applyButton.setToolTipText(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.applyButton.toolTipText")); // NOI18N
+        applyButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        applyButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
+        applyButton.setFocusPainted(false);
+        applyButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                applyButtonMousePressed(evt);
+            }
+        });
+
+        shiftLabel.setFont(new java.awt.Font("Ubuntu", 1, 15)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(shiftLabel, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.shiftLabel.text")); // NOI18N
+        shiftLabel.setToolTipText(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.shiftLabel.toolTipText")); // NOI18N
+
+        precisionGroup.add(lowShiftRB);
+        org.openide.awt.Mnemonics.setLocalizedText(lowShiftRB, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.lowShiftRB.text")); // NOI18N
+        lowShiftRB.setToolTipText(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.lowShiftRB.toolTipText")); // NOI18N
+        lowShiftRB.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                lowShiftRBActionPerformed(evt);
+            }
+        });
+
+        precisionGroup.add(highShiftRB);
+        org.openide.awt.Mnemonics.setLocalizedText(highShiftRB, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.highShiftRB.text")); // NOI18N
+        highShiftRB.setToolTipText(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.highShiftRB.toolTipText")); // NOI18N
+        highShiftRB.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                highShiftRBActionPerformed(evt);
+            }
+        });
+
+        jLabel2.setFont(new java.awt.Font("Ubuntu", 1, 15)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel2.text")); // NOI18N
+
+        javax.swing.GroupLayout transformationPanelLayout = new javax.swing.GroupLayout(transformationPanel);
+        transformationPanel.setLayout(transformationPanelLayout);
+        transformationPanelLayout.setHorizontalGroup(
+            transformationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(transformationPanelLayout.createSequentialGroup()
+                .addGroup(transformationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(transformationPanelLayout.createSequentialGroup()
+                        .addComponent(jSeparator5)
+                        .addGap(474, 474, 474))
+                    .addGroup(transformationPanelLayout.createSequentialGroup()
+                        .addGroup(transformationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+                            .addComponent(jSeparator4, javax.swing.GroupLayout.PREFERRED_SIZE, 589, javax.swing.GroupLayout.PREFERRED_SIZE)
+                            .addGroup(transformationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                                .addGroup(transformationPanelLayout.createSequentialGroup()
+                                    .addGap(580, 580, 580)
+                                    .addComponent(shiftPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                                .addGroup(transformationPanelLayout.createSequentialGroup()
+                                    .addGap(349, 349, 349)
+                                    .addComponent(jSeparator10, javax.swing.GroupLayout.PREFERRED_SIZE, 15, javax.swing.GroupLayout.PREFERRED_SIZE))
+                                .addGroup(transformationPanelLayout.createSequentialGroup()
+                                    .addContainerGap()
+                                    .addGroup(transformationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                                        .addComponent(translationPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 227, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                        .addGroup(transformationPanelLayout.createSequentialGroup()
+                                            .addGap(12, 12, 12)
+                                            .addComponent(shiftLabel)
+                                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                                            .addComponent(lowShiftRB)
+                                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                                            .addComponent(highShiftRB)))
+                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                                    .addGroup(transformationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                                        .addGroup(transformationPanelLayout.createSequentialGroup()
+                                            .addComponent(resetAllButton, javax.swing.GroupLayout.PREFERRED_SIZE, 128, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                                            .addComponent(applyButton, javax.swing.GroupLayout.PREFERRED_SIZE, 128, javax.swing.GroupLayout.PREFERRED_SIZE))
+                                        .addGroup(transformationPanelLayout.createSequentialGroup()
+                                            .addComponent(rotationPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 224, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                                            .addComponent(scalePanel, javax.swing.GroupLayout.PREFERRED_SIZE, 102, javax.swing.GroupLayout.PREFERRED_SIZE))))
+                                .addGroup(transformationPanelLayout.createSequentialGroup()
+                                    .addContainerGap()
+                                    .addComponent(jLabel2))))
+                        .addGap(0, 91, Short.MAX_VALUE)))
+                .addContainerGap())
+        );
+        transformationPanelLayout.setVerticalGroup(
+            transformationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(transformationPanelLayout.createSequentialGroup()
+                .addComponent(jSeparator4, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addGap(2, 2, 2)
+                .addComponent(jLabel2)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(transformationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+                    .addGroup(transformationPanelLayout.createSequentialGroup()
+                        .addComponent(scalePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                        .addGap(1, 1, 1))
+                    .addComponent(translationPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                    .addComponent(rotationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(transformationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(applyButton, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addGroup(transformationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                        .addComponent(shiftLabel)
+                        .addComponent(lowShiftRB)
+                        .addComponent(highShiftRB)
+                        .addComponent(resetAllButton)))
+                .addGap(39, 39, 39)
+                .addComponent(jSeparator10, javax.swing.GroupLayout.PREFERRED_SIZE, 62, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addGap(25, 25, 25)
+                .addComponent(shiftPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                .addComponent(jSeparator5, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE))
+        );
+
+        jPanel1.setMaximumSize(new java.awt.Dimension(600, 32767));
+
+        jLabel3.setFont(new java.awt.Font("Ubuntu", 1, 15)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel3.text")); // NOI18N
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel7, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel7.text")); // NOI18N
+
+        jCheckBox1.setSelected(true);
+        org.openide.awt.Mnemonics.setLocalizedText(jCheckBox1, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jCheckBox1.text")); // NOI18N
+        jCheckBox1.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                jCheckBox1ActionPerformed(evt);
+            }
+        });
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel5.text")); // NOI18N
+
+        jFormattedTextField1.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter()));
+        jFormattedTextField1.setText(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jFormattedTextField1.text")); // NOI18N
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel6, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel6.text")); // NOI18N
+
+        jFormattedTextField2.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(java.text.NumberFormat.getIntegerInstance())));
+        jFormattedTextField2.setText(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jFormattedTextField2.text")); // NOI18N
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel8, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel8.text")); // NOI18N
+
+        jComboBox1.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "None", "Random 200" }));
+
+        jButton1.setFont(new java.awt.Font("Ubuntu", 1, 15)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jButton1.text")); // NOI18N
+        jButton1.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                jButton1ActionPerformed(evt);
+            }
+        });
+
+        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
+        jPanel1.setLayout(jPanel1Layout);
+        jPanel1Layout.setHorizontalGroup(
+            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(jPanel1Layout.createSequentialGroup()
+                .addContainerGap()
+                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(jPanel1Layout.createSequentialGroup()
+                        .addComponent(jLabel3)
+                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+                    .addGroup(jPanel1Layout.createSequentialGroup()
+                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                            .addGroup(jPanel1Layout.createSequentialGroup()
+                                .addComponent(jLabel8)
+                                .addGap(2, 2, 2)
+                                .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, 166, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+                            .addGroup(jPanel1Layout.createSequentialGroup()
+                                .addComponent(jLabel7)
+                                .addGap(6, 6, 6)
+                                .addComponent(jCheckBox1)
+                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                                .addComponent(jLabel5)
+                                .addGap(4, 4, 4)
+                                .addComponent(jFormattedTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 49, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                .addGap(57, 57, 57)))
+                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                            .addComponent(jButton1, javax.swing.GroupLayout.Alignment.TRAILING)
+                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
+                                .addComponent(jLabel6)
+                                .addGap(3, 3, 3)
+                                .addComponent(jFormattedTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, 53, javax.swing.GroupLayout.PREFERRED_SIZE)))
+                        .addGap(54, 54, 54))))
+        );
+        jPanel1Layout.setVerticalGroup(
+            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(jPanel1Layout.createSequentialGroup()
+                .addContainerGap()
+                .addComponent(jLabel3)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(jLabel7)
+                    .addComponent(jCheckBox1)
+                    .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                        .addComponent(jFormattedTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE)
+                        .addComponent(jLabel5)
+                        .addComponent(jLabel6)
+                        .addComponent(jFormattedTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(jButton1)
+                    .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                        .addComponent(jLabel8)
+                        .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE)))
+                .addContainerGap(13, Short.MAX_VALUE))
+        );
+
+        jPanel2.setPreferredSize(new java.awt.Dimension(600, 74));
+
+        jLabel4.setFont(new java.awt.Font("Ubuntu", 1, 15)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel4.text")); // NOI18N
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel22, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel22.text")); // NOI18N
+
+        org.openide.awt.Mnemonics.setLocalizedText(jCheckBox2, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jCheckBox2.text")); // NOI18N
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel23, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel23.text")); // NOI18N
+
+        jComboBox2.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Point to point", "Point to triangle" }));
+        jComboBox2.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                jComboBox2ActionPerformed(evt);
+            }
+        });
+
+        jToggleButton1.setFont(new java.awt.Font("Ubuntu", 1, 15)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(jToggleButton1, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jToggleButton1.text")); // NOI18N
+        jToggleButton1.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                jToggleButton1ActionPerformed(evt);
+            }
+        });
+
+        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
+        jPanel2.setLayout(jPanel2Layout);
+        jPanel2Layout.setHorizontalGroup(
+            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(jPanel2Layout.createSequentialGroup()
+                .addContainerGap()
+                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(jLabel4)
+                    .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 600, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addGroup(jPanel2Layout.createSequentialGroup()
+                        .addComponent(jLabel22)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(jCheckBox2)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(jLabel23)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(jComboBox2, javax.swing.GroupLayout.PREFERRED_SIZE, 145, javax.swing.GroupLayout.PREFERRED_SIZE)
+                        .addGap(40, 40, 40)
+                        .addComponent(jToggleButton1)))
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+        jPanel2Layout.setVerticalGroup(
+            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(jPanel2Layout.createSequentialGroup()
+                .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addGap(2, 2, 2)
+                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+                    .addGroup(jPanel2Layout.createSequentialGroup()
+                        .addComponent(jLabel4)
+                        .addGap(12, 12, 12)
+                        .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                            .addComponent(jCheckBox2)
+                            .addComponent(jLabel22)))
+                    .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                        .addComponent(jLabel23)
+                        .addComponent(jComboBox2, javax.swing.GroupLayout.PREFERRED_SIZE, 29, javax.swing.GroupLayout.PREFERRED_SIZE)
+                        .addComponent(jToggleButton1)))
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+
+        jLabel1.setFont(new java.awt.Font("Ubuntu", 1, 15)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel1.text")); // NOI18N
+
+        visualizationLabel.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(visualizationLabel, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.visualizationLabel.text")); // NOI18N
+
+        transparencySlider.setMajorTickSpacing(5);
+        transparencySlider.setMaximum(20);
+        transparencySlider.setMinorTickSpacing(5);
+        transparencySlider.setPaintTicks(true);
+        transparencySlider.setToolTipText(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.transparencySlider.toolTipText")); // NOI18N
+        transparencySlider.setValue(10);
+        transparencySlider.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
+        transparencySlider.addChangeListener(new javax.swing.event.ChangeListener() {
+            public void stateChanged(javax.swing.event.ChangeEvent evt) {
+                transparencySliderStateChanged(evt);
+            }
+        });
+
+        transparencyButton.setFont(new java.awt.Font("Ubuntu", 0, 14)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(transparencyButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.transparencyButton.text")); // NOI18N
+        transparencyButton.setToolTipText(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.transparencyButton.toolTipText")); // NOI18N
+        transparencyButton.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder()));
+        transparencyButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        transparencyButton.setPreferredSize(new java.awt.Dimension(100, 19));
+        transparencyButton.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                transparencyButtonActionPerformed(evt);
+            }
+        });
+
+        org.openide.awt.Mnemonics.setLocalizedText(frontButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.frontButton.text")); // NOI18N
+        frontButton.setToolTipText(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.frontButton.toolTipText")); // NOI18N
+        frontButton.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder()));
+        frontButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        frontButton.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                frontButtonActionPerformed(evt);
+            }
+        });
+
+        org.openide.awt.Mnemonics.setLocalizedText(profileButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.profileButton.text")); // NOI18N
+        profileButton.setToolTipText(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.profileButton.toolTipText")); // NOI18N
+        profileButton.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder()));
+        profileButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+
+        featurePointsLabel.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(featurePointsLabel, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.featurePointsLabel.text")); // NOI18N
+
+        thersholdFTF.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter()));
+
+        thersholdUpButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/add-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(thersholdUpButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.thersholdUpButton.text")); // NOI18N
+        thersholdUpButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        thersholdUpButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        thersholdUpButton.setMaximumSize(new java.awt.Dimension(24, 24));
+        thersholdUpButton.setMinimumSize(new java.awt.Dimension(24, 24));
+        thersholdUpButton.setPreferredSize(new java.awt.Dimension(24, 24));
+        thersholdUpButton.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                thersholdUpButtonActionPerformed(evt);
+            }
+        });
+
+        thresholdDownButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/subtract-line.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(thresholdDownButton, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.thresholdDownButton.text")); // NOI18N
+        thresholdDownButton.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+        thresholdDownButton.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        thresholdDownButton.setMaximumSize(new java.awt.Dimension(24, 24));
+        thresholdDownButton.setMinimumSize(new java.awt.Dimension(24, 24));
+        thresholdDownButton.setPreferredSize(new java.awt.Dimension(24, 24));
+        thresholdDownButton.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                thresholdDownButtonActionPerformed(evt);
+            }
+        });
+
+        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
+        jPanel4.setLayout(jPanel4Layout);
+        jPanel4Layout.setHorizontalGroup(
+            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(jPanel4Layout.createSequentialGroup()
+                .addContainerGap()
+                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(jSeparator3, javax.swing.GroupLayout.Alignment.TRAILING)
+                    .addGroup(jPanel4Layout.createSequentialGroup()
+                        .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
+                            .addGroup(jPanel4Layout.createSequentialGroup()
+                                .addComponent(featurePointsLabel)
+                                .addGap(4, 4, 4)
+                                .addComponent(thersholdFTF, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                                .addComponent(thersholdUpButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                                .addComponent(thresholdDownButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                                .addComponent(frontButton, javax.swing.GroupLayout.PREFERRED_SIZE, 85, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                                .addComponent(profileButton, javax.swing.GroupLayout.PREFERRED_SIZE, 85, javax.swing.GroupLayout.PREFERRED_SIZE))
+                            .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                                .addComponent(jLabel1)
+                                .addGroup(jPanel4Layout.createSequentialGroup()
+                                    .addComponent(visualizationLabel)
+                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                                    .addComponent(transparencySlider, javax.swing.GroupLayout.PREFERRED_SIZE, 344, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                                    .addComponent(transparencyButton, javax.swing.GroupLayout.PREFERRED_SIZE, 72, javax.swing.GroupLayout.PREFERRED_SIZE))))
+                        .addGap(26, 34, Short.MAX_VALUE))))
+        );
+        jPanel4Layout.setVerticalGroup(
+            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(jPanel4Layout.createSequentialGroup()
+                .addComponent(jSeparator3, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addGap(2, 2, 2)
+                .addComponent(jLabel1)
+                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(transparencySlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addGroup(jPanel4Layout.createSequentialGroup()
+                        .addGap(18, 18, 18)
+                        .addComponent(visualizationLabel))
+                    .addGroup(jPanel4Layout.createSequentialGroup()
+                        .addGap(18, 18, 18)
+                        .addComponent(transparencyButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+                    .addGroup(jPanel4Layout.createSequentialGroup()
+                        .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                            .addComponent(featurePointsLabel)
+                            .addComponent(thersholdFTF, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE))
+                        .addGap(55, 55, 55))
+                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel4Layout.createSequentialGroup()
+                        .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
+                            .addComponent(profileButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                            .addComponent(frontButton, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                            .addComponent(thersholdUpButton, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                            .addComponent(thresholdDownButton, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+                        .addGap(0, 0, Short.MAX_VALUE))))
+        );
+
+        jLabel9.setFont(new java.awt.Font("Ubuntu", 1, 15)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel9, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel9.text")); // NOI18N
+
+        jPanel5.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jPanel5.border.title"))); // NOI18N
+
+        jLabel12.setFont(new java.awt.Font("Ubuntu", 1, 15)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel12, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel12.text")); // NOI18N
+
+        jLabel13.setFont(new java.awt.Font("Ubuntu", 1, 15)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel13, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel13.text")); // NOI18N
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel10, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel10.text")); // NOI18N
+
+        jLabel15.setFont(new java.awt.Font("Ubuntu", 0, 15)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel15, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel15.text")); // NOI18N
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel11, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel11.text")); // NOI18N
+
+        jLabel14.setFont(new java.awt.Font("Ubuntu", 0, 15)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel14, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel14.text")); // NOI18N
+
+        javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5);
+        jPanel5.setLayout(jPanel5Layout);
+        jPanel5Layout.setHorizontalGroup(
+            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(jPanel5Layout.createSequentialGroup()
+                .addGap(9, 9, 9)
+                .addComponent(jLabel12)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jLabel13, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jLabel10)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jLabel15, javax.swing.GroupLayout.PREFERRED_SIZE, 39, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jLabel11)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jLabel14, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+        jPanel5Layout.setVerticalGroup(
+            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(jPanel5Layout.createSequentialGroup()
+                .addGap(3, 3, 3)
+                .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(jLabel12)
+                    .addComponent(jLabel13)
+                    .addComponent(jLabel10)
+                    .addComponent(jLabel15)
+                    .addComponent(jLabel11)
+                    .addComponent(jLabel14))
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+
+        jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jPanel3.border.title"))); // NOI18N
+
+        jLabel16.setFont(new java.awt.Font("Ubuntu", 1, 15)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel16, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel16.text")); // NOI18N
+
+        jLabel17.setFont(new java.awt.Font("Ubuntu", 1, 15)); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel17, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel17.text")); // NOI18N
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel18, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel18.text")); // NOI18N
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel19, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel19.text")); // NOI18N
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel20, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel20.text")); // NOI18N
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel21, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jLabel21.text")); // NOI18N
+
+        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
+        jPanel3.setLayout(jPanel3Layout);
+        jPanel3Layout.setHorizontalGroup(
+            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(jPanel3Layout.createSequentialGroup()
+                .addGap(9, 9, 9)
+                .addComponent(jLabel16)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jLabel17, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addGap(2, 2, 2)
+                .addComponent(jLabel18)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jLabel19, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jLabel20)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jLabel21, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+        jPanel3Layout.setVerticalGroup(
+            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(jPanel3Layout.createSequentialGroup()
+                .addGap(3, 3, 3)
+                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(jLabel16)
+                    .addComponent(jLabel17)
+                    .addComponent(jLabel18)
+                    .addComponent(jLabel19)
+                    .addComponent(jLabel20)
+                    .addComponent(jLabel21))
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+
+        javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6);
+        jPanel6.setLayout(jPanel6Layout);
+        jPanel6Layout.setHorizontalGroup(
+            jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(jPanel6Layout.createSequentialGroup()
+                .addContainerGap()
+                .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel6Layout.createSequentialGroup()
+                        .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                        .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                        .addGap(22, 22, 22))
+                    .addComponent(jLabel9)
+                    .addComponent(jSeparator6, javax.swing.GroupLayout.PREFERRED_SIZE, 587, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+        jPanel6Layout.setVerticalGroup(
+            jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(jPanel6Layout.createSequentialGroup()
+                .addComponent(jSeparator6, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addGap(2, 2, 2)
+                .addComponent(jLabel9)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addGap(0, 20, Short.MAX_VALUE))
+        );
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addGap(805, 805, 805)
+                .addComponent(jSeparator11))
+            .addGroup(layout.createSequentialGroup()
+                .addGap(791, 791, 791)
+                .addComponent(jSeparator2)
+                .addGap(450, 450, 450))
+            .addGroup(layout.createSequentialGroup()
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(transformationPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 692, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addComponent(jPanel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
+                        .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 624, Short.MAX_VALUE)
+                        .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
+                .addGap(0, 0, Short.MAX_VALUE))
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, 77, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, 135, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(transformationPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 209, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jPanel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addGap(77, 77, 77)
+                .addComponent(jSeparator11, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addGap(221, 221, 221)
+                .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+    }// </editor-fold>//GEN-END:initComponents
+
+       
+    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
+        resetAllButtonMousePressed(null);
+    }//GEN-LAST:event_jButton1ActionPerformed
+
+    private void jCheckBox1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBox1ActionPerformed
+        // TODO add your handling code here:
+    }//GEN-LAST:event_jCheckBox1ActionPerformed
+
+    /**
+     * Resets transparency slider to default position
+     * @param evt 
+     */
+    private void transparencyButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_transparencyButtonActionPerformed
+        transparencySlider.setValue(TRANSPARENCY_RANGE);
+        transparencySlider.repaint();
+        //listener.setTransparency(PostRegistrationListener.TRANSPARENCY_RANGE);
+    }//GEN-LAST:event_transparencyButtonActionPerformed
+
+    private void transparencySliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_transparencySliderStateChanged
+        listener.actionPerformed(
+            new ActionEvent(
+                evt.getSource(),
+                ActionEvent.ACTION_PERFORMED,
+                ACTION_COMMAND_TRANSPARENCY)
+        );
+    }//GEN-LAST:event_transparencySliderStateChanged
+
+    private void thresholdDownButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_thresholdDownButtonActionPerformed
+        double newValue = ((Number)thersholdFTF.getValue()).doubleValue() - 0.1;
+        thersholdFTF.setValue(newValue);
+        thersholdFTF.postActionEvent();
+    }//GEN-LAST:event_thresholdDownButtonActionPerformed
+
+    private void thersholdUpButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_thersholdUpButtonActionPerformed
+        double newValue = ((Number)thersholdFTF.getValue()).doubleValue() + 0.1;
+        thersholdFTF.setValue(newValue);
+        thersholdFTF.postActionEvent();
+    }//GEN-LAST:event_thersholdUpButtonActionPerformed
+
+    private void highShiftRBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_highShiftRBActionPerformed
+        this.moveModifier = HIGH_SHIFT_QUOTIENT;
+    }//GEN-LAST:event_highShiftRBActionPerformed
+
+    private void lowShiftRBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_lowShiftRBActionPerformed
+        this.moveModifier = LOW_SHIFT_QUOTIENT;
+    }//GEN-LAST:event_lowShiftRBActionPerformed
+
+    private void applyButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_applyButtonMousePressed
+        resetAllButtonMousePressed(evt);
+    }//GEN-LAST:event_applyButtonMousePressed
+
+    private void resetAllButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_resetAllButtonMousePressed
+        translationButtonMousePressed(evt);
+        rotationButtonMousePressed(evt);
+        scaleButtonMousePressed(evt);
+    }//GEN-LAST:event_resetAllButtonMousePressed
+
+    private void scaleMinusButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_scaleMinusButtonMouseReleased
+        animator.stopModelAnimation(this);
+    }//GEN-LAST:event_scaleMinusButtonMouseReleased
+
+    private void scaleMinusButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_scaleMinusButtonMousePressed
+        animator.startModelAnimation(Direction.ZOOM_OUT, this);
+    }//GEN-LAST:event_scaleMinusButtonMousePressed
+
+    private void scaleButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_scaleButtonMousePressed
+        scaleFTF.setValue(0.0);
+    }//GEN-LAST:event_scaleButtonMousePressed
+
+    private void scalePlusButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_scalePlusButtonMouseReleased
+        animator.stopModelAnimation(this);
+    }//GEN-LAST:event_scalePlusButtonMouseReleased
+
+    private void scalePlusButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_scalePlusButtonMousePressed
+        animator.startModelAnimation(Direction.ZOOM_IN, this);
+    }//GEN-LAST:event_scalePlusButtonMousePressed
+
+    private void rightRotationXButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightRotationXButtonMouseReleased
+        animator.stopModelAnimation(this);
+    }//GEN-LAST:event_rightRotationXButtonMouseReleased
+
+    private void rightRotationXButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightRotationXButtonMousePressed
+        animator.startModelAnimation(Direction.ROTATE_RIGHT, this);
+    }//GEN-LAST:event_rightRotationXButtonMousePressed
+
+    private void leftRotationZButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftRotationZButtonMouseReleased
+        animator.stopModelAnimation(this);
+    }//GEN-LAST:event_leftRotationZButtonMouseReleased
+
+    private void leftRotationZButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftRotationZButtonMousePressed
+        animator.startModelAnimation(Direction.ROTATE_IN, this);
+    }//GEN-LAST:event_leftRotationZButtonMousePressed
+
+    private void rightRotationYButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightRotationYButtonMouseReleased
+        animator.stopModelAnimation(this);
+    }//GEN-LAST:event_rightRotationYButtonMouseReleased
+
+    private void rightRotationYButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightRotationYButtonMousePressed
+        animator.startModelAnimation(Direction.ROTATE_DOWN, this);
+    }//GEN-LAST:event_rightRotationYButtonMousePressed
+
+    private void rightRotationZButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightRotationZButtonMouseReleased
+        animator.stopModelAnimation(this);
+    }//GEN-LAST:event_rightRotationZButtonMouseReleased
+
+    private void rightRotationZButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightRotationZButtonMousePressed
+        animator.startModelAnimation(Direction.ROTATE_OUT, this);
+    }//GEN-LAST:event_rightRotationZButtonMousePressed
+
+    private void rotationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rotationButtonMousePressed
+        rotationXFTF.setValue(0.0);
+        rotationYFTF.setValue(0.0);
+        rotationZFTF.setValue(0.0);
+    }//GEN-LAST:event_rotationButtonMousePressed
+
+    private void leftRotationXButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftRotationXButtonMouseReleased
+        animator.stopModelAnimation(this);
+    }//GEN-LAST:event_leftRotationXButtonMouseReleased
+
+    private void leftRotationXButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftRotationXButtonMousePressed
+        animator.startModelAnimation(Direction.ROTATE_LEFT, this);
+    }//GEN-LAST:event_leftRotationXButtonMousePressed
+
+    private void leftRotationYButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftRotationYButtonMouseReleased
+        animator.stopModelAnimation(this);
+    }//GEN-LAST:event_leftRotationYButtonMouseReleased
+
+    private void leftRotationYButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftRotationYButtonMousePressed
+        animator.startModelAnimation(Direction.ROTATE_UP, this);
+    }//GEN-LAST:event_leftRotationYButtonMousePressed
+
+    private void leftTranslationZButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftTranslationZButtonMouseReleased
+        animator.stopModelAnimation(this);
+    }//GEN-LAST:event_leftTranslationZButtonMouseReleased
+
+    private void leftTranslationZButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftTranslationZButtonMousePressed
+        animator.startModelAnimation(Direction.TRANSLATE_IN, this);
+    }//GEN-LAST:event_leftTranslationZButtonMousePressed
+
+    private void leftTranslationXButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftTranslationXButtonMouseReleased
+        animator.stopModelAnimation(this);
+    }//GEN-LAST:event_leftTranslationXButtonMouseReleased
+
+    private void leftTranslationXButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftTranslationXButtonMousePressed
+        animator.startModelAnimation(Direction.TRANSLATE_LEFT, this);
+    }//GEN-LAST:event_leftTranslationXButtonMousePressed
+
+    private void rightTranslationZButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightTranslationZButtonMouseReleased
+        animator.stopModelAnimation(this);
+    }//GEN-LAST:event_rightTranslationZButtonMouseReleased
+
+    private void rightTranslationZButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightTranslationZButtonMousePressed
+        animator.startModelAnimation(Direction.TRANSLATE_OUT, this);
+    }//GEN-LAST:event_rightTranslationZButtonMousePressed
+
+    private void rightTranslationYButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightTranslationYButtonMouseReleased
+        animator.stopModelAnimation(this);
+    }//GEN-LAST:event_rightTranslationYButtonMouseReleased
+
+    private void rightTranslationYButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightTranslationYButtonMousePressed
+        animator.startModelAnimation(Direction.TRANSLATE_DOWN, this);
+    }//GEN-LAST:event_rightTranslationYButtonMousePressed
+
+    private void leftTranslationYButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftTranslationYButtonMouseReleased
+        animator.stopModelAnimation(this);
+    }//GEN-LAST:event_leftTranslationYButtonMouseReleased
+
+    private void leftTranslationYButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftTranslationYButtonMousePressed
+        animator.startModelAnimation(Direction.TRANSLATE_UP, this);
+    }//GEN-LAST:event_leftTranslationYButtonMousePressed
+
+    private void rightTranslationXButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightTranslationXButtonMouseReleased
+        animator.stopModelAnimation(this);
+    }//GEN-LAST:event_rightTranslationXButtonMouseReleased
+
+    private void rightTranslationXButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightTranslationXButtonMousePressed
+        animator.startModelAnimation(Direction.TRANSLATE_RIGHT, this);
+    }//GEN-LAST:event_rightTranslationXButtonMousePressed
+
+    private void translationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_translationButtonMousePressed
+        translationXFTF.setValue(0.0);
+        translationYFTF.setValue(0.0);
+        translationZFTF.setValue(0.0);
+    }//GEN-LAST:event_translationButtonMousePressed
+
+    private void scaleFTFActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_scaleFTFActionPerformed
+        // TODO add your handling code here:
+    }//GEN-LAST:event_scaleFTFActionPerformed
+
+    private void jComboBox2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBox2ActionPerformed
+        // TODO add your handling code here:
+    }//GEN-LAST:event_jComboBox2ActionPerformed
+
+    private void jToggleButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleButton1ActionPerformed
+        // TODO add your handling code here:
+    }//GEN-LAST:event_jToggleButton1ActionPerformed
+
+    private void frontButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_frontButtonActionPerformed
+        // TODO add your handling code here:
+    }//GEN-LAST:event_frontButtonActionPerformed
+
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JButton applyButton;
+    private javax.swing.JLabel featurePointsLabel;
+    private javax.swing.JButton frontButton;
+    private javax.swing.JRadioButton highShiftRB;
+    private javax.swing.JButton jButton1;
+    private javax.swing.JCheckBox jCheckBox1;
+    private javax.swing.JCheckBox jCheckBox2;
+    private javax.swing.JComboBox<String> jComboBox1;
+    private javax.swing.JComboBox<String> jComboBox2;
+    private javax.swing.JFormattedTextField jFormattedTextField1;
+    private javax.swing.JFormattedTextField jFormattedTextField2;
+    private javax.swing.JLabel jLabel1;
+    private javax.swing.JLabel jLabel10;
+    private javax.swing.JLabel jLabel11;
+    private javax.swing.JLabel jLabel12;
+    private javax.swing.JLabel jLabel13;
+    private javax.swing.JLabel jLabel14;
+    private javax.swing.JLabel jLabel15;
+    private javax.swing.JLabel jLabel16;
+    private javax.swing.JLabel jLabel17;
+    private javax.swing.JLabel jLabel18;
+    private javax.swing.JLabel jLabel19;
+    private javax.swing.JLabel jLabel2;
+    private javax.swing.JLabel jLabel20;
+    private javax.swing.JLabel jLabel21;
+    private javax.swing.JLabel jLabel22;
+    private javax.swing.JLabel jLabel23;
+    private javax.swing.JLabel jLabel3;
+    private javax.swing.JLabel jLabel4;
+    private javax.swing.JLabel jLabel5;
+    private javax.swing.JLabel jLabel6;
+    private javax.swing.JLabel jLabel7;
+    private javax.swing.JLabel jLabel8;
+    private javax.swing.JLabel jLabel9;
+    private javax.swing.JPanel jPanel1;
+    private javax.swing.JPanel jPanel2;
+    private javax.swing.JPanel jPanel3;
+    private javax.swing.JPanel jPanel4;
+    private javax.swing.JPanel jPanel5;
+    private javax.swing.JPanel jPanel6;
+    private javax.swing.JSeparator jSeparator1;
+    private javax.swing.JSeparator jSeparator10;
+    private javax.swing.JSeparator jSeparator11;
+    private javax.swing.JSeparator jSeparator2;
+    private javax.swing.JSeparator jSeparator3;
+    private javax.swing.JSeparator jSeparator4;
+    private javax.swing.JSeparator jSeparator5;
+    private javax.swing.JSeparator jSeparator6;
+    private javax.swing.JToggleButton jToggleButton1;
+    private javax.swing.JButton leftRotationXButton;
+    private javax.swing.JButton leftRotationYButton;
+    private javax.swing.JButton leftRotationZButton;
+    private javax.swing.JButton leftTranslationXButton;
+    private javax.swing.JButton leftTranslationYButton;
+    private javax.swing.JButton leftTranslationZButton;
+    private javax.swing.JRadioButton lowShiftRB;
+    private javax.swing.ButtonGroup precisionGroup;
+    private javax.swing.ButtonGroup primaryRenderModeGroup;
+    private javax.swing.JButton profileButton;
+    private javax.swing.JButton resetAllButton;
+    private javax.swing.JButton rightRotationXButton;
+    private javax.swing.JButton rightRotationYButton;
+    private javax.swing.JButton rightRotationZButton;
+    private javax.swing.JButton rightTranslationXButton;
+    private javax.swing.JButton rightTranslationYButton;
+    private javax.swing.JButton rightTranslationZButton;
+    private javax.swing.JLabel rotatXLabel;
+    private javax.swing.JLabel rotatYLabel;
+    private javax.swing.JLabel rotatZLabel;
+    private javax.swing.JButton rotationButton;
+    private javax.swing.JPanel rotationPanel;
+    private javax.swing.JFormattedTextField rotationXFTF;
+    private javax.swing.JFormattedTextField rotationYFTF;
+    private javax.swing.JFormattedTextField rotationZFTF;
+    private javax.swing.JButton scaleButton;
+    private javax.swing.JFormattedTextField scaleFTF;
+    private javax.swing.JButton scaleMinusButton;
+    private javax.swing.JPanel scalePanel;
+    private javax.swing.JButton scalePlusButton;
+    private javax.swing.ButtonGroup secondaryRenerModeGroup;
+    private javax.swing.JLabel shiftLabel;
+    private javax.swing.JPanel shiftPanel;
+    private javax.swing.JFormattedTextField thersholdFTF;
+    private javax.swing.JButton thersholdUpButton;
+    private javax.swing.JButton thresholdDownButton;
+    private javax.swing.JPanel transformationPanel;
+    private javax.swing.JLabel translXLabel;
+    private javax.swing.JLabel translYLabel;
+    private javax.swing.JLabel translZLabel;
+    private javax.swing.JButton translationButton;
+    private javax.swing.JPanel translationPanel;
+    private javax.swing.JFormattedTextField translationXFTF;
+    private javax.swing.JFormattedTextField translationYFTF;
+    private javax.swing.JFormattedTextField translationZFTF;
+    private javax.swing.JButton transparencyButton;
+    private javax.swing.JSlider transparencySlider;
+    private javax.swing.JLabel visualizationLabel;
+    // End of variables declaration//GEN-END:variables
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/scene/Camera.java b/GUI/src/main/java/cz/fidentis/analyst/scene/Camera.java
similarity index 99%
rename from GUI/src/main/java/cz/fidentis/analyst/gui/scene/Camera.java
rename to GUI/src/main/java/cz/fidentis/analyst/scene/Camera.java
index 782da9040d3fd8a0fb276aaf4cee0e4f00d917fe..b89b9c1e53c09a011d194af69220e072afe23ebf 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/scene/Camera.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/scene/Camera.java
@@ -1,4 +1,4 @@
-package cz.fidentis.analyst.gui.scene;
+package cz.fidentis.analyst.scene;
 
 import javax.vecmath.Vector3d;
 
diff --git a/GUI/src/main/java/cz/fidentis/analyst/scene/Drawable.java b/GUI/src/main/java/cz/fidentis/analyst/scene/Drawable.java
new file mode 100644
index 0000000000000000000000000000000000000000..c6dbe3210bbd27e30b1630f2280cd12fe1e256e9
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/scene/Drawable.java
@@ -0,0 +1,209 @@
+package cz.fidentis.analyst.scene;
+
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2;
+import java.awt.Color;
+import javax.vecmath.Vector3d;
+
+/**
+ * A drawable object, i.e., an object with drawing state and capable to 
+ * render itself into an OpenGL context.
+ * 
+ * @author Radek Oslejsek
+ * @author Richard Pajersky
+ */
+public abstract class Drawable {
+    
+    private boolean display = true;
+    
+    /* material info */
+    private Color color = Color.LIGHT_GRAY;
+    private float transparency = 1; // 0 = off, 1 = max
+    private Color highlights = new Color(0, 0, 0, 1);
+    
+    /* transformation */
+    private Vector3d translation = new Vector3d(0, 0, 0);
+    private Vector3d rotation = new Vector3d(0, 0, 0);
+    private Vector3d scale = new Vector3d(0, 0, 0);
+    
+    /* rendering mode */
+    /**
+     * Render mode to use, one from {@code GL_FILL}, {@code GL_LINE}, {@code GL_POINT}
+     */
+    private int renderMode = GL2.GL_FILL; // GL_FILL, GL_LINE, or GL_POINT
+    
+    /**
+     * Renders the scene.
+     * @param gl OpenGL context
+     */
+    public void render(GL2 gl) {
+        initRendering(gl);
+        
+        gl.glPushMatrix(); 
+        
+        // rotate
+        gl.glRotated(getRotation().x, 1, 0, 0);
+        gl.glRotated(getRotation().y, 0, 1, 0);
+        gl.glRotated(getRotation().z, 0, 0, 1);
+        // move
+        gl.glTranslated(getTranslation().x, getTranslation().y, getTranslation().z);
+        // scale
+        gl.glScaled(1 + getScale().x, 1 + getScale().y, 1 + getScale().z);
+        
+        renderObject(gl);
+
+        gl.glPopMatrix();
+        
+        finishRendering(gl);
+    }
+    
+    protected void initRendering(GL2 gl) {
+        gl.glShadeModel(GL2.GL_SMOOTH);
+        gl.glPolygonMode(GL.GL_FRONT_AND_BACK, getRenderMode());
+        
+        // set color
+        float[] rgba = {color.getRed() / 255f, color.getGreen() / 255f, 
+            color.getBlue() / 255f , getTransparency()};
+        gl.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_DIFFUSE, rgba, 0);
+
+    }
+    
+    protected abstract void renderObject(GL2 gl);
+
+    protected void finishRendering(GL2 gl) {    
+    }
+        
+    /**
+     * This drawable mesh is included in the rendered scene.
+     */
+    public void show() {
+        display = true;
+    }
+    
+    /**
+     * This drawable mesh is excluded from the rendered scene (skipped).
+     */
+    public void hide() {
+        display = false;
+    }
+    
+    /**
+     * 
+     * @return {@code true} if the object is included (rendered) in the scene.
+     */
+    public boolean isShown() {
+        return display;
+    }
+    
+    /**
+     * Sets color
+     * @param color Color
+     */
+    public void setColor(Color color) {
+        this.color = color;
+    }
+
+    /**
+     * @return {@link Color}
+     */
+    public Color getColor() {
+        return color;
+    }
+    
+    /**
+     * @return Current value of transparency
+     */
+    public float getTransparency() {
+        return transparency;
+    }
+
+    /**
+     * Sets transparency
+     * @param transparency Transparency
+     */
+    public void setTransparency(float transparency) {
+        this.transparency = transparency;
+    }
+    
+    /**
+     * @return {@link Color} of highlights
+     */
+    public Color getHighlights() {
+        return highlights;
+    }
+
+    /**
+     * Sets {@link Color} of highlights
+     * @param highlights 
+     */
+    public void setHighlights(Color highlights) {
+        this.highlights = highlights;
+    }
+    
+    /**
+     * @return Current translation
+     */
+    public Vector3d getTranslation() {
+        return translation;
+    }
+
+    /**
+     * Sets tranlation
+     * @param translation Translation
+     */
+    public void setTranslation(Vector3d translation) {
+        this.translation = translation;
+    }
+
+    /**
+     * @return Current rotation
+     */
+    public Vector3d getRotation() {
+        return rotation;
+    }
+
+    /**
+     * Sets rotation
+     * @param rotation 
+     */
+    public void setRotation(Vector3d rotation) {
+        this.rotation = rotation;
+    }
+
+    /**
+     * @return Current scale
+     */
+    public Vector3d getScale() {
+        return scale;
+    }
+
+    /**
+     * Sets scale
+     * @param scale Scale
+     */
+    public void setScale(Vector3d scale) {
+        this.scale = scale;
+    }
+    
+    /**
+     * @return Value of {@link #renderMode}
+     */
+    public int getRenderMode() {
+        return renderMode;
+    }
+
+    /**
+     * Sets render mode
+     * @param renderMode Render mode
+     * @throws IllegalArgumentException if renderMode isn't {@code GL_FILL}, {@code GL_LINE} or {@code GL_POINT}
+     */
+    public void setRenderMode(int renderMode) {
+        if (renderMode != GL2.GL_FILL && 
+                renderMode != GL2.GL_LINE &&
+                renderMode != GL2.GL_POINT) {
+            throw new IllegalArgumentException("invalid mode");
+        }
+        this.renderMode = renderMode;
+    }
+
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/scene/DrawableFace.java b/GUI/src/main/java/cz/fidentis/analyst/scene/DrawableFace.java
new file mode 100644
index 0000000000000000000000000000000000000000..3d1c97da453e6910f02ccc6cdec3068ee09b0810
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/scene/DrawableFace.java
@@ -0,0 +1,136 @@
+package cz.fidentis.analyst.scene;
+
+import com.jogamp.opengl.GL2;
+import cz.fidentis.analyst.face.HumanFace;
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import java.awt.Color;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Drawable human face.
+ * 
+ * @author Radek Oslejsek
+ * @author Daniel Schramm
+ */
+public class DrawableFace extends DrawableMesh {
+    
+    public static final Color SKIN_COLOR_PRIMARY = new Color(224, 172, 105);
+    public static final Color SKIN_COLOR_SECONDARY = new Color(236, 188, 180);
+    
+    private final HumanFace humanFace;
+    private boolean renderHeatMap = false;
+    
+    /**
+     * Values at mesh vertices that are to be transferred to colors.
+     */
+    private Map<MeshFacet, List<Double>> heatmap = new HashMap<>();
+    /**
+     * Values at mesh vertices that determine the saturation level of heatmap colors.
+     */
+    private Map<MeshFacet, List<Double>> heatmapSaturation = new HashMap<>();
+    
+    /**
+     * Constructor.
+     * 
+     * @param face Drawable human face
+     * @throws IllegalArgumentException if the mesh model
+     *         of the human face is {@code null}
+     */
+    public DrawableFace(HumanFace face) {
+        super(face.getMeshModel());
+        humanFace = face;
+        setColor(SKIN_COLOR_PRIMARY);
+    }
+    
+    /**
+     * Sets new heatmap.
+     * 
+     * @param heatmap New heatmap
+     */
+    public void setHeatMap(Map<MeshFacet, List<Double>> heatmap) {
+        this.heatmap = heatmap;
+    }
+    
+    /**
+     * Removes the heatmap from the face.
+     */
+    public void clearHeatMap() {
+        heatmap = new HashMap<>();
+    }
+    
+    /**
+     * Returns heatmap of the face
+     * (values at mesh vertices that are to be transferred to colors).
+     * 
+     * @return Heatmap of the face
+     */
+    public Map<MeshFacet, List<Double>> getHeatMap() {
+        return Collections.unmodifiableMap(heatmap);
+    }
+
+    /**
+     * Sets new map of heatmap colors saturation.
+     * 
+     * @param heatmapSaturation New map of heatmap colors saturation
+     */
+    public void setHeatMapSaturation(Map<MeshFacet, List<Double>> heatmapSaturation) {
+        this.heatmapSaturation = heatmapSaturation;
+    }
+    
+    /**
+     * Removes the map of heatmap colors saturation from the face.
+     */
+    public void clearHeatMapSaturation() {
+        heatmapSaturation = new HashMap<>();
+    }
+
+    /**
+     * Returns map of heatmap colors saturation
+     * (values at mesh vertices that determine the saturation level of heatmap colors).
+     * 
+     * @return Map of heatmap colors saturation
+     */
+    public Map<MeshFacet, List<Double>> getHeatMapSaturation() {
+        return Collections.unmodifiableMap(heatmapSaturation);
+    }
+
+    /**
+     * Returns the human face.
+     * 
+     * @return {@link HumanFace}
+     */
+    public HumanFace getHumanFace() {
+        return humanFace;
+    }
+    
+    /**
+     * Sets if the heatmap should be rendered or not.
+     * 
+     * @param render The switch
+     */
+    public void setRenderHeatmap(boolean render) {
+        this.renderHeatMap = render;
+    }
+    
+    /**
+     * Determines whether the heatmap is set to be rendered.
+     * 
+     * @return id the heatmap will be rendered
+     */
+    public boolean isHeatmapRendered() {
+        return this.renderHeatMap;
+    }
+    
+    @Override
+    protected void renderObject(GL2 gl) {
+        if (isHeatmapRendered()) {
+            new HeatmapRenderer().drawMeshModel(gl, getModel(), heatmap, heatmapSaturation);
+        } else {
+            super.renderObject(gl);
+        }
+    }
+    
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/scene/DrawableFeaturePoints.java b/GUI/src/main/java/cz/fidentis/analyst/scene/DrawableFeaturePoints.java
new file mode 100644
index 0000000000000000000000000000000000000000..3b9b93bc0aa94e658132cfff0613417203dc06ff
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/scene/DrawableFeaturePoints.java
@@ -0,0 +1,280 @@
+package cz.fidentis.analyst.scene;
+
+import com.jogamp.opengl.GL2;
+import com.jogamp.opengl.glu.GLU;
+import com.jogamp.opengl.glu.GLUquadric;
+import cz.fidentis.analyst.feature.FeaturePoint;
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Drawable feature points.
+ * 
+ * @author Radek Oslejsek
+ * @author Daniel Schramm
+ */
+public class DrawableFeaturePoints extends Drawable {
+    
+    public static final Color DEFAULT_COLOR = Color.LIGHT_GRAY;
+    public static final double DEFAULT_SIZE = 3f;
+    
+    private static final GLU GLU_CONTEXT = new GLU();
+    
+    /* feature points */
+    private final List<FeaturePoint> featurePoints;
+    
+    /**
+     * feature points with color different from the default color
+     */
+    private final Map<Integer, Color> specialColors = new HashMap<>();
+    
+    /**
+     * feature points with size different from the default size
+     */
+    private final Map<Integer, Double> specialSizes = new HashMap<>();
+    
+    /**
+     * feature points rendered differently than the default render mode
+     */
+    private final Map<Integer, Integer> specialRenderModes = new HashMap<>();
+    
+    /**
+     * Constructor.
+     * 
+     * @param featurePoints Feature points
+     */
+    public DrawableFeaturePoints(List<FeaturePoint> featurePoints) {
+        this.featurePoints = new ArrayList<>(featurePoints);
+        setColor(DEFAULT_COLOR);
+    }
+    
+    /**
+     * Returns color of the feature point.
+     * 
+     * @param index Index of the feature point
+     * @return The color or {@code null}
+     */
+    public Color getColor(int index) {
+        if (index < 0 || index >= featurePoints.size()) {
+            return null;
+        }
+        if (specialColors.containsKey(index)) {
+            return specialColors.get(index);
+        } else {
+            return getColor();
+        }
+    }
+    
+    /**
+     * Sets color of the feature point.
+     * 
+     * @param index Index of the feature point
+     * @param color New color of the feature point
+     */
+    public void setColor(int index, Color color) {
+        if (index < 0 || index >= featurePoints.size() || color == null) {
+            return;
+        }
+        if (color.equals(getColor())) {
+            specialColors.remove(index);
+        } else {
+            specialColors.put(index, color);
+        }
+    }
+    
+    /**
+     * Removes (possible) special color of the feature point.
+     * 
+     * @param index Index of the feature point
+     */
+    public void resetColorToDefault(int index) {
+        setColor(index, getColor());
+    }
+    
+    /**
+     * Removes all individual colors of feature points.
+     */
+    public void resetAllColorsToDefault() {
+        this.specialColors.clear();
+    }
+    
+    /**
+     * Returns size of the feature point.
+     * 
+     * @param index Index of the feature point
+     * @return The size or {@code null}
+     */
+    public Double getSize(int index) {
+        if (index < 0 || index >= featurePoints.size()) {
+            return null;
+        }
+        if (specialSizes.containsKey(index)) {
+            return specialSizes.get(index);
+        } else {
+            return DEFAULT_SIZE;
+        }
+    }
+    
+    /**
+     * Sets size of the feature point.
+     * 
+     * @param index Index of the feature point
+     * @param size New size of the feature point
+     */
+    public void setSize(int index, double size) {
+        if (index < 0 || index >= featurePoints.size()) {
+            return;
+        }
+        if (size == DEFAULT_SIZE) {
+            specialSizes.remove(index);
+        } else {
+            specialSizes.put(index, size);
+        }
+    }
+    
+    /**
+     * Removes (possible) special size of the feature point.
+     * 
+     * @param index Index of the feature point
+     */
+    public void resetSizeToDefault(int index) {
+        setSize(index, DEFAULT_SIZE);
+    }
+    
+    /**
+     * Removes all individual sizes of feature points.
+     */
+    public void resetAllSizesToDefault() {
+        specialSizes.clear();
+    }
+    
+    /**
+     * Returns render mode of the feature point.
+     * 
+     * @param index Index of the feature point
+     * @return The render mode or {@code null}
+     */
+    public Integer getRenderMode(int index) {
+        if (index < 0 || index >= featurePoints.size()) {
+            return null;
+        }
+        if (specialRenderModes.containsKey(index)) {
+            return specialRenderModes.get(index);
+        } else {
+            return getRenderMode();
+        }
+    }
+    
+    /**
+     * Sets render mode of the feature point.
+     * The render mode must be {@link GL2#GL_FILL}, {@link GL2#GL_LINE}
+     * or {@link GL2#GL_POINT}.
+     * 
+     * @param index Index of the feature point
+     * @param renderMode New render mode of the feature point
+     * @throws IllegalArgumentException if renderMode isn't {@code GL_FILL},
+     *         {@code GL_LINE} or {@code GL_POINT}
+     */
+    public void setRenderMode(int index, int renderMode) {
+        if (renderMode != GL2.GL_FILL &&
+                renderMode != GL2.GL_LINE &&
+                renderMode != GL2.GL_POINT) {
+            throw new IllegalArgumentException("renderMode");
+        }
+        if (index < 0 || index >= featurePoints.size()) {
+            return;
+        }
+        if (renderMode == getRenderMode()) {
+            specialRenderModes.remove(index);
+        } else {
+            specialRenderModes.put(index, renderMode);
+        }
+    }
+    
+    /**
+     * Removes (possible) special render mode of the feature point.
+     * 
+     * @param index Index of the feature point
+     */
+    public void resetRenderModeToDefault(int index) {
+        setRenderMode(index, getRenderMode());
+    }
+    
+    /**
+     * Removes all individual render modes of feature points.
+     */
+    public void resetAllRenderModesToDefault() {
+        specialRenderModes.clear();
+    }
+
+    @Override
+    protected void renderObject(GL2 gl) {
+        float[] rgba = {
+            getColor().getRed() / 255f, 
+            getColor().getGreen() / 255f, 
+            getColor().getBlue() / 255f, 
+            getTransparency()
+        };
+        gl.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_DIFFUSE, rgba, 0); // set default color
+        
+        for (int i = 0; i < featurePoints.size(); i++) {
+            FeaturePoint fp = featurePoints.get(i);
+            
+            Color specialColor = specialColors.get(i);
+            if (specialColor != null) {
+                float[] tmpRGB = {specialColor.getRed() / 255f, specialColor.getGreen() / 255f, specialColor.getBlue() / 255f, getTransparency()};
+                gl.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_DIFFUSE, tmpRGB, 0);
+            }
+            
+            Integer specialRenderMode = specialRenderModes.get(i);
+            if (specialRenderMode != null) {
+                gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, specialRenderMode);
+            }
+            
+            gl.glPushMatrix(); 
+            gl.glTranslated(fp.getX(), fp.getY(), fp.getZ());
+            GLUquadric center = GLU_CONTEXT.gluNewQuadric();
+            GLU_CONTEXT.gluQuadricDrawStyle(center, GLU.GLU_FILL);
+            GLU_CONTEXT.gluQuadricNormals(center, GLU.GLU_FLAT);
+            GLU_CONTEXT.gluQuadricOrientation(center, GLU.GLU_OUTSIDE);
+            GLU_CONTEXT.gluSphere(center, specialSizes.getOrDefault(i, DEFAULT_SIZE), 16, 16);
+            GLU_CONTEXT.gluDeleteQuadric(center);
+            gl.glPopMatrix();
+    
+            if (specialColor != null) {
+                gl.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_DIFFUSE, rgba, 0); // set default color
+            }
+            if (specialRenderMode != null) {
+                gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, getRenderMode()); // set default render mode
+            }
+        }
+    }
+    
+    
+       
+    /**
+     * @return {@link List} of {@link FeaturePoint}
+     */
+    public List<FeaturePoint> getFeaturePoints() {
+        return featurePoints;
+    }
+
+    /**
+     * Sets feature points
+     * @param featurePoints Feature points
+     */
+    /*
+    public void setFeaturePoints(List<FeaturePoint> featurePoints) {
+        this.featurePoints = featurePoints;
+        List<Color> colors = new ArrayList<>();
+        featurePoints.forEach((_item) -> {
+            colors.add(getColor());
+        });
+        this.setFeaturePointsColor(colors);
+    } 
+    */
+    
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/scene/DrawableMesh.java b/GUI/src/main/java/cz/fidentis/analyst/scene/DrawableMesh.java
new file mode 100644
index 0000000000000000000000000000000000000000..ae19a418ae4061685480fca7802081415fef8a3f
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/scene/DrawableMesh.java
@@ -0,0 +1,107 @@
+package cz.fidentis.analyst.scene;
+
+import com.jogamp.opengl.GL2;
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshModel;
+import java.awt.Color;
+import java.util.List;
+import javax.vecmath.Point3d;
+import javax.vecmath.Vector3d;
+
+/**
+ * A drawable triangular mesh, i.e., a mesh model with drawing information like 
+ * material, transparency, color, relative transformations in the scene etc. 
+ * This class encapsulates rendering state and parameters,
+ * 
+ * @author Radek Oslejsek
+ * @author Richard Pajersky
+ */
+public class DrawableMesh extends Drawable {
+    
+    private final MeshModel model;
+    
+    /**
+     * Constructor. 
+     * 
+     * @param model Drawable mesh model
+     * @throws IllegalArgumentException if the model is {@code null}
+     */
+    public DrawableMesh(MeshModel model) {
+        if (model == null) {
+            throw new IllegalArgumentException("model is null");
+        }
+        this.model = model;
+    }
+    
+    /**
+     * Constructor. 
+     * 
+     * @param facet Mesh facet
+     * @throws IllegalArgumentException if the model is {@code null}
+     */
+    public DrawableMesh(MeshFacet facet) {
+        if (facet == null) {
+            throw new IllegalArgumentException("facet is null");
+        }
+        this.model = new MeshModel();
+        this.model.addFacet(facet);
+    }
+    
+    @Override
+    protected void initRendering(GL2 gl) {
+        super.initRendering(gl);
+        
+        // showBackface
+        //float[] pos = {0f, 0f, -1f, 0f};
+        //gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_POSITION, pos, 0);
+        //if (isShowBackface()) {
+        //    gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_DIFFUSE, Color.white.getComponents(null), 0);
+        //} else {
+        //    gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_DIFFUSE, Color.black.getComponents(null), 0);
+        //}
+    
+        // set color of highlights
+        Color col = getHighlights();
+        float[] highlights = {col.getRed(), col.getGreen(), col.getBlue(), 1};
+        gl.glMaterialf(GL2.GL_FRONT_AND_BACK, GL2.GL_SHININESS, 50);  
+        gl.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_SPECULAR, highlights, 0);
+    }
+    
+    @Override
+    protected void renderObject(GL2 gl) {
+        for (MeshFacet facet: getFacets()) {
+            gl.glBegin(GL2.GL_TRIANGLES); //vertices are rendered as triangles
+        
+            // get the normal and tex coords indicies for face i  
+            for (int v = 0; v < facet.getCornerTable().getSize(); v++) {            
+                // render the normals
+                Vector3d norm = facet.getVertices().get(facet.getCornerTable().getRow(v).getVertexIndex()).getNormal(); 
+                if(norm != null) {
+                    gl.glNormal3d(norm.x, norm.y, norm.z);
+                }
+                // render the vertices
+                Point3d vert = facet.getVertices().get(facet.getCornerTable().getRow(v).getVertexIndex()).getPosition();
+                gl.glVertex3d(vert.x, vert.y, vert.z);
+            }
+        
+            gl.glEnd();
+        }
+    }
+    
+    /**
+     * Returns list of individual facets.
+     * 
+     * @return list of individual facets.
+     */
+    public List<MeshFacet> getFacets() {
+        return model.getFacets();
+    }
+    
+    /**
+     * @return {@link MeshModel}
+     */
+    public MeshModel getModel() {
+        return this.model;
+    }
+
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/scene/DrawablePlane.java b/GUI/src/main/java/cz/fidentis/analyst/scene/DrawablePlane.java
new file mode 100644
index 0000000000000000000000000000000000000000..795bddc0c7d9bec925588f81aca244f363ade894
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/scene/DrawablePlane.java
@@ -0,0 +1,41 @@
+package cz.fidentis.analyst.scene;
+
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshModel;
+import cz.fidentis.analyst.symmetry.Plane;
+
+/**
+ * A cutting plane.
+ * 
+ * @author Radek Oslejsek
+ */
+public class DrawablePlane extends DrawableMesh {
+    
+    private final Plane plane;
+    
+    /**
+     * Constructor.
+     * @param model Mesh model of the plane
+     * @param plane The plane
+     */
+    public DrawablePlane(MeshModel model, Plane plane) {
+        super(model);
+        if (plane == null) {
+            throw new IllegalArgumentException("plane");
+        }
+        this.plane = plane;
+    }
+    
+    /**
+     * Constructor.
+     * @param facet Mesh facet of the plane
+     * @param plane The plane
+     */
+    public DrawablePlane(MeshFacet facet, Plane plane) {
+        super(facet);
+        if (plane == null) {
+            throw new IllegalArgumentException("plane");
+        }
+        this.plane = plane;
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/scene/HeatmapRenderer.java b/GUI/src/main/java/cz/fidentis/analyst/scene/HeatmapRenderer.java
new file mode 100644
index 0000000000000000000000000000000000000000..015692b2bf614d9ec54f6a6d660f0032f7cae946
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/scene/HeatmapRenderer.java
@@ -0,0 +1,153 @@
+package cz.fidentis.analyst.scene;
+
+import com.jogamp.opengl.GL2;
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshModel;
+import java.awt.Color;
+import java.util.List;
+import java.util.Map;
+import javax.vecmath.Point3d;
+import javax.vecmath.Vector3d;
+
+/**
+ * Heatmap rendering.
+ * 
+ * @author Daniel Sokol
+ * @author Daniel Schramm
+ */
+public class HeatmapRenderer {
+    
+    private Color minColor = Color.RED;
+    private Color maxColor = Color.BLUE;
+
+    public void setMinColor(Color color) {
+        minColor = color;
+    }
+    
+    public void setMaxColor(Color color) {
+        maxColor = color;
+    }
+    
+    /**
+     * Maps distances of mesh model vertices to colors and renders the taken heatmap.
+     * @param gl OpenGL context
+     * @param model Mesh model to be rendered
+     * @param distances Distances in mesh model vertices
+     * @param saturation Saturation of colors at mesh model vertices
+     */
+    public void drawMeshModel(GL2 gl, MeshModel model,
+            Map<MeshFacet, List<Double>> distances, Map<MeshFacet, List<Double>> saturation) {
+        double minDistance = Double.POSITIVE_INFINITY;
+        double maxDistance = Double.NEGATIVE_INFINITY;
+        
+        for (MeshFacet f: model.getFacets()) {
+            List<Double> distanceList = distances.get(f);
+            if (distanceList != null) {
+                minDistance = Math.min(
+                        minDistance,
+                        distanceList.parallelStream()
+                                .mapToDouble(Double::doubleValue)
+                                .min()
+                                .getAsDouble()
+                );
+                maxDistance = Math.max(
+                        maxDistance,
+                        distanceList.parallelStream()
+                                .mapToDouble(Double::doubleValue)
+                                .max()
+                                .getAsDouble()
+                );
+            }
+        }
+        
+        for (MeshFacet f: model.getFacets()) {
+            if (distances.containsKey(f)) {
+                renderMeshFacet(gl, f, distances.get(f), saturation.get(f), minDistance, maxDistance);
+            }
+        }
+    }
+    
+    /**
+     * Maps distances of mesh facet to colors and renders the taken heatmap.
+     * @param gl OpenGL context
+     * @param facet Mesh facet
+     * @param distancesList Distances in the mesh facet vertices
+     * @param saturationList Saturation of colors at mesh facet vertices. May be {@code null}.
+     * @param minDistance Minimal distance threshold (smaller distances are cut-off)
+     * @param maxDistance Maxim distance threshold (bigger distances are cut-off)
+     */
+    public void renderMeshFacet(GL2 gl, MeshFacet facet, List<Double> distancesList,
+            List<Double> saturationList, double minDistance, double maxDistance) {
+        gl.glBegin(GL2.GL_TRIANGLES); //vertices are rendered as triangles
+
+        // get the normal and tex coords indicies for face i
+        for (int v = 0; v < facet.getCornerTable().getSize(); v++) {
+            int vertexIndex = facet.getCornerTable().getRow(v).getVertexIndex();
+            
+            // render the normals
+            Vector3d norm = facet.getVertices().get(vertexIndex).getNormal();
+            if (norm != null) {
+                gl.glNormal3d(norm.x, norm.y, norm.z);
+            }
+            
+            // render the vertices
+            Point3d vert = facet.getVertices().get(vertexIndex).getPosition();
+            
+            //get color of vertex
+            double currentDistance = distancesList.get(vertexIndex);
+            double currentSaturation = saturationList == null ? 1d : saturationList.get(vertexIndex);
+            Color c = getColor(currentDistance, currentSaturation, minDistance, maxDistance);
+            gl.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_DIFFUSE, c.getComponents(null), 0);
+
+            gl.glVertex3d(vert.x, vert.y, vert.z);
+        }
+        gl.glEnd();
+        gl.glPopAttrib();
+    }
+    
+    private Color getColor(double currentDistance, double currentSaturation, double minDistance, double maxDistance) {
+        double currentParameter = ((currentDistance - minDistance) / (maxDistance - minDistance));
+
+        float[] hsb1 = Color.RGBtoHSB(minColor.getRed(), minColor.getGreen(), minColor.getBlue(), null);
+        float h1 = hsb1[0];
+        float s1 = hsb1[1];
+        float b1 = hsb1[2];
+
+        float[] hsb2 = Color.RGBtoHSB(maxColor.getRed(), maxColor.getGreen(), maxColor.getBlue(), null);
+        float h2 = hsb2[0];
+        float s2 = hsb2[1];
+        float b2 = hsb2[2];
+
+        // determine clockwise and counter-clockwise distance between hues
+        float distCCW;
+        float distCW;
+
+        if (h1 >= h2) {
+            distCCW = h1 - h2;
+            distCW = 1 + h2 - h1;
+        } else {
+            distCCW = 1 + h1 - h2;
+            distCW = h2 - h1;
+        }
+
+        float hue;
+
+        if (distCW >= distCCW) {
+            hue = (float) (h1 + (distCW * currentParameter));
+        } else {
+            hue = (float) (h1 - (distCCW * currentParameter));
+        }
+
+        if (hue < 0) {
+            hue = 1 + hue;
+        }
+        if (hue > 1) {
+            hue = hue - 1;
+        }
+
+        float saturation = (float) (((1 - currentParameter) * s1 + currentParameter * s2) * currentSaturation);
+        float brightness = (float) ((1 - currentParameter) * b1 + currentParameter * b2);
+
+        return Color.getHSBColor(hue, saturation, brightness);
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/scene/Scene.java b/GUI/src/main/java/cz/fidentis/analyst/scene/Scene.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f14cee8e275a139ba89f18b008486b629e2a0ed
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/scene/Scene.java
@@ -0,0 +1,193 @@
+package cz.fidentis.analyst.scene;
+
+import cz.fidentis.analyst.face.HumanFace;
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Abstract class for ...
+ * 
+ * @author Radek Oslejsek
+ */
+public class Scene {
+    
+    private final List<HumanFace> faces = new ArrayList<>();
+    private final List<DrawableFace> drawableFaces = new ArrayList<>();
+    private final List<DrawableFeaturePoints> drawableFeaturePoints = new ArrayList<>();
+    private final List<DrawablePlane> drawableSymmetryPlanes = new ArrayList<>();
+    private final List<Drawable> otherDrawables = new ArrayList<>();
+    
+    /**
+     * Constructor for single face analysis.
+     * 
+     * @param face Human face to be analyzed
+     * @throws IllegalArgumentException if the {@code face} is {@code null}
+     */
+    public Scene(HumanFace face) {
+        if (face == null) {
+            throw new IllegalArgumentException("face");
+        }
+
+        faces.add(face);
+        drawableFaces.add(new DrawableFace(face));
+        if (face.getFeaturePoints() != null) {
+            drawableFeaturePoints.add(new DrawableFeaturePoints(face.getFeaturePoints()));
+        } else {
+            drawableFeaturePoints.add(null);
+        }
+        drawableSymmetryPlanes.add(null);
+        
+        setDefaultColors();
+    }
+    
+    /**
+     * Constructor for one-to-one analysis.
+     * 
+     * @param primary Primary face to be analyzed
+     * @param secondary Secondary face to be analyzed
+     * @throws IllegalArgumentException if some face is {@code null}
+     */
+    public Scene(HumanFace primary, HumanFace secondary) {
+        if (primary == null) {
+            throw new IllegalArgumentException("primary");
+        }
+        if (secondary == null) {
+            throw new IllegalArgumentException("secondary");
+        }
+        
+        faces.add(primary);
+        faces.add(secondary);
+        
+        drawableFaces.add(new DrawableFace(primary));
+        drawableFaces.add(new DrawableFace(secondary));
+        
+        if (primary.getFeaturePoints() != null) {
+            drawableFeaturePoints.add(new DrawableFeaturePoints(primary.getFeaturePoints()));
+        } else {
+            drawableFeaturePoints.add(null);
+        }
+        if (secondary.getFeaturePoints() != null) {
+            drawableFeaturePoints.add(new DrawableFeaturePoints(secondary.getFeaturePoints()));
+        } else {
+            drawableFeaturePoints.add(null);
+        }
+
+        drawableSymmetryPlanes.add(null);
+        drawableSymmetryPlanes.add(null);
+
+        setDefaultColors();
+    }
+    
+    /**
+     * Sets default colors of faces and feature points
+     */
+    public final void setDefaultColors() {
+        for (int i = 0; i < getNumFaces(); i++) {
+            if (drawableFaces.get(i) != null) {
+                drawableFaces.get(i).setColor((i == 0) ? DrawableFace.SKIN_COLOR_PRIMARY : DrawableFace.SKIN_COLOR_SECONDARY); 
+            }
+            if (drawableFeaturePoints.get(i) != null) {
+                drawableFeaturePoints.get(i).setColor(getColorOfFeaturePoints((i == 0) ? DrawableFace.SKIN_COLOR_PRIMARY : DrawableFace.SKIN_COLOR_SECONDARY));
+                drawableFeaturePoints.get(i).resetAllColorsToDefault();
+            }
+        }
+    }
+    
+    /**
+     * Returns number of faces in the scene.
+     * @return number of faces in the scene
+     */
+    public int getNumFaces() {
+        return faces.size();
+    }
+    
+    /**
+     * Returns human face.
+     * 
+     * @param index Index of the face
+     * @return drawable face or {@code null}
+     */
+    public HumanFace getHumanFace(int index) {
+        return (index >= 0 && index < getNumFaces()) ? faces.get(index) : null;
+    }
+    
+    /**
+     * Returns drawable face.
+     * 
+     * @param index Index of the face
+     * @return drawable face or {@code null}
+     */
+    public DrawableFace getDrawableFace(int index) {
+        return (index >= 0 && index < getNumFaces()) ? drawableFaces.get(index) : null;
+    }
+    
+    /**
+     * Returns drawable feature points.
+     * 
+     * @param index Index of the face
+     * @return drawable face or {@code null}
+     */
+    public DrawableFeaturePoints getDrawableFeaturePoints(int index) {
+        return (index >= 0 && index < getNumFaces()) ? drawableFeaturePoints.get(index) : null;
+    }
+    
+    /**
+     * Returns drawable symmetry plane.
+     * 
+     * @param index Index of the face
+     * @return drawable face or {@code null}
+     */
+    public DrawablePlane getDrawableSymmetryPlane(int index) {
+        return (index >= 0 && index < getNumFaces()) ? drawableSymmetryPlanes.get(index) : null;
+    }
+    
+    /**
+     * Sets the drawable symmetry plane.
+     * 
+     * @param index Index of the face
+     * @param sPlane New symmetry plane
+     */
+    public void setDrawableSymmetryPlane(int index, DrawablePlane sPlane) {
+        if (index >= 0 && index < getNumFaces() && sPlane != null) {
+            this.drawableSymmetryPlanes.set(index, sPlane);
+        }
+    }
+    
+    /**
+     * Adds new drawable object to the scene.
+     * 
+     * <p>
+     * Note: This drawable object is ignored in the {@link setDefaultColors} method.
+     * The caller must take care of the colors of the object themself.
+     * </p>
+     * 
+     * @param otherDrawable Drawable object to be added to the scene
+     */
+    public void addOtherDrawable(Drawable otherDrawable) {
+        otherDrawables.add(otherDrawable);
+    }
+    
+    /**
+     * Returns all drawable objects.
+     * 
+     * @return all drawable objects.
+     */
+    public List<Drawable> getAllDrawables() {
+        List<Drawable> ret = new ArrayList<>();
+        ret.addAll(this.drawableFaces);
+        ret.addAll(this.drawableFeaturePoints);
+        ret.addAll(this.drawableSymmetryPlanes);
+        ret.addAll(this.otherDrawables);
+        while (ret.remove(null)) {}
+        return ret;
+    }
+    
+    private Color getColorOfFeaturePoints(Color origColor) {
+        return new Color(
+                Math.min(255, origColor.getRed() + 40),
+                Math.min(255, origColor.getGreen() + 40),
+                Math.min(255, origColor.getBlue() + 40)
+        );
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/scene/SceneRenderer.java b/GUI/src/main/java/cz/fidentis/analyst/scene/SceneRenderer.java
similarity index 59%
rename from GUI/src/main/java/cz/fidentis/analyst/gui/scene/SceneRenderer.java
rename to GUI/src/main/java/cz/fidentis/analyst/scene/SceneRenderer.java
index cda999208c6311f269071aea9dc2b7304cb13c64..7307d5afe9fe12edf8feab2b9a7c7ae7523323cf 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/scene/SceneRenderer.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/scene/SceneRenderer.java
@@ -1,18 +1,15 @@
-package cz.fidentis.analyst.gui.scene;
+package cz.fidentis.analyst.scene;
 
 import com.jogamp.opengl.GL;
-import static com.jogamp.opengl.GL.GL_DEPTH_TEST;
-import static com.jogamp.opengl.GL.GL_FRONT_AND_BACK;
 import com.jogamp.opengl.GL2;
-import static com.jogamp.opengl.GL2GL3.GL_FILL;
-import static com.jogamp.opengl.GL2GL3.GL_LINE;
 import com.jogamp.opengl.glu.GLU;
 import cz.fidentis.analyst.mesh.core.MeshFacet;
+import java.awt.Color;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import javax.vecmath.Point3d;
-import javax.vecmath.Point4f;
 import javax.vecmath.Vector3d;
 
 /**
@@ -20,17 +17,17 @@ import javax.vecmath.Vector3d;
  * 
  * @author Natalia Bebjakova
  * @author Radek Oslejsek
+ * @author Richard Pajersky
  */
 public class SceneRenderer {
 
-    private static final Point4f BRIGHT_BACKGROUND = new Point4f(0.9f, 0.9f, 0.9f, 0);
-    private static final Point4f DARK_BACKGROUND = new Point4f(0.25f, 0.25f, 0.25f, 0);
+    public static final Color BRIGHT_BACKGROUND = new Color(0.9f, 0.9f, 0.9f);
+    public static final Color DARK_BACKGROUND = new Color(0.25f, 0.25f, 0.25f);
     
     private final GLU glu = new GLU();
     private GL2 gl;
     
     private boolean brightBackground = false;
-    private boolean wireframe = false;
     
     /**
      * Constructor.
@@ -47,6 +44,7 @@ public class SceneRenderer {
         gl.setSwapInterval(1);
         gl.glEnable(GL2.GL_LIGHTING);
         gl.glEnable(GL2.GL_LIGHT0);
+        gl.glEnable(GL2.GL_LIGHT1);
         gl.glEnable(GL2.GL_DEPTH_TEST);
         gl.glClearColor(0,0,0,0);     // background for GLCanvas
         gl.glClear(GL2.GL_COLOR_BUFFER_BIT);
@@ -55,10 +53,13 @@ public class SceneRenderer {
 
         gl.glDepthFunc(GL2.GL_LESS);
         gl.glDepthRange(0.0, 1.0);
-        gl.glEnable(GL_DEPTH_TEST); 
+        gl.glEnable(GL.GL_DEPTH_TEST); 
 
         gl.glEnable(GL2.GL_NORMALIZE);
         gl.glDisable(GL2.GL_CULL_FACE);
+        
+        gl.glEnable(GL2.GL_BLEND);    // enable transparency
+        gl.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE_MINUS_SRC_ALPHA);
     }
     
     /**
@@ -84,7 +85,8 @@ public class SceneRenderer {
      * @param height Height
      */
     public void setViewport(int x, int y, int width, int height) {
-
+        //OutputWindow out = OutputWindow.measureTime();
+        
         if (height == 0) {
             height = 1;    // to avoid division by 0 in aspect ratio below
         }
@@ -94,47 +96,78 @@ public class SceneRenderer {
 
         gl.glMatrixMode(GL2.GL_PROJECTION);
         gl.glLoadIdentity();
-
-        glu.gluPerspective(65, width / (float) height, 5.0f, 1500.0f);
+        glu.gluPerspective(50, width / (float) height, 5.0f, 1500.0f);
+        
         gl.glMatrixMode(GL2.GL_MODELVIEW);
         gl.glLoadIdentity();
-
         gl.glTranslatef(0.0f, 0.0f, -40.0f);
+        
+        //out.printDuration("GL viewport set to " + width + "x" + height);
     }
     
     /**
      * Renders drawable objects.
      */
-    public void renderScene(Camera camera, Collection<DrawableMesh> drawables) {
+    public void renderScene(Camera camera, Collection<Drawable> drawables) {
+        //OutputWindow out = OutputWindow.measureTime();
         clearScene();
         
-        // sets model to proper position
+        // light backface
+        gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_POSITION, new float[] {0f, 0f, -1f, 0f}, 0);
+        gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_DIFFUSE, Color.white.getComponents(null), 0);
+        
+        setPosition(camera);
+        List<DrawableFace> faces = getOrderedFaces(drawables);
+        
+        for (Drawable obj: drawables) {
+            if (!(obj instanceof DrawableFace) && obj.isShown()) {
+                obj.render(gl);
+            }
+        }
+        
+        for (DrawableFace obj: faces) {
+            if (obj.isShown()) {
+                //showBackface(obj);
+                obj.render(gl);
+            }
+        }
+        
+        gl.glFlush();
+        
+        //out.printDuration("Scene rendering");
+    }
+    
+    /**
+     * Sets model to proper position
+     * 
+     * @param camera Camera
+     */
+    private void setPosition(Camera camera) {
         Vector3d currentPosition = camera.getPosition();
         Vector3d center = camera.getCenter();
         Vector3d upDirection = camera.getUpDirection();
         glu.gluLookAt(currentPosition.x, currentPosition.y, currentPosition.z,  
                 center.x, center.y, center.z,
                 upDirection.x, upDirection.y, upDirection.z);
-
-        gl.glShadeModel(GL2.GL_SMOOTH);
-        //gl.glGetIntegerv(GL_VIEWPORT, viewport, 0);
-        //gl.glGetFloatv(GL_MODELVIEW_MATRIX, modelViewMatrix, 0);
-        //gl.glGetFloatv(GL_PROJECTION_MATRIX, projectionMatrix, 0);
-        
-        if (this.wireframe) {
-            gl.glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
-        } else {
-            gl.glPolygonMode( GL_FRONT_AND_BACK, GL_FILL);
-        }
-        
-        for (DrawableMesh obj: drawables) {
-            for (MeshFacet facet: obj.getFacets()) {
-                // TO DO - R. Pajersky: add transformation (glPushMatrix, glRotate, ...)
-                renderFacet(facet);
+    }
+    
+    /**
+     * Sets up transparent objects to render later in order to render properly
+     * Now works only for two meshes
+     * 
+     * @param drawables List of meshes
+     */
+    private List<DrawableFace> getOrderedFaces(Collection<Drawable> drawables) {
+        List<DrawableFace> faces = new ArrayList<>();
+        for (Drawable obj: drawables) {
+            if (obj instanceof DrawableFace) {
+                faces.add((DrawableFace) obj);
             }
         }
-        
-         gl.glFlush();
+        if (faces.get(0).getTransparency() != 1) {
+            Collections.reverse(faces);
+        }
+        return faces;
     }
     
     /**
@@ -142,50 +175,42 @@ public class SceneRenderer {
      */
     protected void clearScene() { // join with the renderScene() ???
         if (brightBackground) {
-            gl.glClearColor(BRIGHT_BACKGROUND.x, BRIGHT_BACKGROUND.y, BRIGHT_BACKGROUND.z, BRIGHT_BACKGROUND.w);
+            gl.glClearColor(
+                    BRIGHT_BACKGROUND.getRed()   / 255f, 
+                    BRIGHT_BACKGROUND.getGreen() / 255f, 
+                    BRIGHT_BACKGROUND.getBlue()  / 255f, 
+                    0.0f);
         } else {
-            gl.glClearColor(DARK_BACKGROUND.x, DARK_BACKGROUND.y, DARK_BACKGROUND.z, DARK_BACKGROUND.w);
+            gl.glClearColor(
+                    DARK_BACKGROUND.getRed()   / 255f, 
+                    DARK_BACKGROUND.getGreen() / 255f, 
+                    DARK_BACKGROUND.getBlue()  / 255f, 
+                    0.0f);
         }
         gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
         gl.glLoadIdentity();
     }
     
-    /**
-     * Sets the wire-frame rendering mode
-     */
-    protected void setWireframeMode() {
-        this.wireframe = true;
-    }
-    
-    /**
-     * Sets the "shaded" rendering mode (filled triangles)
-     */
-    protected void setFillMode() {
-        this.wireframe = false;
-    }
-    
     /**
      * Loops through the facet and render all the vertices as they are stored in corner table
      * 
-     * @param gl OpenGL context
      * @param facet facet of model
      */
     protected void renderFacet(MeshFacet facet) {
         gl.glBegin(GL2.GL_TRIANGLES); //vertices are rendered as triangles
         
          // get the normal and tex coords indicies for face i  
-        for (int v = 0; v < facet.getCornerTable().getSize(); v++) { 
+        for (int v = 0; v < facet.getCornerTable().getSize(); v++) {            
             // render the normals
             Vector3d norm = facet.getVertices().get(facet.getCornerTable().getRow(v).getVertexIndex()).getNormal(); 
             if(norm != null) {
                 gl.glNormal3d(norm.x, norm.y, norm.z);
             }
             // render the vertices
-            Point3d vert = facet.getVertices().get(facet.getCornerTable().getRow(v).getVertexIndex()).getPosition(); 
+            Point3d vert = facet.getVertices().get(facet.getCornerTable().getRow(v).getVertexIndex()).getPosition();
             gl.glVertex3d(vert.x, vert.y, vert.z);
         }
         
         gl.glEnd();
     }
-    
 }
diff --git a/GUI/src/main/java/cz/fidentis/analyst/symmetry/SymmetryAction.java b/GUI/src/main/java/cz/fidentis/analyst/symmetry/SymmetryAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..f48946047f820e7b836aef2f1a040ee952cef520
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/symmetry/SymmetryAction.java
@@ -0,0 +1,74 @@
+package cz.fidentis.analyst.symmetry;
+
+import cz.fidentis.analyst.canvas.Canvas;
+import cz.fidentis.analyst.core.ControlPanelAction;
+import cz.fidentis.analyst.core.OutputWindow;
+import cz.fidentis.analyst.scene.DrawablePlane;
+import java.awt.event.ActionEvent;
+import javax.swing.JTabbedPane;
+import javax.swing.JToggleButton;
+
+/**
+ * Action listener for the manipulation with the symmetry plane.
+ * 
+ * @author Radek Oslejsek
+ */
+public class SymmetryAction extends ControlPanelAction {
+
+    private final SymmetryPanel controlPanel;
+
+    /**
+     * Constructor.
+     * 
+     * @param canvas OpenGL canvas
+     * @param topControlPanel Top component for placing control panels
+     */
+    public SymmetryAction(Canvas canvas, JTabbedPane topControlPanel) {
+        super(canvas, topControlPanel);
+        this.controlPanel = new SymmetryPanel(this);
+    }
+    
+    @Override
+    public void actionPerformed(ActionEvent ae) {
+        String action = ae.getActionCommand();
+        DrawablePlane plane;
+        
+        switch (action) {
+            case SymmetryPanel.ACTION_COMMAND_SHOW_HIDE_PANEL:
+                hideShowPanelActionPerformed(ae, this.controlPanel);   
+                break;
+            case SymmetryPanel.ACTION_COMMAND_SHOW_HIDE_PLANE:
+                plane = getCanvas().getScene().getDrawableSymmetryPlane(0);
+                if (plane == null) { // no plane compute so far
+                    break;
+                }
+                if (((JToggleButton) ae.getSource()).isSelected()) {
+                    plane.show();
+                } else {
+                    plane.hide();
+                }
+                break;
+            case SymmetryPanel.ACTION_COMMAND_RECOMPUTE: 
+                recomputeSymmetryPlane();
+                break;  
+            default:
+                // to nothing
+        }
+        renderScene();
+    }
+    
+    private void recomputeSymmetryPlane() {
+        OutputWindow out = OutputWindow.measureTime();
+        
+        SymmetryEstimator se = new SymmetryEstimator(controlPanel.getSymmetryConfig());
+        getPrimaryDrawableFace().getModel().compute(se);
+        DrawablePlane plane = new DrawablePlane(se.getSymmetryPlaneMesh(), se.getSymmetryPlane());
+        getCanvas().getScene().setDrawableSymmetryPlane(0, plane);
+        
+        out.printDuration("Computation of Hausdorff distance for models with " 
+                + getPrimaryDrawableFace().getHumanFace().getMeshModel().getNumVertices()
+                + " vertices"
+        );
+    }
+    
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/symmetry/SymmetryPanel.java b/GUI/src/main/java/cz/fidentis/analyst/symmetry/SymmetryPanel.java
new file mode 100644
index 0000000000000000000000000000000000000000..647e4d909217937c0c14e06826dda0141cbde814
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/symmetry/SymmetryPanel.java
@@ -0,0 +1,295 @@
+package cz.fidentis.analyst.symmetry;
+
+import cz.fidentis.analyst.core.ControlPanel;
+import cz.fidentis.analyst.core.ControlPanelBuilder;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+import javax.swing.ImageIcon;
+import javax.swing.JCheckBox;
+import javax.swing.JOptionPane;
+import javax.swing.JTextField;
+import javax.swing.JToggleButton;
+import org.openide.windows.WindowManager;
+
+/**
+ * Control panel for symmetry plane.
+ *
+ * @author Natalia Bebjakova
+ * @author Radek Oslejsek
+ */
+public final class SymmetryPanel extends ControlPanel {
+    
+    /*
+     * Handled actions
+     */
+    public static final String ACTION_COMMAND_SHOW_HIDE_PLANE = "show-hide symmetry plane";
+    public static final String ACTION_COMMAND_RECOMPUTE = "recompute";
+    
+    /*
+     * Mandatory design elements
+     */
+    public static final String ICON = "symmetry28x28.png";
+    public static final String NAME = "Symmetry";
+    
+    /*
+     * Configuration of panel-specific GUI elements
+     */
+    public static final int MAX_SIGNIFICANT_POINTS = 500;
+    
+    /*
+     * Computational state
+     */
+    private final SymmetryConfig config = new SymmetryConfig();
+    private final SymmetryConfig tempConfig = new SymmetryConfig();
+    
+    /*
+     * GUI primitives holding the configuration state:
+     */
+    private JTextField signPointsTF = null;
+    private JTextField minCurvatureTF = null;
+    private JTextField minAngleCosTF = null;
+    private JTextField minNormAngleCosTF = null;
+    private JTextField maxRelDistTF = null;
+    private final JCheckBox averaging;
+    private final JCheckBox showSymmetryPlane;
+    
+    /**    
+     * Constructor.
+     * 
+     * @param action Action listener
+     */
+    public SymmetryPanel(ActionListener action) {
+        this.setName(NAME);
+        
+        ControlPanelBuilder builder = new ControlPanelBuilder(this);
+        
+        builder.addCaptionLine("Computation options:");
+        builder.addLine();
+        
+        signPointsTF = builder.addSliderOptionLine(
+                (ActionEvent e) -> { 
+                    showSignPointsHelp(); 
+                }, 
+                "Significant points", 
+                MAX_SIGNIFICANT_POINTS, 
+                (ActionEvent e) -> { 
+                    tempConfig.setSignificantPointCount(ControlPanelBuilder.parseLocaleInt(signPointsTF)); 
+                }
+        );
+        builder.addLine();
+        
+        minCurvatureTF = builder.addSliderOptionLine(
+                (ActionEvent e) -> { 
+                    showMinCurvHelp();     
+                }, 
+                "Min. curvature ratio", 
+                -1, 
+                (ActionEvent e) -> { 
+                    tempConfig.setMinCurvRatio(ControlPanelBuilder.parseLocaleDouble(minCurvatureTF));
+                });
+        builder.addLine();
+        
+        minAngleCosTF = builder.addSliderOptionLine(
+                (ActionEvent e) -> { 
+                    showMinAngleCosHelp();
+                }, 
+                "Min. angle cosine", 
+                -1, 
+                (ActionEvent e) -> { 
+                    tempConfig.setMinAngleCos(ControlPanelBuilder.parseLocaleDouble(minAngleCosTF));
+                });
+        builder.addLine();
+        
+        minNormAngleCosTF = builder.addSliderOptionLine(
+                (ActionEvent e) -> { 
+                    showNormalAngleHelp();     
+                }, 
+                "Normal angle", 
+                -1, 
+                (ActionEvent e) -> { 
+                    tempConfig.setMinNormAngleCos(ControlPanelBuilder.parseLocaleDouble(minNormAngleCosTF));
+                });
+        builder.addLine();
+        
+        maxRelDistTF = builder.addSliderOptionLine(
+                (ActionEvent e) -> { 
+                    showRelDistHelp();     
+                }, 
+                "Relative distance", 
+                -1, 
+                (ActionEvent e) -> { 
+                    tempConfig.setMaxRelDistance(ControlPanelBuilder.parseLocaleDouble(maxRelDistTF));
+                });
+        builder.addLine();
+        
+        averaging = builder.addCheckBoxOptionLine(
+                (ActionEvent e) -> { 
+                    showAveragingHelp(); 
+                }, 
+                "Averaging", 
+                config.isAveraging(), 
+                (ActionEvent e) -> { 
+                    tempConfig.setAveraging(((JToggleButton) e.getSource()).isSelected());
+                });
+        builder.addLine();
+        
+        builder.addCaptionLine("Visualization options:");
+        builder.addLine();
+        
+        showSymmetryPlane = builder.addCheckBoxOptionLine(
+                null, 
+                "Show symmetry plane", 
+                true, 
+                createListener(action, ACTION_COMMAND_SHOW_HIDE_PLANE)
+        ); 
+        builder.addLine();
+        
+        builder.addButtons(
+                List.of("Reset changes", 
+                        "Reset to defaults", 
+                        "(Re)compute"), 
+                List.of(
+                        (ActionEvent e) -> {
+                            setTempConfig(config);
+                        },
+                        (ActionEvent e) -> {
+                            setTempConfig(new SymmetryConfig());
+                        },
+                        (ActionEvent e) -> {
+                            config.copy(tempConfig); // confirm changes
+                            action.actionPerformed(new ActionEvent( // recompute
+                                    e.getSource(), 
+                                    ActionEvent.ACTION_PERFORMED, 
+                                    ACTION_COMMAND_RECOMPUTE)
+                            ); 
+                            action.actionPerformed(new ActionEvent( // and then show or keep hidden
+                                    showSymmetryPlane,
+                                    ActionEvent.ACTION_PERFORMED,
+                                    ACTION_COMMAND_SHOW_HIDE_PLANE)
+                            );
+                        }
+                )
+        );
+        
+        setTempConfig(new SymmetryConfig()); // intialize values;
+    }
+    
+    /**
+     * Returns symmetry plane configuration
+     * @return symmetry plane configuration
+     */
+    public SymmetryConfig getSymmetryConfig() {
+        return this.config;
+    }
+    
+    @Override
+    public ImageIcon getIcon() {
+        return getStaticIcon();
+    }
+    
+    /**
+     * Static implementation of the {@link #getIcon()} method.
+     * 
+     * @return Control panel icon
+     */
+    public static ImageIcon getStaticIcon() {
+        return new ImageIcon(SymmetryPanel.class.getClassLoader().getResource("/" + ICON));
+    }
+    
+    private void setTempConfig(SymmetryConfig config) {
+        // update input fields
+        this.signPointsTF.setText(ControlPanelBuilder.intToStringLocale(config.getSignificantPointCount()));
+        this.minCurvatureTF.setText(ControlPanelBuilder.doubleToStringLocale(config.getMinCurvRatio()));
+        this.minAngleCosTF.setText(ControlPanelBuilder.doubleToStringLocale(config.getMinAngleCos()));
+        this.minNormAngleCosTF.setText(ControlPanelBuilder.doubleToStringLocale(config.getMinNormAngleCos()));
+        this.maxRelDistTF.setText(ControlPanelBuilder.doubleToStringLocale(config.getMaxRelDistance()));
+        this.averaging.setSelected(config.isAveraging());
+        
+        // fire changes (update sliders)
+        this.signPointsTF.postActionEvent();
+        this.minCurvatureTF.postActionEvent();
+        this.minAngleCosTF.postActionEvent();
+        this.minNormAngleCosTF.postActionEvent();
+        this.maxRelDistTF.postActionEvent();
+        
+        // update config
+        tempConfig.copy(config);
+    }
+    
+    private void showSignPointsHelp() {
+        JOptionPane.showMessageDialog(WindowManager.getDefault().findTopComponent("SingleFaceTab"),
+                "Entered number represents amount of points of the mesh that are taken into account" + System.lineSeparator()
+                        + "while counting the plane of approximate symmetry." + System.lineSeparator() 
+                        + System.lineSeparator()
+                        + "Higher number → longer calculation, possibly more accurate result." + System.lineSeparator()
+                        + "Lower number → shorter calculation, possibly less accurate result.", 
+                "Significant points",
+                0, 
+                new ImageIcon(getClass().getResource("/points.png"))
+        );
+                
+    }
+     
+    private void showMinAngleCosHelp() {
+        JOptionPane.showMessageDialog(WindowManager.getDefault().findTopComponent("SingleFaceTab"),
+                "Entered number represents how large the angle between normal vector of candidate plane and the vector" + System.lineSeparator()
+                        + "of two vertices can be to take into account these vertices while counting the approximate symmetry."  + System.lineSeparator()
+                        + System.lineSeparator()
+                        + "Higher number → fewer pairs of vertices satisfy the criterion → shorter calculation, possibly less accurate result." + System.lineSeparator()
+                        + "Lower number → more pairs of vertices satisfy the criterion → longer calculation, possibly more accurate result.",
+                "Minimum angle",
+                0, 
+                new ImageIcon(getClass().getResource("/angle.png"))
+        );
+    }
+    
+    private void showNormalAngleHelp() {                                             
+        JOptionPane.showMessageDialog(WindowManager.getDefault().findTopComponent("SingleFaceTab"),
+                "Entered number represents how large the angle between normal vector of candidate plane and vector" + System.lineSeparator()
+                        + "from subtraction of normal vectors of two vertices can be to take into account these vertices while counting the approximate symmetry." + System.lineSeparator()
+                         + System.lineSeparator()
+                        + "Higher number → fewer pairs of vertices satisfy the criterion → shorter calculation, possibly less accurate result." + System.lineSeparator()
+                        + "Lower number → more pairs of vertices satisfy the criterion → longer calculation, possibly more accurate result.",
+                "Minimum normal angle",
+                0, 
+                new ImageIcon(getClass().getResource("/angle.png"))
+        );
+    }   
+    
+    private void showMinCurvHelp() {                                         
+        JOptionPane.showMessageDialog(WindowManager.getDefault().findTopComponent("SingleFaceTab"),
+                "Entered number represents how similar the curvature in two vertices must be" + System.lineSeparator()
+                        + "to take into account these vertices while counting the plane of approximate symmetry." + System.lineSeparator()
+                        + "The higher the number is the more similar they must be." + System.lineSeparator()
+                        + System.lineSeparator()
+                        + "Higher number → fewer pairs of vertices satisfy the criterion → shorter calculation, possibly less accurate result." + System.lineSeparator()
+                        + "Lower number → more pairs of vertices satisfy the criterion → longer calculation, possibly more accurate result.",
+                "Minimum curvature ratio",
+                0, 
+                new ImageIcon(getClass().getResource("/curvature.png"))
+        );
+    }                                        
+
+    private void showRelDistHelp() {
+        JOptionPane.showMessageDialog(WindowManager.getDefault().findTopComponent("SingleFaceTab"),
+                "Entered number represents how far middle point of two vertices can be from candidate plane of symmetry" + System.lineSeparator()
+                        + "to give this plane vote. Plane with highest number of votes is plane of approximate symmetry." + System.lineSeparator()
+                        + System.lineSeparator()
+                        + "Higher number → more pairs of vertices satisfy the criterion → longer calculation, possibly more accurate result." + System.lineSeparator()
+                        + "Lower number → fewer pairs of vertices satisfy the criterion → shorter calculation, possibly less accurate result.",
+                "Maximum relative distance from plane",
+                0, 
+                new ImageIcon(getClass().getResource("/distance.png"))
+        );
+    }
+    
+    private void showAveragingHelp() {
+        JOptionPane.showMessageDialog(WindowManager.getDefault().findTopComponent("SingleFaceTab"),
+                "TO DO",
+                "TO DO",
+                0, 
+                new ImageIcon(getClass().getResource("/distance.png"))
+        );
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/tests/BatchTests.java b/GUI/src/main/java/cz/fidentis/analyst/tests/BatchTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..8b87528828229846ec881dbdb08c1f70cd68cb8d
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/tests/BatchTests.java
@@ -0,0 +1,96 @@
+package cz.fidentis.analyst.tests;
+
+import cz.fidentis.analyst.BatchProcessor;
+import cz.fidentis.analyst.face.HumanFace;
+import cz.fidentis.analyst.face.HumanFaceFactory;
+import cz.fidentis.analyst.icp.NoUndersampling;
+import cz.fidentis.analyst.icp.UndersamplingStrategy;
+import cz.fidentis.analyst.kdtree.KdTree;
+import cz.fidentis.analyst.mesh.io.MeshObjExporter;
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A class for testing the efficiency of batch processing algorithms.
+ * 
+ * @author Radek Oslejsek
+ */
+public class BatchTests {
+    
+    private static final String DATA_DIR = "../../analyst-data/multi-scan-models-anonymized-fixed/";
+    private static final String PRIMARY_FACE_PATH = DATA_DIR + "/average-boy-17-20/average_boy_17-20.obj";
+    //private static final String PRIMARY_FACE_PATH = dataDir + "/average-girl-17-20/average_girl_17-20.obj";
+    //private static final String PRIMARY_FACE_PATH = "../../analyst-data/basic-models/02.obj";
+    //private static final String PRIMARY_FACE_PATH = dataDir + "/07/00007_01_ECA.obj";
+    private static final String TEMPLATE_FACE_PATH = DATA_DIR + "template.obj";
+    
+    /**
+     * Main method 
+     * @param args Input arguments 
+     * @throws IOException on IO error
+     */
+    public static void main(String[] args) throws IOException, ClassNotFoundException, Exception {
+        BatchProcessor batch = new BatchProcessor(200); // the best is 500?
+        long startTime, endTime;
+        
+        List<String> faceIDs;
+        String primaryFaceId = HumanFaceFactory.instance().loadFace(new File(PRIMARY_FACE_PATH));
+        HumanFace primaryFace = HumanFaceFactory.instance().getFace(primaryFaceId);
+        KdTree primaryFacekdTree = primaryFace.computeKdTree(false);
+        
+        //////////////////////////////////////////////
+        System.out.println();
+        System.out.println("Loading files:");
+        startTime = System.currentTimeMillis();
+        faceIDs = batch.readFaces(DATA_DIR);
+        endTime = System.currentTimeMillis();
+        printTimes(startTime, endTime, faceIDs.size());
+        System.out.println(faceIDs.size() + "\t\t Number of files");
+        System.out.println(HumanFaceFactory.instance());
+        
+        //////////////////////////////////////////////
+        System.out.println();
+        System.out.println("Computation of symmetry planes:");
+        startTime = System.currentTimeMillis();
+        batch.computeSymmetryPlanes(faceIDs);
+        batch.computeSymmetryPlanes(Collections.singletonList(primaryFaceId));
+        endTime = System.currentTimeMillis();
+        printTimes(startTime, endTime, faceIDs.size());
+        
+        //////////////////////////////////////////////
+        UndersamplingStrategy strategy = new NoUndersampling();
+        //UndersamplingStrategy strategy = new RandomStrategy(0.5);
+        System.out.println();
+        System.out.println("ICP registration with " + strategy + ":");
+        startTime = System.currentTimeMillis();
+        batch.superimposeOnPrimaryFace(primaryFaceId, faceIDs, 10, 0.05, strategy);
+        endTime = System.currentTimeMillis();
+        printTimes(startTime, endTime, faceIDs.size());
+        System.out.printf("%.2f \t\t Avg number of iterations", batch.getAvgNumIcpIterations());
+        System.out.println();
+        
+        //////////////////////////////////////////////
+        System.out.println();
+        System.out.println("Computation of averaged template face:");
+        startTime = System.currentTimeMillis();
+        batch.computeTemplateFace(primaryFaceId, faceIDs);
+        endTime = System.currentTimeMillis();
+        printTimes(startTime, endTime, faceIDs.size());
+        System.out.println("Writing average template to " + TEMPLATE_FACE_PATH);
+        MeshObjExporter exp = new MeshObjExporter(batch.getAvgTemplateFace().getMeshModel());
+        exp.exportModelToObj(new File(TEMPLATE_FACE_PATH));
+    }
+    
+    private static void printTimes(long startTime, long endTime, int numFaces) {
+        double timeDist = endTime - startTime;
+        double avgTime = (timeDist/numFaces)/1000.0;
+        System.out.printf("%.2f sec \t Overall time", timeDist/1000.0);
+        System.out.println();
+        System.out.printf("%.2f sec \t Average time", avgTime);
+        System.out.println();
+        System.out.printf("%.2f min \t Estimated time for 500 faces", (avgTime*500)/60);
+        System.out.println();
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java b/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java
index 59a693005f81601459f3cdf22b41b52a873edc64..3d3fc9a06236ade1b8fc77c24f063a650fe6158c 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java
@@ -1,19 +1,15 @@
 package cz.fidentis.analyst.tests;
 
 import cz.fidentis.analyst.face.HumanFace;
-import cz.fidentis.analyst.face.HumanFacePrivilegedCache;
-import cz.fidentis.analyst.icp.Icp;
 import cz.fidentis.analyst.kdtree.KdTree;
 import cz.fidentis.analyst.mesh.core.MeshFacet;
-import cz.fidentis.analyst.symmetry.Config;
+import cz.fidentis.analyst.symmetry.SymmetryConfig;
 import cz.fidentis.analyst.symmetry.Plane;
-import cz.fidentis.analyst.symmetry.SignificantPoints;
 import cz.fidentis.analyst.symmetry.SymmetryEstimator;
 import cz.fidentis.analyst.visitors.mesh.HausdorffDistance;
 import cz.fidentis.analyst.visitors.mesh.HausdorffDistance.Strategy;
 import java.io.File;
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -40,17 +36,14 @@ public class EfficiencyTests {
      */
     public static void main(String[] args) throws IOException, ClassNotFoundException, Exception {
         face1 = printFaceLoad(faceFile4);
-        face2 = printFaceLoad(faceFile4);
+        face2 = printFaceLoad(faceFile2);
         
         face1.getMeshModel().simplifyModel();
         face2.getMeshModel().simplifyModel();
         
-        for (int i = 0; i < 10; i++) {
-            //HumanFace face = HumanFacePrivilegedCache.instance().loadFace(faceFile4);
-            //face.getMeshModel().simplifyModel();
-            //System.out.println(i+".\t" + HumanFacePrivilegedCache.instance());
-            printFaceDump(face1);
-        }
+        //for (int i = 0; i < 10; i++) {
+        //    printFaceDump(face1);
+        //}
         
         boolean relativeDist = false;
         boolean printDetails = false;
@@ -58,15 +51,11 @@ public class EfficiencyTests {
         
         //face1.getMeshModel().compute(new GaussianCurvature()); // initialize everything, then measure
         
-        System.out.println("ICP:");
-        Icp icp = new Icp();
-        icp.getTransformedFacet(face1.getMeshModel().getFacets().get(0), face2.getMeshModel().getFacets().get(0));
-        
         System.out.println("Symmetry plane calculation:");
-        printSymmetryPlane(face1, true, SignificantPoints.CurvatureAlg.MEAN);
-        printSymmetryPlane(face1, true, SignificantPoints.CurvatureAlg.GAUSSIAN);
-        printSymmetryPlane(face1, false, SignificantPoints.CurvatureAlg.MEAN);
-        printSymmetryPlane(face1, false, SignificantPoints.CurvatureAlg.GAUSSIAN);
+        //printSymmetryPlane(face1, true, CurvatureAlg.MEAN);
+        //printSymmetryPlane(face1, true, CurvatureAlg.GAUSSIAN);
+        //printSymmetryPlane(face1, false, CurvatureAlg.MEAN);
+        //printSymmetryPlane(face1, false, CurvatureAlg.GAUSSIAN);
         
         System.out.println();
         System.out.println(measureKdTreeCreation(face1) + "\tmsec:\tKd-tree creation of first face");
@@ -113,9 +102,9 @@ public class EfficiencyTests {
         return System.currentTimeMillis() - startTime;
     }
     
-    private static void printSymmetryPlane(HumanFace face, boolean concurrently, SignificantPoints.CurvatureAlg curvatureAlg) {
+    private static void printSymmetryPlane(HumanFace face, boolean concurrently) {
         long startTime = System.currentTimeMillis();
-        SymmetryEstimator est = new SymmetryEstimator(Config.getDefault(), curvatureAlg);
+        SymmetryEstimator est = new SymmetryEstimator(new SymmetryConfig());
         face.getMeshModel().compute(est, false);
         Plane plane = est.getSymmetryPlane(concurrently);
         long endTime =  System.currentTimeMillis();
@@ -124,7 +113,7 @@ public class EfficiencyTests {
                 (endTime-startTime) + 
                 "\tmsec: " + 
                 "\t" + (concurrently ? "concurrently" : "sequentially") +
-                "\t" + curvatureAlg + " curvature    " +
+//                "\t" + curvatureAlg + " curvature    " +
                 "\t" + plane.getNormal() + ", " + plane.getDistance()
         );
     }
@@ -149,9 +138,4 @@ public class EfficiencyTests {
         return face;
     }
     
-    public static String formatSize(long v) {
-        if (v < 1024) return v + " B";
-        int z = (63 - Long.numberOfLeadingZeros(v)) / 10;
-        return String.format("%.1f %sB", (double)v / (1L << (z*10)), " KMGTPE".charAt(z));
-    }
 }
diff --git a/GUI/src/main/java/cz/fidentis/analyst/tests/HeatMapsTestApp.java b/GUI/src/main/java/cz/fidentis/analyst/tests/HeatMapsTestApp.java
deleted file mode 100644
index d1a22328ec7d4579e6d46c4a90021d4ae0d01645..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/tests/HeatMapsTestApp.java
+++ /dev/null
@@ -1,388 +0,0 @@
-package cz.fidentis.analyst.tests;
-
-import com.jogamp.opengl.GL;
-import com.jogamp.opengl.GL2;
-import com.jogamp.opengl.GLAutoDrawable;
-import cz.fidentis.analyst.face.HumanFace;
-import cz.fidentis.analyst.mesh.core.MeshFacet;
-import cz.fidentis.analyst.mesh.core.MeshModel;
-
-import javax.vecmath.Vector3d;
-import java.util.List;
-import java.util.Map;
-
-import static com.jogamp.opengl.GL.GL_FRONT_AND_BACK;
-import static com.jogamp.opengl.GL.GL_VIEWPORT;
-import static com.jogamp.opengl.GL2GL3.GL_FILL;
-import static com.jogamp.opengl.GL2GL3.GL_LINE;
-import static com.jogamp.opengl.fixedfunc.GLMatrixFunc.GL_MODELVIEW_MATRIX;
-import static com.jogamp.opengl.fixedfunc.GLMatrixFunc.GL_PROJECTION_MATRIX;
-import cz.fidentis.analyst.gui.Canvas;
-import cz.fidentis.analyst.gui.GeneralGLEventListener;
-import cz.fidentis.analyst.mesh.core.MeshPoint;
-import cz.fidentis.analyst.visitors.mesh.Curvature;
-import cz.fidentis.analyst.visitors.mesh.HausdorffDistance;
-import cz.fidentis.analyst.visitors.mesh.HausdorffDistance.Strategy;
-import java.awt.Color;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.io.File;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
-import javax.swing.JButton;
-import javax.swing.JFrame;
-import javax.vecmath.Point3d;
-import org.openide.util.Exceptions;
-
-/**
- * Testing application displaying different heat maps in 3D.
- * 
- * @author Daniel Sokol
- * @author Radek Oslejsek
- */
-public class HeatMapsTestApp extends GeneralGLEventListener {
-    
-    private static final JFrame TEST_FRAME = new JFrame();
-    
-    private Map<MeshFacet, List<Double>> values;
-    private final Color minColor = Color.BLUE;
-    private final Color maxColor = Color.RED;
-    
-    private double minDistance;
-    private double maxDistance;
-
-    
-    /**
-     * Constructor.
-     * @param canvas Canvas
-     */
-    public HeatMapsTestApp(Canvas canvas) {
-        super(canvas);
-    }
-    
-    /**
-     * Main method 
-     * @param args Input arguments 
-     * @throws IOException on IO error
-     */
-    public static void main(String[] args) {
-        //Declaration
-        JButton gaussButton = new JButton("Show Gaussian curvature");
-        JButton meanButton = new JButton("Show mean curvature");
-        JButton maxButton = new JButton("Show maximum principal curvature");
-        JButton minButton = new JButton("Show minimum principal curvature");
-        JButton hdButton1 = new JButton("Show Hausdorff distance to average boy - p2p abosult");
-        JButton hdButton2 = new JButton("Show Hausdorff distance to average boy - p2p relative");
-
-        Canvas testCanvas = new Canvas();
-        HeatMapsTestApp colorListener = new HeatMapsTestApp(testCanvas);
-        testCanvas.setListener(colorListener);
-        
-        gaussButton.addActionListener(e -> colorListener.computeGaussian());
-        meanButton.addActionListener(e -> colorListener.computeMean());
-        maxButton.addActionListener(e -> colorListener.computeMaxPrincipal());
-        minButton.addActionListener(e -> colorListener.computeMinPrincipal());
-        hdButton1.addActionListener(e -> colorListener.computeHausdorffDistanceP2pAbs());
-        hdButton2.addActionListener(e -> colorListener.computeHausdorffDistanceP2pRel());
-
-        TEST_FRAME.setLayout(new GridBagLayout());
-        TEST_FRAME.setVisible(true);
-        TEST_FRAME.setSize(1600, 900);
-
-        // Adding
-        GridBagConstraints c = new GridBagConstraints();
-        c.fill = GridBagConstraints.BOTH;
-        c.gridx = 0;
-        c.gridy = 0;
-        c.weighty = 1;
-        c.weightx = 1;
-
-        c.gridheight = 6;
-        c.gridwidth = 4;
-        c.weightx = 4;
-        TEST_FRAME.add(testCanvas, c);
-        c.gridheight = 1;
-        c.gridwidth = 2;
-        c.gridx = 4;
-        c.weightx = 2;
-        //testFrame.add(addButton, c);
-        c.gridy = 1;
-        TEST_FRAME.add(gaussButton, c);
-        c.gridy = 2;
-        TEST_FRAME.add(meanButton, c);
-        c.gridy = 3;
-        TEST_FRAME.add(maxButton, c);
-        c.gridy = 4;
-        TEST_FRAME.add(minButton, c);
-        c.gridy = 5;
-        TEST_FRAME.add(hdButton1, c);
-        c.gridy = 6;
-        TEST_FRAME.add(hdButton2, c);
-    }
-    
-    @Override
-    public void setModel(MeshModel model) {
-        super.setModel(model);
-        
-        System.err.println();
-        System.err.println("MODEL: " + getModel());
-        
-        Set<Point3d> unique = new HashSet<>();
-        for (MeshPoint p: getModel().getFacets().get(0).getVertices()) {
-            unique.add(p.getPosition());
-        }
-        System.out.println("UNIQUE VERTICES: " + unique.size());
-        /*
-        for (Vector3d v: unique2) {
-            for (MeshPoint p: uniqueVerts) {
-                if (v.equals(p.getPosition())) {
-                    System.out.println(p);
-                }
-            }
-            System.out.println("----------------");
-        }
-        */
-    }
-
-    /**
-     * Computes curvature
-     */
-    public void computeGaussian() {
-        if (this.getModel() == null) {
-            return;
-        }
-        
-        long startTime = System.currentTimeMillis();
-        Curvature vis = new Curvature();
-        this.getModel().compute(vis);
-        values = vis.getGaussianCurvatures();
-        long duration =  System.currentTimeMillis() - startTime;
-        System.err.println(duration + "\tmsec: Gaussian curvature");
-        
-        minDistance = -0.02;
-        maxDistance = 0.008;
-    }
-    
-    /**
-     * Computes curvature
-     */
-    public void computeMean() {
-        if (this.getModel() == null) {
-            return;
-        }
-        
-        long startTime = System.currentTimeMillis();
-        Curvature vis = new Curvature();
-        this.getModel().compute(vis);
-        values = vis.getMeanCurvatures();
-        long duration =  System.currentTimeMillis() - startTime;
-        System.err.println(duration + "\tmsec: Mean curvature");
-        
-        minDistance = -0.001;
-        maxDistance = 0.1;
-    }
-    
-    /**
-     * Computes curvature
-     */
-    public void computeMinPrincipal() {
-        if (this.getModel() == null) {
-            return;
-        }
-        
-        long startTime = System.currentTimeMillis();
-        Curvature vis = new Curvature();
-        this.getModel().compute(vis);
-        values = vis.getMinPrincipalCurvatures();
-        long duration =  System.currentTimeMillis() - startTime;
-        System.err.println(duration + "\tmsec: Minimum principal curvature");
-        
-        minDistance = -0.05;
-        maxDistance = 0.03;
-    }
-    
-    /**
-     * Computes curvature
-     */
-    public void computeMaxPrincipal() {
-        if (this.getModel() == null) {
-            return;
-        }
-        
-        long startTime = System.currentTimeMillis();
-        Curvature vis = new Curvature();
-        this.getModel().compute(vis);
-        values = vis.getMaxPrincipalCurvatures();
-        long duration =  System.currentTimeMillis() - startTime;
-        System.err.println(duration + "\tmsec: Maximum principal curvature");
-        
-        minDistance = -0.02;
-        maxDistance = 0.25;
-    }
-    
-    /**
-     * Computes absolute HD
-     */
-    public void computeHausdorffDistanceP2pAbs() {
-        if (this.getModel() == null) {
-            return;
-        }
-        try {
-            HumanFace boy = new HumanFace(new File("src/test/resources/cz/fidentis/analyst/average_boy_17-20.obj"));
-            long startTime = System.currentTimeMillis();
-            HausdorffDistance vis = new HausdorffDistance(boy.getMeshModel(), Strategy.POINT_TO_POINT, false, true);
-            this.getModel().compute(vis);
-            values = vis.getDistances();
-            long duration =  System.currentTimeMillis() - startTime;
-            System.err.println(duration + "\tmsec: Hausdorff distance " + vis.getStrategy() + " " + (vis.relativeDistance() ? "RELATIVE" : "ABSOLUTE"));
-        } catch (IOException ex) {
-            Exceptions.printStackTrace(ex);
-        }
-        List<Double> distanceList = values.get(getModel().getFacets().get(0));
-        minDistance = distanceList.stream().mapToDouble(Double::doubleValue).min().getAsDouble();
-        maxDistance = distanceList.stream().mapToDouble(Double::doubleValue).max().getAsDouble();
-    }
-    
-    /**
-     * Computes relative HD
-     */
-    public void computeHausdorffDistanceP2pRel() {
-        if (this.getModel() == null) {
-            return;
-        }
-        try {
-            HumanFace boy = new HumanFace(new File("src/test/resources/cz/fidentis/analyst/average_boy_17-20.obj"));
-            long startTime = System.currentTimeMillis();
-            HausdorffDistance vis = new HausdorffDistance(boy.getMeshModel(), Strategy.POINT_TO_POINT, true, true);
-            this.getModel().compute(vis);
-            values = vis.getDistances();
-            long duration =  System.currentTimeMillis() - startTime;
-            System.err.println(duration + "\tmsec: Hausdorff distance " + vis.getStrategy() + " " + (vis.relativeDistance() ? "RELATIVE" : "ABSOLUTE"));
-        } catch (IOException ex) {
-            Exceptions.printStackTrace(ex);
-        }
-        List<Double> distanceList = values.get(getModel().getFacets().get(0));
-        minDistance = distanceList.stream().mapToDouble(Double::doubleValue).min().getAsDouble();
-        maxDistance = distanceList.stream().mapToDouble(Double::doubleValue).max().getAsDouble();
-    }
-    
-    @Override
-    public void display(GLAutoDrawable glad) {
-        wireModel = glCanvas.getDrawWired(); // is wire-frame or not
-
-        if (whiteBackround) {
-            gl.glClearColor(0.9f, 0.9f, 0.9f, 0);
-        } else {
-            gl.glClearColor(0.25f, 0.25f, 0.25f, 0);
-        }
-        // background for GLCanvas
-        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
-        gl.glLoadIdentity();
-
-        // sets model to proper position
-        glu.gluLookAt(xCameraPosition, yCameraPosition, zCameraPosition, xCenter, yCenter, zCenter, xUpPosition, yUpPosition, zUpPosition);
-
-        gl.glShadeModel(GL2.GL_SMOOTH);
-        gl.glGetIntegerv(GL_VIEWPORT, viewport, 0);
-        gl.glGetFloatv(GL_MODELVIEW_MATRIX, modelViewMatrix, 0);
-        gl.glGetFloatv(GL_PROJECTION_MATRIX, projectionMatrix, 0);
-
-        //if there is any model, draw
-        if (values != null) {
-            drawHeatmap(this.getModel());
-        } else if (getModel() != null) {
-            if (wireModel) {
-                gl.glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //drawn as wire-frame
-            } else {
-                gl.glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // drawn as full traingles
-            }
-
-            drawWithoutTextures(getModel());
-        }
-
-        gl.glFlush();
-    }
-
-    protected void drawHeatmap(MeshModel model) {
-        for (int i = 0; i < model.getFacets().size(); i++) {
-            renderFaceWithHeatmap(model.getFacets().get(i), values.get(model.getFacets().get(i)), minDistance, maxDistance);
-        }
-    }
-
-    protected void renderFaceWithHeatmap(MeshFacet facet, List<Double> distancesList, Double minDistance, Double maxDistance) {
-        gl.glBegin(GL2.GL_TRIANGLES); //vertices are rendered as triangles
-
-        // get the normal and tex coords indicies for face i
-        for (int v = 0; v < facet.getCornerTable().getSize(); v++) {
-            // render the normals
-            Vector3d norm = facet.getVertices().get(facet.getCornerTable().getRow(v).getVertexIndex()).getNormal();
-            if (norm != null) {
-                gl.glNormal3d(norm.x, norm.y, norm.z);
-            }
-            // render the vertices
-            Point3d vert = facet.getVertices().get(facet.getCornerTable().getRow(v).getVertexIndex()).getPosition();
-            //get color of vertex
-            Color c = getColor(distancesList.get(facet.getCornerTable().getRow(v).getVertexIndex()), minDistance, maxDistance);
-            gl.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_DIFFUSE, c.getComponents(null), 0);
-
-            gl.glVertex3d(vert.x, vert.y, vert.z);
-        }
-        gl.glEnd();
-        gl.glPopAttrib();
-    }
-
-    protected Color getColor(Double currentDistance, Double minDistance, Double maxDistance) {
-        double currentParameter = ((currentDistance - minDistance) / (maxDistance - minDistance));
-        
-        if (currentDistance > maxDistance) {
-            currentParameter = 1.0;
-        } else if (currentDistance < minDistance || (maxDistance - minDistance) == 0) { 
-            currentParameter = 0.0;
-        }
-        
-        float[] hsb1 = Color.RGBtoHSB(minColor.getRed(), minColor.getGreen(), minColor.getBlue(), null);
-        double h1 = hsb1[0];
-        double s1 = hsb1[1];
-        double b1 = hsb1[2];
-
-        float[] hsb2 = Color.RGBtoHSB(maxColor.getRed(), maxColor.getGreen(), maxColor.getBlue(), null);
-        double h2 = hsb2[0];
-        double s2 = hsb2[1];
-        double b2 = hsb2[2];
-
-        // determine clockwise and counter-clockwise distance between hues
-        double distCCW;
-        double distCW;
-
-        if (h1 >= h2) {
-            distCCW = h1 - h2;
-            distCW = 1 + h2 - h1;
-        } else {
-            distCCW = 1 + h1 - h2;
-            distCW = h2 - h1;
-        }
-
-        double hue;
-
-        if (distCW >= distCCW) {
-            hue = h1 + (distCW * currentParameter);
-        } else {
-            hue = h1 - (distCCW * currentParameter);
-        }
-
-        if (hue < 0) {
-            hue = 1 + hue;
-        }
-        if (hue > 1) {
-            hue = hue - 1;
-        }
-        
-        double saturation = (1 - currentParameter) * s1 + currentParameter * s2;
-        double brightness = (1 - currentParameter) * b1 + currentParameter * b2;
-
-        //System.out.println("AAA " + hue);
-
-        return Color.getHSBColor((float)hue, (float)saturation, (float)brightness);
-    }
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/tests/ICPTest.java b/GUI/src/main/java/cz/fidentis/analyst/tests/ICPTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..13fa88165cc21a36e28d0c07c150cf24cd2fb545
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/tests/ICPTest.java
@@ -0,0 +1,82 @@
+package cz.fidentis.analyst.tests;
+
+import cz.fidentis.analyst.face.HumanFace;
+import cz.fidentis.analyst.icp.IcpTransformer;
+import cz.fidentis.analyst.icp.NoUndersampling;
+import cz.fidentis.analyst.kdtree.KdTree;
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author Radek Oslejsek
+ */
+public class ICPTest {
+    
+    private static final String DATA_DIR = "../../analyst-data/multi-scan-models-anonymized-fixed/";
+    
+    private static String[] faceFiles = new String[] {
+        DATA_DIR + "02/00002_01_ECA.obj",
+        DATA_DIR + "04/00004_01_ECA.obj",
+        DATA_DIR + "06/00006_01_ECA.obj",
+        DATA_DIR + "07/00007_01_ECA.obj",
+        DATA_DIR + "10/00010_01_ECA.obj"
+    };
+    
+    private static int tests = 0;
+    private static int iters = 0;
+    
+    /**
+     * 
+     * @param args
+     * @throws IOException 
+     */
+    public static void main(String[] args) throws IOException {
+        long time = 0;
+        for (int i = 0; i < faceFiles.length; i++) {
+            time += test(i);
+        }
+        System.out.println("tests: " + tests);
+        System.out.println("iters: " + iters);
+        System.out.println("time: " + time + " ms");
+        System.out.println("AVG iters: " + ((double)iters/tests));
+        System.out.println("AVG time: " + ((double)time/tests) + " ms");
+    }
+    
+    /**
+     * 
+     * @param index
+     * @return
+     * @throws IOException 
+     */
+    public static long test(int index) throws IOException {
+        List<HumanFace> faces = new ArrayList<>();
+        for (int i = 0; i < faceFiles.length; i++) {
+            faces.add(new HumanFace(new File(faceFiles[i])));
+        }
+        HumanFace prim = faces.remove(index);
+        KdTree primKdTree = prim.computeKdTree(true);
+        
+        
+        System.out.println();
+        System.out.println(prim.getId());            
+        long startTime = System.currentTimeMillis();
+        for (HumanFace sec: faces) {
+            tests++;
+            IcpTransformer icpTransformer = new IcpTransformer(primKdTree, 10, false, 0.05, new NoUndersampling());
+            System.out.println(sec.getId());
+            sec.getMeshModel().compute(icpTransformer);
+            
+            for (MeshFacet f: icpTransformer.getTransformations().keySet()) {
+                //System.out.println("AAA"+icpTransformer.getTransformations().get(f).size());
+                iters += icpTransformer.getTransformations().get(f).size();
+            }
+        }
+        long endTime = System.currentTimeMillis();
+        
+        return endTime - startTime;
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/toolbar/FaceToFaceToolBar.java b/GUI/src/main/java/cz/fidentis/analyst/toolbar/FaceToFaceToolBar.java
new file mode 100644
index 0000000000000000000000000000000000000000..337bfc75fc04bfa128f9244e2fe78541f47b9598
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/toolbar/FaceToFaceToolBar.java
@@ -0,0 +1,36 @@
+package cz.fidentis.analyst.toolbar;
+
+import cz.fidentis.analyst.canvas.Canvas;
+import cz.fidentis.analyst.distance.DistanceAction;
+import cz.fidentis.analyst.registration.RegistrationAction;
+import javax.swing.JTabbedPane;
+
+/**
+ * A toolbar extension for the analysis of two faces.
+ * 
+ * @author Radek Oslejsek
+ * @author Daniel Schramm
+ */
+public class FaceToFaceToolBar extends RenderingToolBar {
+    
+    /**
+     * Constructor.
+     * 
+     * @param canvas Rendering canvas
+     * @param controlPanel The top component control panels
+     */
+    public FaceToFaceToolBar(Canvas canvas, JTabbedPane controlPanel) {
+        super(canvas);
+        addPrimaryFaceButton();
+        addSecondaryFaceButton();
+        
+        // (Re)render scene after all change listeners have been called
+        // (the first added listener is called last)
+        controlPanel.addChangeListener(e -> getCanvas().renderScene());
+        
+        // Add distance panel to the control panel
+        new DistanceAction(getCanvas(), controlPanel);
+        // Add registration panel to the control panel
+        new RegistrationAction(getCanvas(), controlPanel);
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/toolbar/RenderingModeAction.java b/GUI/src/main/java/cz/fidentis/analyst/toolbar/RenderingModeAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..3d4d2c473e9c09278a65d2766a90e13c39454860
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/toolbar/RenderingModeAction.java
@@ -0,0 +1,112 @@
+package cz.fidentis.analyst.toolbar;
+
+import com.jogamp.opengl.GL2;
+import cz.fidentis.analyst.canvas.Canvas;
+import static cz.fidentis.analyst.toolbar.RenderingToolBar.REFLECTIONS_COLOR;
+import cz.fidentis.analyst.scene.Drawable;
+import cz.fidentis.analyst.scene.DrawableFeaturePoints;
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+import javax.swing.AbstractAction;
+import javax.swing.JToggleButton;
+
+/**
+ * Action listener for changing OpenGL canvas rendering modes.
+ * 
+ * @author Radek Oslejsek
+ */
+public class RenderingModeAction extends AbstractAction {
+    
+    public static final String ACTION_COMMAND_SMOOTH_MODE = "smooth";
+    public static final String ACTION_COMMAND_WIREFRAME_MODE = "wireframe";
+    public static final String ACTION_COMMAND_POINT_CLOUD_MODE = "point cloud";
+    public static final String ACTION_COMMAND_BACKGROUND_CHANGE = "background";
+    public static final String ACTION_COMMAND_REFLECTIONS_ON_OFF = "reflections";
+    public static final String ACTION_COMMAND_SHOW_HIDE_PRIMARY_FACE = "primary face";
+    public static final String ACTION_COMMAND_SHOW_HIDE_SECONDARY_FACES = "secondary faces";
+    public static final String ACTION_COMMAND_SHOW_HIDE_FEATURE_POINTS = "feature points";
+    
+    
+    private final Canvas canvas;
+    private boolean showFPs = true;
+    
+    /**
+     * Constructor.
+     * @param canvas OpenGL canvas
+     */
+    public RenderingModeAction(Canvas canvas) {
+        this.canvas = canvas;
+    }
+    
+    @Override
+    public void actionPerformed(ActionEvent ae) {
+        String action = ae.getActionCommand();
+        switch (action) {
+            case ACTION_COMMAND_SMOOTH_MODE:
+                for (int i = 0; i < canvas.getScene().getNumFaces(); i++){
+                   canvas.getScene().getDrawableFace(i).setRenderMode(GL2.GL_FILL);
+                }
+                break;
+            case ACTION_COMMAND_WIREFRAME_MODE:
+                for (int i = 0; i < canvas.getScene().getNumFaces(); i++){
+                   canvas.getScene().getDrawableFace(i).setRenderMode(GL2.GL_LINE);
+                }
+                break;
+            case ACTION_COMMAND_POINT_CLOUD_MODE:
+                for (int i = 0; i < canvas.getScene().getNumFaces(); i++){
+                   canvas.getScene().getDrawableFace(i).setRenderMode(GL2.GL_POINT);
+                }
+                break;
+            case ACTION_COMMAND_BACKGROUND_CHANGE:
+                canvas.setDarkBackground(! ((JToggleButton) ae.getSource()).isSelected());
+               break;
+            case ACTION_COMMAND_REFLECTIONS_ON_OFF:
+                for (Drawable dm: canvas.getScene().getAllDrawables()) {
+                    if (((JToggleButton) ae.getSource()).isSelected()) {
+                        dm.setHighlights(REFLECTIONS_COLOR);
+                    } else {
+                        dm.setHighlights(Color.BLACK);
+                    }
+                }
+                break;
+            case ACTION_COMMAND_SHOW_HIDE_PRIMARY_FACE:
+                showHideFace(0, ((JToggleButton) ae.getSource()).isSelected());
+                break;
+            case ACTION_COMMAND_SHOW_HIDE_SECONDARY_FACES:
+                for (int i = 1; i < canvas.getScene().getNumFaces(); i++) {
+                    showHideFace(i, ((JToggleButton) ae.getSource()).isSelected());
+                }
+                break;
+            case ACTION_COMMAND_SHOW_HIDE_FEATURE_POINTS:
+                for (int i = 0; i < canvas.getScene().getNumFaces(); i++) {
+                    DrawableFeaturePoints fp = canvas.getScene().getDrawableFeaturePoints(i);
+                    if (((JToggleButton) ae.getSource()).isSelected()) { // show
+                        if (canvas.getScene().getDrawableFace(i).isShown() && fp != null) {
+                            fp.show();
+                        }
+                    } else if (fp != null) { // hide
+                        fp.hide();
+                    }
+                }
+                break;
+            default:
+                throw new UnsupportedOperationException(action);
+        }
+        canvas.renderScene();
+    }
+    
+    private void showHideFace(int i, boolean show) {
+        DrawableFeaturePoints fp = canvas.getScene().getDrawableFeaturePoints(i);
+        if (show) {
+            canvas.getScene().getDrawableFace(i).show();
+            if (showFPs) {
+                fp.show();
+            }
+        } else { //hide
+            canvas.getScene().getDrawableFace(i).hide();
+            if (fp != null) {
+                fp.hide();
+            }
+        }
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/toolbar/RenderingToolBar.java b/GUI/src/main/java/cz/fidentis/analyst/toolbar/RenderingToolBar.java
new file mode 100644
index 0000000000000000000000000000000000000000..3d8464133ce5bc2d9472f960efecf3462fca2d9a
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/toolbar/RenderingToolBar.java
@@ -0,0 +1,159 @@
+package cz.fidentis.analyst.toolbar;
+
+import cz.fidentis.analyst.canvas.Canvas;
+import java.awt.Color;
+import java.awt.GridLayout;
+import java.awt.image.BufferedImage;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.JToggleButton;
+import javax.swing.JToolBar;
+import org.openide.awt.DropDownButtonFactory;
+import org.openide.util.NbBundle;
+
+/**
+ * Generic rendering toolbar with common tools.
+ * 
+ * @author Radek Oslejsek
+ */
+public class RenderingToolBar extends JToolBar {
+    
+    public static final int WIDTH = 58;
+    public static final Color REFLECTIONS_COLOR = Color.DARK_GRAY;
+    
+    public static final String RENDERING_MODE_BUTTON_ICON = "wireframe28x28.png";
+    public static final String BACKGROUND_BUTTON_ICON = "background28x28.png";
+    public static final String REFLECTIONS_BUTTON_ICON = "reflections28x28.png";
+    public static final String SMOOT_BUTTON_ICON = "smooth-tri28x28.png";
+    public static final String WIREFRAME_BUTTON_ICON = "wireframe-tri28x28.png";
+    public static final String POINTS_BUTTON_ICON = "points-tri28x28.png";
+    public static final String PRIMARY_FACE_BUTTON_ICON = "primaryFace28x28.png";
+    public static final String SECONDARY_FACE_BUTTON_ICON = "secondaryFace28x28.png";
+    public static final String FEATURE_POINTS_BUTTON_ICON = "fps28x28.png";
+        
+    private final Canvas canvas;
+    
+    /**
+     * Constructor.
+     * @param canvas Rendering canvas
+     */
+    public RenderingToolBar(Canvas canvas) {
+        this.canvas = canvas;
+        initToolBar();
+        addRenderingModeButton();
+        addBackgroundButton();
+        addReflectionsButton();
+        addFeaturePointsButton();
+    }
+    
+    protected Canvas getCanvas() {
+        return canvas;
+    }
+    
+    private void initToolBar() {
+        setOrientation(javax.swing.SwingConstants.VERTICAL);
+        setRollover(true);
+        setFloatable(false);
+    }
+    
+    private void addRenderingModeButton() {
+        JPopupMenu popup = new JPopupMenu();
+        
+        JMenuItem menuItem1 = new JMenuItem(new RenderingModeAction(canvas));
+        JMenuItem menuItem2 = new JMenuItem(new RenderingModeAction(canvas));
+        JMenuItem menuItem3 = new JMenuItem(new RenderingModeAction(canvas));
+        
+        menuItem1.setActionCommand(RenderingModeAction.ACTION_COMMAND_SMOOTH_MODE);
+        menuItem2.setActionCommand(RenderingModeAction.ACTION_COMMAND_WIREFRAME_MODE);
+        menuItem3.setActionCommand(RenderingModeAction.ACTION_COMMAND_POINT_CLOUD_MODE);
+        
+        menuItem1.setIcon(new ImageIcon(getClass().getResource("/" + RenderingToolBar.SMOOT_BUTTON_ICON)));
+        menuItem2.setIcon(new ImageIcon(getClass().getResource("/" + RenderingToolBar.WIREFRAME_BUTTON_ICON)));
+        menuItem3.setIcon(new ImageIcon(getClass().getResource("/" + RenderingToolBar.POINTS_BUTTON_ICON)));
+
+        menuItem1.setToolTipText(NbBundle.getMessage(RenderingToolBar.class, "RenderingToolBar.smooth.text"));
+        menuItem2.setToolTipText(NbBundle.getMessage(RenderingToolBar.class, "RenderingToolBar.wireframe.text"));
+        menuItem3.setToolTipText(NbBundle.getMessage(RenderingToolBar.class, "RenderingToolBar.pointcloud.text"));
+        
+        popup.add(menuItem1);
+        popup.add(menuItem2);
+        popup.add(menuItem3);
+        
+        popup.setLayout(new GridLayout(1,0));
+
+        // The button that will display the default action and the
+        // dropdown arrow
+        JButton button = DropDownButtonFactory.createDropDownButton(
+                new ImageIcon(new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB)), 
+                popup);
+        
+        button.setIcon(new ImageIcon(getClass().getResource("/" + RenderingToolBar.RENDERING_MODE_BUTTON_ICON)));
+        
+        //Mnemonics.setLocalizedText(button, NbBundle.getMessage(RenderingToolBar.class, "RenderingToolBar.renderingmode.text"));
+        button.setToolTipText(NbBundle.getMessage(RenderingToolBar.class, "RenderingToolBar.renderingmode.text"));
+        button.setFocusable(false);
+        //button.setText(null);
+        add(button);
+    }
+    
+    private void addBackgroundButton() {
+        JToggleButton button = new JToggleButton();
+        button.addActionListener(new RenderingModeAction(canvas));
+        button.setActionCommand(RenderingModeAction.ACTION_COMMAND_BACKGROUND_CHANGE);
+        //button.setAction(new BackgroundAction(canvas));
+        button.setIcon(new ImageIcon(getClass().getResource("/" + RenderingToolBar.BACKGROUND_BUTTON_ICON)));
+        //Mnemonics.setLocalizedText(button, NbBundle.getMessage(RenderingToolBar.class, "RenderingToolBar.background.text"));
+        button.setFocusable(false);
+       // button.setText(null);
+        button.setToolTipText(NbBundle.getMessage(RenderingToolBar.class, "RenderingToolBar.background.text"));
+        add(button);
+    }
+    
+    private void addReflectionsButton() {
+        JToggleButton button = new JToggleButton();
+        button.addActionListener(new RenderingModeAction(canvas));
+        button.setActionCommand(RenderingModeAction.ACTION_COMMAND_REFLECTIONS_ON_OFF);
+        button.setIcon(new ImageIcon(getClass().getResource("/" + RenderingToolBar.REFLECTIONS_BUTTON_ICON)));
+        button.setFocusable(false);
+        button.setToolTipText(NbBundle.getMessage(RenderingToolBar.class, "RenderingToolBar.reflections.text"));
+        add(button);
+    }
+ 
+    protected void addPrimaryFaceButton() {
+        JToggleButton button = new JToggleButton();
+        button.addActionListener(new RenderingModeAction(canvas));
+        button.setActionCommand(RenderingModeAction.ACTION_COMMAND_SHOW_HIDE_PRIMARY_FACE);
+        button.setIcon(new ImageIcon(getClass().getResource("/" + RenderingToolBar.PRIMARY_FACE_BUTTON_ICON)));
+        button.setToolTipText(NbBundle.getMessage(RenderingToolBar.class, "RenderingToolBar.primaryface.text"));
+        //button.setText("P");
+        button.setSelected(true);
+        button.setFocusable(false);
+        add(button);
+    }
+
+    protected void addSecondaryFaceButton() {
+        JToggleButton button = new JToggleButton();
+        button.addActionListener(new RenderingModeAction(canvas));
+        button.setActionCommand(RenderingModeAction.ACTION_COMMAND_SHOW_HIDE_SECONDARY_FACES);
+        button.setIcon(new ImageIcon(getClass().getResource("/" + RenderingToolBar.SECONDARY_FACE_BUTTON_ICON)));
+        button.setToolTipText(NbBundle.getMessage(RenderingToolBar.class, "RenderingToolBar.secondaryfaces.text"));
+        //button.setText("S");
+        button.setSelected(true);
+        button.setFocusable(false);
+        add(button);
+    }
+    
+    protected void addFeaturePointsButton() {
+        JToggleButton button = new JToggleButton();
+        button.addActionListener(new RenderingModeAction(canvas));
+        button.setActionCommand(RenderingModeAction.ACTION_COMMAND_SHOW_HIDE_FEATURE_POINTS);
+        button.setIcon(new ImageIcon(getClass().getResource("/" + RenderingToolBar.FEATURE_POINTS_BUTTON_ICON)));
+        button.setToolTipText(NbBundle.getMessage(RenderingToolBar.class, "RenderingToolBar.featurepoints.text"));
+        //button.setText("FPs");
+        button.setSelected(true);
+        button.setFocusable(false);
+        add(button);
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/toolbar/SingleFaceToolBar.java b/GUI/src/main/java/cz/fidentis/analyst/toolbar/SingleFaceToolBar.java
new file mode 100644
index 0000000000000000000000000000000000000000..bf42881da1c3a1f1ed2a1a8733b145ccc7220405
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/toolbar/SingleFaceToolBar.java
@@ -0,0 +1,51 @@
+package cz.fidentis.analyst.toolbar;
+
+import cz.fidentis.analyst.symmetry.SymmetryAction;
+import cz.fidentis.analyst.canvas.Canvas;
+import cz.fidentis.analyst.core.ControlPanel;
+import cz.fidentis.analyst.curvature.CurvatureAction;
+import cz.fidentis.analyst.curvature.CurvaturePanel;
+import cz.fidentis.analyst.symmetry.SymmetryPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.JToggleButton;
+import org.openide.util.NbBundle;
+
+/**
+ * A toolbar extension for a single face analysis.
+ * 
+ * @author Radek Oslejsek
+ */
+public class SingleFaceToolBar extends RenderingToolBar {
+    
+    /**
+     * Constructor.
+     * 
+     * @param canvas Rendering canvas
+     * @param controlPanel The top component control panels
+     */
+    public SingleFaceToolBar(Canvas canvas, JTabbedPane controlPanel) {
+        super(canvas);
+        addPrimaryFaceButton();
+        addSeparator();
+        addSymmetryPlaneButton(controlPanel);
+        addCurvatureButton(controlPanel);
+    }
+    
+    private void addSymmetryPlaneButton(JTabbedPane controlPanel) {
+        JToggleButton button = new JToggleButton();
+        button.addActionListener(new SymmetryAction(getCanvas(), controlPanel));
+        button.setActionCommand(ControlPanel.ACTION_COMMAND_SHOW_HIDE_PANEL);
+        button.setIcon(SymmetryPanel.getStaticIcon());
+        button.setToolTipText(NbBundle.getMessage(RenderingToolBar.class, "SingleFaceToolBar.symmetry.text"));
+        add(button);
+    }
+    
+    private void addCurvatureButton(JTabbedPane topControlPanel) {
+        JToggleButton button = new JToggleButton();
+        button.addActionListener(new CurvatureAction(getCanvas(), topControlPanel));
+        button.setActionCommand(ControlPanel.ACTION_COMMAND_SHOW_HIDE_PANEL);
+        button.setIcon(CurvaturePanel.getStaticIcon());
+        button.setToolTipText(NbBundle.getMessage(RenderingToolBar.class, "SingleFaceToolBar.curvature.text"));
+        add(button);
+    }
+}
diff --git a/GUI/src/main/nbm/manifest.mf b/GUI/src/main/nbm/manifest.mf
index 1ecced8c8ac2d3294d5d12c1f6e499b26ff49456..cc2b72af9a038822de616d30687f90023e9bf397 100644
--- a/GUI/src/main/nbm/manifest.mf
+++ b/GUI/src/main/nbm/manifest.mf
@@ -1,6 +1,6 @@
-Manifest-Version: 1.0
-OpenIDE-Module: cz.fidentis.analyst.gui
-OpenIDE-Module-Install: cz/fidentis/analyst/gui/Installer.class
-OpenIDE-Module-Localizing-Bundle: cz/fidentis/analyst/gui/Bundle.properties
-OpenIDE-Module-Requires: org.openide.windows.WindowManager
-OpenIDE-Module-Specification-Version: 1.0
+Manifest-Version: 1.0
+OpenIDE-Module: cz.fidentis.analyst.gui
+OpenIDE-Module-Install: cz/fidentis/analyst/gui/Installer.class
+OpenIDE-Module-Localizing-Bundle: cz/fidentis/analyst/gui/Bundle.properties
+OpenIDE-Module-Requires: org.openide.windows.WindowManager
+OpenIDE-Module-Specification-Version: 1.0
diff --git a/GUI/src/main/resources/add-line.png b/GUI/src/main/resources/add-line.png
new file mode 100644
index 0000000000000000000000000000000000000000..4bdec92d9fd9f374c93dede972a7c3142473403b
Binary files /dev/null and b/GUI/src/main/resources/add-line.png differ
diff --git a/GUI/src/main/resources/arrow-left-s-line.png b/GUI/src/main/resources/arrow-left-s-line.png
new file mode 100644
index 0000000000000000000000000000000000000000..5e1b29e5762b88b84515113ea8fb0d1e61ecc0ea
Binary files /dev/null and b/GUI/src/main/resources/arrow-left-s-line.png differ
diff --git a/GUI/src/main/resources/arrow-right-s-line.png b/GUI/src/main/resources/arrow-right-s-line.png
new file mode 100644
index 0000000000000000000000000000000000000000..44e603c907aa6ea11ea5f54747c25ed011d2f6e3
Binary files /dev/null and b/GUI/src/main/resources/arrow-right-s-line.png differ
diff --git a/GUI/src/main/resources/background.png b/GUI/src/main/resources/background.png
new file mode 100644
index 0000000000000000000000000000000000000000..121165c953d3ad25ecd87f9da64fa47aa5f45fe2
Binary files /dev/null and b/GUI/src/main/resources/background.png differ
diff --git a/GUI/src/main/resources/background28x28.png b/GUI/src/main/resources/background28x28.png
new file mode 100644
index 0000000000000000000000000000000000000000..abbb76b9c4dcc8f1470e8bf733d8230add78f4e9
Binary files /dev/null and b/GUI/src/main/resources/background28x28.png differ
diff --git a/GUI/src/main/resources/curvature2.png b/GUI/src/main/resources/curvature2.png
new file mode 100644
index 0000000000000000000000000000000000000000..2dd071f0abf5f9c7d47f17c6f27d26dd8aa0ad5e
Binary files /dev/null and b/GUI/src/main/resources/curvature2.png differ
diff --git a/GUI/src/main/resources/curvature28x28.png b/GUI/src/main/resources/curvature28x28.png
new file mode 100644
index 0000000000000000000000000000000000000000..235784d198b3b5a302749cdf00f21d1ebee55a0e
Binary files /dev/null and b/GUI/src/main/resources/curvature28x28.png differ
diff --git a/GUI/src/main/resources/cz/fidentis/analyst/core/Bundle.properties b/GUI/src/main/resources/cz/fidentis/analyst/core/Bundle.properties
new file mode 100644
index 0000000000000000000000000000000000000000..4255855dbc53c394dc5f36136ce2dd288f4f51f2
--- /dev/null
+++ b/GUI/src/main/resources/cz/fidentis/analyst/core/Bundle.properties
@@ -0,0 +1,23 @@
+
+SingleFaceTab.jButton1.text=
+PostRegistrationCP.rotationXFTF.text=0
+PostRegistrationCP.translationZFTF.text=0
+PostRegistrationCP.translationYFTF.text=0
+PostRegistrationCP.translationXFTF.text=0
+PostRegistrationCP.scaleFTF.text=0
+PostRegistrationCP.rotationZFTF.text=0
+PostRegistrationCP.rotationYFTF.text=0
+PostRegistrationCP.jFormattedTextField1.text=jFormattedTextField1
+SingleFaceTab.jButton2.text=jButton2
+ProjectTopComp.addButton1.text=Add
+ProjectTopComp.inflateButton1.text=Inflate
+ProjectTopComp.deselectAllButton1.text=Deselect all
+ProjectTopComp.selectAllButton1.text=Select all
+ProjectTopComp.removeButton1.text=Remove
+ProjectTopComp.jTable1.columnModel.title0=Title 1
+ProjectTopComp.jTable1.columnModel.title3=Title 4
+ProjectTopComp.jTable1.columnModel.title1=Title 2
+ProjectTopComp.jTable1.columnModel.title0_1=Models
+ProjectTopComp.jTable1.columnModel.title1_1=
+ProjectTopComp.oneOnOneButton1.text=Open 1:1
+ProjectTopComp.analyseButton1.text=Analyse
diff --git a/GUI/src/main/resources/cz/fidentis/analyst/gui/Bundle.properties b/GUI/src/main/resources/cz/fidentis/analyst/gui/Bundle.properties
index 735652e9ef762861b6814501b1b928b18d771306..b10fefa922d775960e6d52bece6245fc074dfbe8 100644
--- a/GUI/src/main/resources/cz/fidentis/analyst/gui/Bundle.properties
+++ b/GUI/src/main/resources/cz/fidentis/analyst/gui/Bundle.properties
@@ -9,10 +9,91 @@ AligmentTopComponent.jLabel1.text=Registration
 AligmentTopComponent.jButton1.text=Register
 AligmentTopComponent.jLabel2.text=Primary color
 AligmentTopComponent.jLabel3.text=Secondary color
-ProjectTopComp.deselectAllButton1.text=Deselect all
-ProjectTopComp.selectAllButton1.text=Select all
-ProjectTopComp.removeButton1.text=Remove
-ProjectTopComp.addButton1.text=Add
-ProjectTopComp.analyzeButton1.text=Open 1:1
-ProjectTopComp.inflateButton1.text=Inflate
-ProjectTopComp.collapseButton1.text=Collapse
+PreRegistrationPanel.titleLabel.text=Registration setup
+PreRegistrationPanel.methodLabel.text=Method:
+PreRegistrationPanel.jLabel1.text=jLabel1
+PreRegistrationPanel.jLabel2.text=jLabel2
+PreRegistrationPanel.registerButton.text=Register
+PostRegistrationCP.shiftLabel.text=shift
+PostRegistrationCP.visualizationLabel.text=Visualization
+PostRegistrationCP.registrationAdjustmentLabel.text=Registration adjustment
+PostRegistrationCP.transformationLabel.text=Transformation
+PostRegistrationCP.featurePointsLabel.text=Feature points:
+PostRegistrationCP.resetAllButton.toolTipText=reset all transformations
+PostRegistrationCP.resetAllButton.text=reset all
+PostRegistrationCP.thersholdButton.text=thershold
+PostRegistrationCP.scaleButton.toolTipText=reset scale
+PostRegistrationCP.scaleButton.text=
+PostRegistrationCP.thersholdUpButton.text=
+PostRegistrationCP.scaleFTF.toolTipText=
+PostRegistrationCP.thresholdDownButton.text=
+PostRegistrationCP.scaleMinusButton.text=
+PostRegistrationCP.scalePlusButton.text=
+PostRegistrationCP.jLabel4.text=Scale:
+PostRegistrationCP.featurePointsButton.text=show
+PostRegistrationCP.backfaceButton.text=hide backface
+PostRegistrationCP.viewLabel.text=View:
+PostRegistrationCP.jLabel3.text=Rotation:
+PostRegistrationCP.frontButton.toolTipText=model front view
+PostRegistrationCP.frontButton.text=front
+PostRegistrationCP.rotationXFTF.toolTipText=
+PostRegistrationCP.profileButton.toolTipText=model profile view
+PostRegistrationCP.profileButton.text=side
+# To change this license header, choose License Headers in Project Properties.
+# To change this template file, choose Tools | Templates
+# and open the template in the editor.
+PostRegistrationCP.rightRotationXButton.text=
+PostRegistrationCP.leftRotationZButton.text=
+PostRegistrationCP.primaryFillRB.text=
+PostRegistrationCP.rightRotationYButton.text=
+PostRegistrationCP.secondaryLinesRB.text=
+PostRegistrationCP.rightRotationZButton.text=
+PostRegistrationCP.secondaryPointsRB.text=
+PostRegistrationCP.rotationButton.toolTipText=reset rotation
+PostRegistrationCP.rotationButton.text=
+PostRegistrationCP.rotatXLabel.text=X
+PostRegistrationCP.primaryPointsRB.text=
+PostRegistrationCP.secondaryFillRB.text=
+PostRegistrationCP.primaryLinesRB.text=
+PostRegistrationCP.primaryColorPanel.toolTipText=sets color of primary model
+PostRegistrationCP.rotatYLabel.text=Y
+PostRegistrationCP.secondaryColorPanel.toolTipText=sets color of secondary model
+PostRegistrationCP.rotatZLabel.text=Z
+PostRegistrationCP.transparencySlider.toolTipText=sets model transparency
+PostRegistrationCP.leftRotationXButton.text=
+PostRegistrationCP.secondaryLabel.toolTipText=
+PostRegistrationCP.secondaryLabel.text=secondary
+PostRegistrationCP.leftRotationYButton.text=
+PostRegistrationCP.primaryLabel.text=primary
+PostRegistrationCP.highlightsLabel.text=highlights
+PostRegistrationCP.leftTranslationZButton.text=
+PostRegistrationCP.primaryHighlightsCB.text=
+PostRegistrationCP.leftTranslationXButton.text=
+PostRegistrationCP.rightTranslationZButton.text=
+PostRegistrationCP.translYLabel.text=vertical
+PostRegistrationCP.translZLabel.text=front-back
+PostRegistrationCP.secondaryHighlightsCB.text=
+PostRegistrationCP.renderModeLabel.text=render mode
+PostRegistrationCP.fillLabel.text=fill
+PostRegistrationCP.colorButton.toolTipText=reset colors
+PostRegistrationCP.colorButton.text=color
+PostRegistrationCP.linesLabel.text=lines
+PostRegistrationCP.translXLabel.text=horizontal
+PostRegistrationCP.transparencyButton.toolTipText=reset transparency
+PostRegistrationCP.transparencyButton.text=opacity
+PostRegistrationCP.rightTranslationYButton.text=
+PostRegistrationCP.pointsLabel.text=points
+PostRegistrationCP.modelLabel.text=Model:
+PostRegistrationCP.leftTranslationYButton.text=
+PostRegistrationCP.translationXFTF.toolTipText=
+PostRegistrationCP.rightTranslationXButton.text=
+PostRegistrationCP.jLabel2.text=Translation:
+PostRegistrationCP.translationButton.toolTipText=reset translation
+PostRegistrationCP.translationButton.text=
+PostRegistrationCP.applyButton.toolTipText=apply transformations
+PostRegistrationCP.applyButton.text=Apply changes
+PostRegistrationCP.highShiftRB.toolTipText=set high shifting amount
+PostRegistrationCP.highShiftRB.text=high
+PostRegistrationCP.lowShiftRB.toolTipText=set low shifting amount
+PostRegistrationCP.lowShiftRB.text=low
+PostRegistrationCP.shiftLabel.toolTipText=transformation amount
diff --git a/GUI/src/main/resources/cz/fidentis/analyst/gui/tab/Bundle.properties b/GUI/src/main/resources/cz/fidentis/analyst/gui/tab/Bundle.properties
deleted file mode 100644
index 3b4ce9f121b8633cb7cf8321818cc146ce77b8ad..0000000000000000000000000000000000000000
--- a/GUI/src/main/resources/cz/fidentis/analyst/gui/tab/Bundle.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-
-SingleFaceTab.jButton1.text=
diff --git a/GUI/src/main/resources/cz/fidentis/analyst/newgui/swing/Bundle.properties b/GUI/src/main/resources/cz/fidentis/analyst/newgui/swing/Bundle.properties
deleted file mode 100644
index 3b4ce9f121b8633cb7cf8321818cc146ce77b8ad..0000000000000000000000000000000000000000
--- a/GUI/src/main/resources/cz/fidentis/analyst/newgui/swing/Bundle.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-
-SingleFaceTab.jButton1.text=
diff --git a/GUI/src/main/resources/cz/fidentis/analyst/options/Bundle.properties b/GUI/src/main/resources/cz/fidentis/analyst/options/Bundle.properties
new file mode 100644
index 0000000000000000000000000000000000000000..c7bbd76846fa0d0743fc8105152ecb1548c3cb7d
--- /dev/null
+++ b/GUI/src/main/resources/cz/fidentis/analyst/options/Bundle.properties
@@ -0,0 +1 @@
+TestPanel.jLabel1.text=TO DO
diff --git a/GUI/src/main/resources/cz/fidentis/analyst/registration/Bundle.properties b/GUI/src/main/resources/cz/fidentis/analyst/registration/Bundle.properties
new file mode 100644
index 0000000000000000000000000000000000000000..d15a3ec8f6a9a605b93fc73d2816cf4c61a390e0
--- /dev/null
+++ b/GUI/src/main/resources/cz/fidentis/analyst/registration/Bundle.properties
@@ -0,0 +1,88 @@
+RegistrationPanel.jButton1.text=(Re)compute
+RegistrationPanel.jCheckBox1.text=
+RegistrationPanel.jFormattedTextField1.text=0,3
+RegistrationPanel.jLabel5.text=minimal error:
+RegistrationPanel.jFormattedTextField2.text=50
+RegistrationPanel.jLabel6.text=max. iteration.:
+RegistrationPanel.jLabel7.text=scale face:
+RegistrationPanel.jLabel8.text=undersampling:
+RegistrationPanel.thersholdUpButton.text=
+RegistrationPanel.visualizationLabel.text=Transparency:
+RegistrationPanel.profileButton.toolTipText=model profile view
+RegistrationPanel.profileButton.text=side view
+RegistrationPanel.frontButton.toolTipText=model front view
+RegistrationPanel.frontButton.text=front view
+RegistrationPanel.transparencyButton.toolTipText=reset transparency
+RegistrationPanel.transparencyButton.text=clear
+RegistrationPanel.transparencySlider.toolTipText=sets model transparency
+RegistrationPanel.thresholdDownButton.text=
+RegistrationPanel.featurePointsLabel.text=FP dist. threshold:
+RegistrationPanel.jLabel10.text=min:
+RegistrationPanel.jLabel11.text=max:
+RegistrationPanel.jLabel12.text=avg:
+RegistrationPanel.jLabel13.text=0
+RegistrationPanel.jLabel14.text=0
+RegistrationPanel.jLabel15.text=0
+RegistrationPanel.jLabel16.text=avg:
+RegistrationPanel.jLabel17.text=0
+RegistrationPanel.jLabel18.text=min:
+RegistrationPanel.jLabel19.text=0
+RegistrationPanel.jLabel20.text=max:
+RegistrationPanel.jLabel21.text=0
+2
+RegistrationPanel.translationButton.text=
+RegistrationPanel.translationPanel.border.title=translation
+RegistrationPanel.jLabel2.text=Fine-tuning of mutual position:
+RegistrationPanel.highShiftRB.toolTipText=set high shifting amount
+RegistrationPanel.highShiftRB.text=big
+RegistrationPanel.lowShiftRB.toolTipText=set low shifting amount
+RegistrationPanel.lowShiftRB.text=small
+RegistrationPanel.shiftLabel.toolTipText=transformation amount
+RegistrationPanel.shiftLabel.text=step:
+RegistrationPanel.applyButton.toolTipText=apply transformations
+RegistrationPanel.applyButton.text=Apply changes
+RegistrationPanel.resetAllButton.toolTipText=reset all transformations
+RegistrationPanel.resetAllButton.text=reset all
+RegistrationPanel.scaleMinusButton.text=
+RegistrationPanel.scaleButton.toolTipText=reset scale
+RegistrationPanel.scaleButton.text=
+RegistrationPanel.scaleFTF.toolTipText=
+RegistrationPanel.scalePlusButton.text=
+RegistrationPanel.scalePanel.border.title=scale
+RegistrationPanel.rotationXFTF.toolTipText=
+# To change this license header, choose License Headers in Project Properties.
+# To change this template file, choose Tools | Templates
+# and open the template in the editor.
+RegistrationPanel.rightRotationXButton.text=
+RegistrationPanel.leftRotationZButton.text=
+RegistrationPanel.rightRotationYButton.text=
+RegistrationPanel.rightRotationZButton.text=
+RegistrationPanel.rotationButton.toolTipText=reset rotation
+RegistrationPanel.rotationButton.text=
+RegistrationPanel.rotatXLabel.text=x
+RegistrationPanel.rotatYLabel.text=y
+RegistrationPanel.rotatZLabel.text=z
+RegistrationPanel.leftRotationXButton.text=
+RegistrationPanel.leftRotationYButton.text=
+RegistrationPanel.rotationPanel.border.title=rotation
+RegistrationPanel.leftTranslationZButton.text=
+RegistrationPanel.leftTranslationXButton.text=
+RegistrationPanel.rightTranslationZButton.text=
+RegistrationPanel.translYLabel.text=vertical
+RegistrationPanel.translZLabel.text=front-back
+RegistrationPanel.translXLabel.text=horizontal
+RegistrationPanel.rightTranslationYButton.text=
+RegistrationPanel.leftTranslationYButton.text=
+RegistrationPanel.translationXFTF.toolTipText=
+RegistrationPanel.rightTranslationXButton.text=
+RegistrationPanel.translationButton.toolTipText=reset translation
+RegistrationPanel.jLabel3.text=ICP registration
+RegistrationPanel.jLabel4.text=Hausdorff distance
+RegistrationPanel.jPanel3.border.title=Hausdorff distance
+RegistrationPanel.jLabel22.text=relative distance:
+RegistrationPanel.jCheckBox2.text=
+RegistrationPanel.jLabel23.text=strategy:
+RegistrationPanel.jToggleButton1.text=Show heatmap
+RegistrationPanel.jLabel1.text=View
+RegistrationPanel.jPanel5.border.title=distance of feature points
+RegistrationPanel.jLabel9.text=Stats
diff --git a/GUI/src/main/resources/cz/fidentis/analyst/toolbar/Bundle.properties b/GUI/src/main/resources/cz/fidentis/analyst/toolbar/Bundle.properties
new file mode 100644
index 0000000000000000000000000000000000000000..41b6952bd0b6c1c0879cd4965227aa92e97ba4ef
--- /dev/null
+++ b/GUI/src/main/resources/cz/fidentis/analyst/toolbar/Bundle.properties
@@ -0,0 +1,14 @@
+RenderingToolBar.smooth.text=smooth rendering
+RenderingToolBar.wireframe.text=wireframe rendering
+RenderingToolBar.pointcloud.text=point cloud rendering
+RenderingToolBar.background.text=background
+RenderingToolBar.reflections.text=reflections
+RenderingToolBar.renderingmode.text=rendering mode
+SingleFaceToolBar.symmetry.text=symmetry plane
+SingleFaceToolBar.curvature.text=curvature
+FaceToFaceToolBar.distance.text=distance
+FaceToFaceToolBar.registration.text=registration
+RenderingToolBar.primaryface.text=show/hide the primary face
+RenderingToolBar.secondaryfaces.text=show/hide secondary faces
+RenderingToolBar.featurepoints.text=feature points
+
diff --git a/GUI/src/main/resources/distance-icon.png b/GUI/src/main/resources/distance-icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..4cc71045c12faeb681107500bcc3cd555eb04ec6
Binary files /dev/null and b/GUI/src/main/resources/distance-icon.png differ
diff --git a/GUI/src/main/resources/distance28x28.png b/GUI/src/main/resources/distance28x28.png
new file mode 100644
index 0000000000000000000000000000000000000000..042373ad24be72aae7b881d22a0f686fb16af7dc
Binary files /dev/null and b/GUI/src/main/resources/distance28x28.png differ
diff --git a/GUI/src/main/resources/fps.png b/GUI/src/main/resources/fps.png
new file mode 100644
index 0000000000000000000000000000000000000000..eb7be7593d038a4c88b2eed57cfc15b92198815c
Binary files /dev/null and b/GUI/src/main/resources/fps.png differ
diff --git a/GUI/src/main/resources/fps28x28.png b/GUI/src/main/resources/fps28x28.png
new file mode 100644
index 0000000000000000000000000000000000000000..a75503f5c8dda6a0f70067ff6c01ae4bb5eec0c1
Binary files /dev/null and b/GUI/src/main/resources/fps28x28.png differ
diff --git a/GUI/src/main/resources/headPlack.png b/GUI/src/main/resources/headPlack.png
new file mode 100644
index 0000000000000000000000000000000000000000..d06dea15922db88624842e3b365707bedcd928eb
Binary files /dev/null and b/GUI/src/main/resources/headPlack.png differ
diff --git a/GUI/src/main/resources/logo-28x32.png b/GUI/src/main/resources/logo-28x32.png
new file mode 100644
index 0000000000000000000000000000000000000000..ee2291925ff5aad496d15f9d5de9d12b4d1094a1
Binary files /dev/null and b/GUI/src/main/resources/logo-28x32.png differ
diff --git a/GUI/src/main/resources/points-tri28x28.png b/GUI/src/main/resources/points-tri28x28.png
new file mode 100644
index 0000000000000000000000000000000000000000..864d9be5c1f96e0161c5f8d6d729be11cf1c32bb
Binary files /dev/null and b/GUI/src/main/resources/points-tri28x28.png differ
diff --git a/GUI/src/main/resources/primaryFace.png b/GUI/src/main/resources/primaryFace.png
new file mode 100644
index 0000000000000000000000000000000000000000..64224bedec17457f52992e3a395ef15dac50c267
Binary files /dev/null and b/GUI/src/main/resources/primaryFace.png differ
diff --git a/GUI/src/main/resources/primaryFace28x28.png b/GUI/src/main/resources/primaryFace28x28.png
new file mode 100644
index 0000000000000000000000000000000000000000..f94e94b341ac3e910eb16040e5ed2c4de289a6ec
Binary files /dev/null and b/GUI/src/main/resources/primaryFace28x28.png differ
diff --git a/GUI/src/main/resources/reflections28x28.png b/GUI/src/main/resources/reflections28x28.png
new file mode 100644
index 0000000000000000000000000000000000000000..7c9df1dbe596c358b6573df564ac39e164fefc28
Binary files /dev/null and b/GUI/src/main/resources/reflections28x28.png differ
diff --git a/GUI/src/main/resources/reflections64x64.png b/GUI/src/main/resources/reflections64x64.png
new file mode 100644
index 0000000000000000000000000000000000000000..12911616ab35713fabe816897e54f4d89c9b241c
Binary files /dev/null and b/GUI/src/main/resources/reflections64x64.png differ
diff --git a/GUI/src/main/resources/refresh-line.png b/GUI/src/main/resources/refresh-line.png
new file mode 100644
index 0000000000000000000000000000000000000000..68d7b2f1601b67f6e0cd171b2a03a81d1d9a1317
Binary files /dev/null and b/GUI/src/main/resources/refresh-line.png differ
diff --git a/GUI/src/main/resources/registration.png b/GUI/src/main/resources/registration.png
new file mode 100644
index 0000000000000000000000000000000000000000..61649fe0169af68ddba3862c00b3ccfc143af908
Binary files /dev/null and b/GUI/src/main/resources/registration.png differ
diff --git a/GUI/src/main/resources/registration28x28.png b/GUI/src/main/resources/registration28x28.png
new file mode 100644
index 0000000000000000000000000000000000000000..4d8ac9b98f06318849ef45a598ad3fcf71f0f01e
Binary files /dev/null and b/GUI/src/main/resources/registration28x28.png differ
diff --git a/GUI/src/main/resources/restart-line.png b/GUI/src/main/resources/restart-line.png
new file mode 100644
index 0000000000000000000000000000000000000000..8c3c65ec8f540dc3e8a78c1aa56b3d0210a20bdd
Binary files /dev/null and b/GUI/src/main/resources/restart-line.png differ
diff --git a/GUI/src/main/resources/secondaryFace.png b/GUI/src/main/resources/secondaryFace.png
new file mode 100644
index 0000000000000000000000000000000000000000..1708d775fc9c4feaf85e12635f6406919fa3a58e
Binary files /dev/null and b/GUI/src/main/resources/secondaryFace.png differ
diff --git a/GUI/src/main/resources/secondaryFace28x28.png b/GUI/src/main/resources/secondaryFace28x28.png
new file mode 100644
index 0000000000000000000000000000000000000000..f55e763aa20b61ce58714e7d0f0eba16c640a691
Binary files /dev/null and b/GUI/src/main/resources/secondaryFace28x28.png differ
diff --git a/GUI/src/main/resources/smooth-tri28x28.png b/GUI/src/main/resources/smooth-tri28x28.png
new file mode 100644
index 0000000000000000000000000000000000000000..e6629fb424ebecbfd4cf6125a3e3e75a065e90f6
Binary files /dev/null and b/GUI/src/main/resources/smooth-tri28x28.png differ
diff --git a/GUI/src/main/resources/subtract-line.png b/GUI/src/main/resources/subtract-line.png
new file mode 100644
index 0000000000000000000000000000000000000000..1050607dd0fde9ef1fa0a2b1bfd1a552ce4ec343
Binary files /dev/null and b/GUI/src/main/resources/subtract-line.png differ
diff --git a/GUI/src/main/resources/symmetry28x28.png b/GUI/src/main/resources/symmetry28x28.png
new file mode 100644
index 0000000000000000000000000000000000000000..cb96688e587ede5fb396295721af966f88b82b27
Binary files /dev/null and b/GUI/src/main/resources/symmetry28x28.png differ
diff --git a/GUI/src/main/resources/wireframe-tri28x28.png b/GUI/src/main/resources/wireframe-tri28x28.png
new file mode 100644
index 0000000000000000000000000000000000000000..2340dc47e70bb9a7999416c32853ca02fca89dc2
Binary files /dev/null and b/GUI/src/main/resources/wireframe-tri28x28.png differ
diff --git a/GUI/src/main/resources/wireframe28x28.png b/GUI/src/main/resources/wireframe28x28.png
new file mode 100644
index 0000000000000000000000000000000000000000..de9bca364cf46fcd25e7fdee88579bfda5973ddd
Binary files /dev/null and b/GUI/src/main/resources/wireframe28x28.png differ
diff --git a/GUI/src/main/resources/wireframe32x32.png b/GUI/src/main/resources/wireframe32x32.png
new file mode 100644
index 0000000000000000000000000000000000000000..de8952563fcea42ad69e55be37ac3343115311bc
Binary files /dev/null and b/GUI/src/main/resources/wireframe32x32.png differ
diff --git a/GUI/src/main/resources/wireframe36x36.png b/GUI/src/main/resources/wireframe36x36.png
new file mode 100644
index 0000000000000000000000000000000000000000..b459423fa3131a18f2e044397cfee107e4b5833a
Binary files /dev/null and b/GUI/src/main/resources/wireframe36x36.png differ
diff --git a/GUI/src/main/resources/wireframe46x46.png b/GUI/src/main/resources/wireframe46x46.png
new file mode 100644
index 0000000000000000000000000000000000000000..86f9343d4d157b984dde3a4b586680d67512b7a7
Binary files /dev/null and b/GUI/src/main/resources/wireframe46x46.png differ
diff --git a/MeshModel/pom.xml b/MeshModel/pom.xml
index de983e286d9c1d55fa7853d2a83c82782d987e43..cc58b521ea2edafacd79cf854f04bc7b37c7b0c4 100644
--- a/MeshModel/pom.xml
+++ b/MeshModel/pom.xml
@@ -4,7 +4,7 @@
     <parent>
         <groupId>cz.fidentis</groupId>
         <artifactId>FIDENTIS-Analyst-parent</artifactId>
-        <version>2.1.4</version>
+        <version>2021.10</version>
     </parent>
     <artifactId>MeshModel</artifactId>
     <packaging>nbm</packaging>
@@ -17,13 +17,14 @@
                 <configuration>
                     <useOSGiDependencies>true</useOSGiDependencies>
                     <publicPackages> <!-- expose API/packages to other modules -->
-                        <publicPackage>cz.fidentis.analyst.mesh.core.*</publicPackage>
-                        <publicPackage>cz.fidentis.analyst.mesh.io.*</publicPackage>
-                        <publicPackage>cz.fidentis.analyst.mesh.*</publicPackage>
-                        <publicPackage>cz.fidentis.analyst.kdtree.*</publicPackage>
-                        <!--<publicPackage>cz.fidentis.analyst.mesh.core.MeshFacet</publicPackage>-->
-                        <!--<publicPackage>cz.fidentis.analyst.mesh.core.MeshPoint</publicPackage>-->
-                    </publicPackages>
+                       <publicPackage>cz.fidentis.analyst.mesh.core.*</publicPackage>
+                       <publicPackage>cz.fidentis.analyst.mesh.io.*</publicPackage>
+                       <publicPackage>cz.fidentis.analyst.mesh.*</publicPackage>
+                       <publicPackage>cz.fidentis.analyst.kdtree.*</publicPackage>
+                       <publicPackage>cz.fidentis.analyst.feature.*</publicPackage>
+                       <!--<publicPackage>cz.fidentis.analyst.mesh.core.MeshFacet</publicPackage>-->
+                       <!--<publicPackage>cz.fidentis.analyst.mesh.core.MeshPoint</publicPackage>-->
+                   </publicPackages>
                 </configuration>
             </plugin>
             <plugin>
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/feature/FeaturePoint.java b/MeshModel/src/main/java/cz/fidentis/analyst/feature/FeaturePoint.java
index 6e383a2a885d29eb3245f4dd7d4d1d9ccd4154b6..caf717f323af273b7f1e6272d0a705bb001e34c2 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/feature/FeaturePoint.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/feature/FeaturePoint.java
@@ -1,68 +1,48 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
 package cz.fidentis.analyst.feature;
 
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
+import java.io.Serializable;
+import javax.vecmath.Point3d;
 
 /**
  *
  * @author Jakub Kolman 
  */
-
-@XmlRootElement
-@XmlType(propOrder = {"facialPoints", "x", "y", "z" })
-public class FeaturePoint {
-
-    private double x;
-    private double y;
-    private double z;
-    private FeaturePointType FEATURE_POINT_TYPE;
-
+public class FeaturePoint implements Serializable {
+
+    private final Point3d position;
+    private final FeaturePointType featurePointType;
+
+    /**
+     * Constructor.
+     * 
+     * @param x Location x 
+     * @param y Location y
+     * @param z Location z
+     * @param featurePointType Original type
+     */
     public FeaturePoint(double x, double y, double z, FeaturePointType featurePointType) {
-        this.x = x;
-        this.y = y;
-        this.z = z;
-        this.FEATURE_POINT_TYPE = featurePointType;
+        this.position = new Point3d(x, y, z);
+        this.featurePointType = featurePointType;
     }
-
-    @XmlAttribute  
-    public double getX() {
-        return x;
+    
+    public Point3d getPosition() {
+        return position;
     }
     
-    public void setX(double x) {
-        this.x = x;
+    public double getX() {
+        return position.x;
     }
 
-    @XmlAttribute  
     public double getY() {
-        return y;
-    }
-    
-    public void setY(double y) {
-        this.y = y;
+        return position.y;
     }
 
-    @XmlAttribute  
     public double getZ() {
-        return z;
-    }
-    
-    public void setZ(double z) {
-        this.z = z;
+        return position.z;
     }
 
-    @XmlAttribute  
     public FeaturePointType getFeaturePointType() {
-        return FEATURE_POINT_TYPE;
+        return featurePointType;
     }
     
-    public void setFeaturePointType(FeaturePointType fp) {
-        this.FEATURE_POINT_TYPE = fp;
-    }
 }
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/feature/FeaturePointType.java b/MeshModel/src/main/java/cz/fidentis/analyst/feature/FeaturePointType.java
index 878f92e3e98c5b01a512bd247ed80853b4328442..013a3d7a4228e6b250be0a41a5a293a488ef60b3 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/feature/FeaturePointType.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/feature/FeaturePointType.java
@@ -1,20 +1,18 @@
 package cz.fidentis.analyst.feature;
 
+import java.io.Serializable;
+
 /**
  * 
  * @author Jakub Kolman
  */
-public class FeaturePointType {
+public class FeaturePointType implements Serializable {
     private final int type;
     private final String name;
     private final String info;
     private final String code;
 
-    public FeaturePointType(
-            int type,
-             String name,
-             String info,
-             String code) {
+    public FeaturePointType(int type, String name, String info, String code) {
         this.type = type;
         this.name = name;
         this.info = info;
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/feature/exception/FeaturePointException.java b/MeshModel/src/main/java/cz/fidentis/analyst/feature/exception/FeaturePointException.java
index a7330475150a8b3e73349fada2f812ba1c717852..391081c5cd014b5ce20c53576fdb03943e485914 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/feature/exception/FeaturePointException.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/feature/exception/FeaturePointException.java
@@ -7,10 +7,14 @@ package cz.fidentis.analyst.feature.exception;
 
 /**
  *
- * @author kubok
+ * @author Jakub Kolman
  */
 public class FeaturePointException extends RuntimeException {
     
+    /**
+     * Calls super method that throws exception with message parameter
+     * @param message 
+     */
     public FeaturePointException(String message) {
         super(message);
     }
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/feature/provider/FeaturePointTypeProvider.java b/MeshModel/src/main/java/cz/fidentis/analyst/feature/provider/FeaturePointTypeProvider.java
index ca3eed37019ef802a0a1583e6d52f4fc244dedb4..e37fc061e49ca068f150aa9127b1e8afd6f60892 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/feature/provider/FeaturePointTypeProvider.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/feature/provider/FeaturePointTypeProvider.java
@@ -11,8 +11,8 @@ import java.util.HashMap;
 import java.util.Map;
 
 /**
- *
- * @author kubok
+ * 
+ * @author Jakub Kolman
  */
 public class FeaturePointTypeProvider {
 
@@ -25,6 +25,9 @@ public class FeaturePointTypeProvider {
         public static FeaturePointTypeProvider instance = new FeaturePointTypeProvider();
     }
 
+    /**
+     * 
+     */
     private FeaturePointTypeProvider() {
         FeaturePointTypesService service = new FeaturePointTypesService();
         featurePointTypesById = service.readResources().orElse(new HashMap<>());
@@ -40,24 +43,36 @@ public class FeaturePointTypeProvider {
         return InstanceHolder.instance;
     }
 
+    /**
+     * get feature points types by id
+     * @return 
+     */
     public Map<Integer, FeaturePointType> getFeaturePointTypesById() {
         return featurePointTypesById;
     }
 
+    /**
+     * sorted feature point types by code
+     * @return 
+     */
     public Map<String, FeaturePointType> getFeaturePointTypesByCode() {
         return featurePointTypesByCode;
     }
 
     /**
-     * Get feature point by code
-     *
+     * get single feature point type by its code
      * @param code
-     * @return
+     * @return 
      */
     public FeaturePointType getFeaturePointTypeByCode(String code) {
         return getFeaturePointTypesByCode().get(code);
     }
 
+    /**
+     * get single feature point type by its id
+     * @param id
+     * @return 
+     */
     public FeaturePointType getFeaturePointTypeById(int id) {
         return getFeaturePointTypesById().get(id);
     }
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointsCsvExporter.java b/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointCsvExporter.java
similarity index 77%
rename from MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointsCsvExporter.java
rename to MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointCsvExporter.java
index 11130dd5afb5a8ff74ae1d9187afc431de1645cd..b344b4600405af40a89fa2466f9a3ae2461227e2 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointsCsvExporter.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointCsvExporter.java
@@ -14,14 +14,11 @@ import java.util.logging.Logger;
  * 
  * @author Jakub Kolman
  */
-public class FeaturePointsCsvExporter {
-    
-        public FeaturePointsCsvExporter() {
-            
-        }
+public class FeaturePointCsvExporter {
    
-        public void exportFeaturePointsToCSV(List<FeaturePoint> featurePointList, String objectName) throws IOException {
+        public static void exportFeaturePointsToCSV(List<FeaturePoint> featurePointList, String objectName) throws IOException {
         File csvOutputFile = new File(String.format("%s_landmarks.csv", objectName));
+        // CSV is a normal text file, need a writer
         try (BufferedWriter bw = new BufferedWriter(new FileWriter(csvOutputFile))) {
             bw.write("Scan name");
             featurePointList.forEach(featurePoint -> {
@@ -30,7 +27,7 @@ public class FeaturePointsCsvExporter {
                     bw.write(String.format(",%s y", featurePoint.getFeaturePointType().getCode()));
                     bw.write(String.format(",%s z", featurePoint.getFeaturePointType().getCode()));
                 } catch (IOException ex) {
-                    Logger.getLogger(FeaturePointImportService.class.getName()).log(Level.SEVERE, null, ex);
+                    Logger.getLogger(FeaturePointCsvExporter.class.getName()).log(Level.SEVERE, null, ex);
                 }
             });
             bw.newLine();
@@ -44,12 +41,10 @@ public class FeaturePointsCsvExporter {
                     bw.write(",");
                     bw.write(Double.toString(featurePoint.getZ()));
                 } catch (IOException ex) {
-                    Logger.getLogger(FeaturePointImportService.class.getName()).log(Level.SEVERE, null, ex);
+                    Logger.getLogger(FeaturePointCsvExporter.class.getName()).log(Level.SEVERE, null, ex);
                 }
             });
         }
     }
 
-
-    
 }
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointsCsvLoader.java b/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointCsvLoader.java
similarity index 77%
rename from MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointsCsvLoader.java
rename to MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointCsvLoader.java
index 1de6240186623f67a44b78946533bd17fcd98778..7f51e7f3810f4ae88e6fecb94ac73d5705cb935a 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointsCsvLoader.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointCsvLoader.java
@@ -1,17 +1,18 @@
 package cz.fidentis.analyst.feature.services;
 
 import cz.fidentis.analyst.feature.FeaturePoint;
-import cz.fidentis.analyst.feature.exception.FeaturePointException;
 import cz.fidentis.analyst.feature.provider.FeaturePointTypeProvider;
 import cz.fidentis.analyst.feature.utils.FileResourcesUtils;
 import java.io.BufferedReader;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Optional;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 import java.util.stream.Stream;
 
 /**
@@ -19,12 +20,12 @@ import java.util.stream.Stream;
  * 
  * @author Jakub Kolman
  */
-public class FeaturePointsCsvLoader {
+public class FeaturePointCsvLoader {
     
     private static final String COLUMN_DELIMETER = ",";
     private static final String CODE_PREFIX_DELIMETER = " ";
 
-    public Optional<List<FeaturePoint>> importFeaturePointsCSV(String path, String fileName) {
+    public static List<FeaturePoint> loadFeaturePoints(String path, String fileName) throws FileNotFoundException, IOException {
         FileResourcesUtils app = new FileResourcesUtils();
         try (InputStreamReader streamReader
                 = new InputStreamReader(app.getFileAsStream(path, fileName), StandardCharsets.UTF_8);
@@ -40,7 +41,7 @@ public class FeaturePointsCsvLoader {
 
             if (linesList.size() != 2
                     || linesList.get(0).size() != linesList.get(1).size()) {
-                throw new FeaturePointException(String.format("Feature point import file '%s' has wrong format", fileName));
+                throw new IOException(String.format("Feature point import file '%s' has wrong format", fileName));
             }
 
             List<FeaturePoint> points = new ArrayList<>();
@@ -54,16 +55,14 @@ public class FeaturePointsCsvLoader {
                 );
                 points.add(point);
             }
-            return Optional.of(points);
+            return points;
 
-        } catch (IOException e) {
-            throw new FeaturePointException(String.format("Feature point cannot open file", fileName));
         } catch (NumberFormatException e1) {
-            throw new FeaturePointException(e1.getMessage());
+            throw new IOException(e1);
         }
     }
 
-    private String getCode(String str) {
+    private static String getCode(String str) {
         return str.substring(0, str.indexOf(CODE_PREFIX_DELIMETER));
     }
 }
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointExportService.java b/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointExportService.java
index 975f8ba04db99084f9317bb62e56e0f243dbc822..2a20c43842cfa4f90e040e442d3a6fae11017d5a 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointExportService.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointExportService.java
@@ -8,22 +8,32 @@ import java.util.List;
 
 /**
  * Class used for exporting feature points from file
- * 
- * for more details @see cz.fidentis.analyst.feature.services.FeaturePointsCsvExporter or @see cz.fidentis.analyst.feature.services.FeaturePointsFpExporter
+ 
+ for more details @see cz.fidentis.analyst.feature.services.FeaturePointCsvExporter or @see cz.fidentis.analyst.feature.services.FeaturePointFpExporter
  * 
  * @author Jakub Kolman
  */
 public class FeaturePointExportService {
 
+    /**
+     * Method calls either @see FeaturePointCsvExporter or @see
+ FeaturePointFpExporter based on the format given as parameter
+     * 
+     * @param featurePointList
+     * @param objectName
+     * @param format
+     * @throws FileNotFoundException
+     * @throws IOException 
+     */
     public void exportFeaturePoints(List<FeaturePoint> featurePointList, String objectName, String format) throws FileNotFoundException, IOException {
         switch (format) {
-            case FeaturePointFileFormatTypes.FORMAT_TYPE_OBJ:
-                FeaturePointsCsvExporter csvExporter = new FeaturePointsCsvExporter();
+            case FeaturePointFileFormatTypes.FORMAT_TYPE_CSV:
+                FeaturePointCsvExporter csvExporter = new FeaturePointCsvExporter();
                 csvExporter.exportFeaturePointsToCSV(featurePointList, objectName);
                 break;
 
             case FeaturePointFileFormatTypes.FORMAT_TYPE_FP:
-                FeaturePointsFpExporter fpExporter = new FeaturePointsFpExporter();
+                FeaturePointFpExporter fpExporter = new FeaturePointFpExporter();
                 fpExporter.exportFeaturePointsToFP(featurePointList, objectName);
                 break;
                 
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointsFpExporter.java b/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointFpExporter.java
similarity index 80%
rename from MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointsFpExporter.java
rename to MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointFpExporter.java
index ee5173b5e441dc8bcfac22e4f3de6209f8d78502..19e0955610fc5ef3010a94834d14a241d21afde0 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointsFpExporter.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointFpExporter.java
@@ -15,13 +15,9 @@ import java.util.logging.Logger;
  * 
  * @author Jakub Kolman
  */
-public class FeaturePointsFpExporter {
+public class FeaturePointFpExporter {
     
-        public FeaturePointsFpExporter() {
-            
-        }
-    
-        public void exportFeaturePointsToFP(List<FeaturePoint> featurePointList, String objectName) throws FileNotFoundException, IOException {
+        public static void exportFeaturePointsToFP(List<FeaturePoint> featurePointList, String objectName) throws FileNotFoundException, IOException {
         File csvOutputFile = new File(String.format("%s_landmarks.fp", objectName));
         // CSV is a normal text file, need a writer
         try (BufferedWriter bw = new BufferedWriter(new FileWriter(csvOutputFile))) {
@@ -37,7 +33,7 @@ public class FeaturePointsFpExporter {
                     bw.newLine();
                     bw.write(String.format("<z>%f</z>", featurePoint.getZ()));
                 } catch (IOException ex) {
-                    Logger.getLogger(FeaturePointImportService.class.getName()).log(Level.SEVERE, null, ex);
+                    Logger.getLogger(FeaturePointFpExporter.class.getName()).log(Level.SEVERE, null, ex);
                 }
             });
             bw.newLine();
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointsFpLoader.java b/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointFpLoader.java
similarity index 88%
rename from MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointsFpLoader.java
rename to MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointFpLoader.java
index e1a02572524493f915911d6cedbc0374ff4d8b7a..5d2c1e5d98a44449340c499270e13933b44bd5f6 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointsFpLoader.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointFpLoader.java
@@ -5,6 +5,7 @@ import cz.fidentis.analyst.feature.exception.FeaturePointException;
 import cz.fidentis.analyst.feature.provider.FeaturePointTypeProvider;
 import cz.fidentis.analyst.feature.utils.FileResourcesUtils;
 import java.io.BufferedReader;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.nio.charset.StandardCharsets;
@@ -18,12 +19,20 @@ import java.util.stream.Stream;
  * 
  * @author Jakub Kolman
  */
-public class FeaturePointsFpLoader {
+public class FeaturePointFpLoader {
 
     private static final String GREATER_THAN_DELIMETER = ">";
     private static final String LESS_THAN_DELIMETER = "<";
 
-    public Optional<List<FeaturePoint>> importFeaturePointsFP(String path, String fileName) {
+    /**
+     * Loads feature points form given file 
+     * 
+     * @param path
+     * @param fileName
+     * @return List of FeaturePoint
+     * @throws FileNotFoundException 
+     */
+    public static List<FeaturePoint> loadFeaturePoints(String path, String fileName) throws FileNotFoundException {
         FileResourcesUtils app = new FileResourcesUtils();
         try (InputStreamReader streamReader
                 = new InputStreamReader(app.getFileAsStream(path, fileName), StandardCharsets.UTF_8);
@@ -57,7 +66,7 @@ public class FeaturePointsFpLoader {
                 );
                 points.add(point);
             }
-            return Optional.of(points);
+            return points;
 
         } catch (IOException e) {
             throw new FeaturePointException(String.format("Feature point service cannot open file", fileName));
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointImportService.java b/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointImportService.java
index 86747826f3d79cb995f0c233feefa34ff306dcee..67b03800913c8b9f8dc188f20afb07f151f75083 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointImportService.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointImportService.java
@@ -1,9 +1,44 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
 package cz.fidentis.analyst.feature.services;
 
+import cz.fidentis.analyst.feature.FeaturePoint;
+import cz.fidentis.analyst.feature.utils.FeaturePointFileFormatTypes;
+import java.io.IOException;
+import java.util.List;
+
 /**
  *
  * @author Jakub Kolman
  */
 public class FeaturePointImportService {
 
+    private static final String DELIMETER = ".";
+
+    /**
+     * Method calls either @see FeaturePointCsvLoader or @see
+ FeaturePointFpLoader based on the format taken out of filename
+     *
+     * @param path
+     * @param fileName
+     * @return
+     * @throws IOException
+     */
+    public static List<FeaturePoint> importFeaturePoints(String path, String fileName) throws IOException {
+        String format = fileName.substring(fileName.lastIndexOf(DELIMETER) + 1);
+        switch (format.toUpperCase()) {
+            case (FeaturePointFileFormatTypes.FORMAT_TYPE_CSV):
+                return FeaturePointCsvLoader.loadFeaturePoints(path, fileName);
+
+            case (FeaturePointFileFormatTypes.FORMAT_TYPE_FP):
+                return FeaturePointFpLoader.loadFeaturePoints(path, fileName);
+
+            default:
+                return null;
+        }
+    }
+
 }
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/feature/utils/FeaturePointFileFormatTypes.java b/MeshModel/src/main/java/cz/fidentis/analyst/feature/utils/FeaturePointFileFormatTypes.java
index ea6f682b38d11941b888c5f2cffc46cd55a9389a..bd2d585257ff7c417ecea80dbc918bd7220e96dc 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/feature/utils/FeaturePointFileFormatTypes.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/feature/utils/FeaturePointFileFormatTypes.java
@@ -6,7 +6,7 @@
 package cz.fidentis.analyst.feature.utils;
 
 /**
- *
+ * 
  * @author Jakub Kolman
  */
 public class FeaturePointFileFormatTypes {
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/feature/utils/FileResourcesUtils.java b/MeshModel/src/main/java/cz/fidentis/analyst/feature/utils/FileResourcesUtils.java
index 659105462b7a901a5f99df6014c99a3e30c7a726..40f0fd768f4fa74812cf452120b699b2062fcb2f 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/feature/utils/FileResourcesUtils.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/feature/utils/FileResourcesUtils.java
@@ -14,6 +14,7 @@ import java.util.List;
 
 public class FileResourcesUtils {
 
+
     public static void main(String[] args) throws IOException, URISyntaxException {
 
         FileResourcesUtils app = new FileResourcesUtils();
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTree.java b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTree.java
index 7d019ce3b9b105830da45a42687626f4f426a6a6..cadc0548bfe59b72a6157081163e53e2f00924db 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTree.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTree.java
@@ -73,7 +73,7 @@ public class KdTree implements Serializable {
     /**
      * Constructor. If no mesh points (vertices) are provided, then an empty 
      * KD-tree is constructed (with the root node set to null).
-     * If multiple mesh factes share the same vertex, then they are stored 
+     * If multiple mesh facets share the same vertex, then they are stored 
      * efficiently in the same node of the KD-tree.
      *
      * @param facets The list of mesh facets to be stored. Facets can share vertices.
@@ -134,7 +134,53 @@ public class KdTree implements Serializable {
     }
     
     /**
-     * Visits this facet.
+     * Return number of nodes in the k-d tree.
+     * @return number of nodes in the k-d tree
+     */
+    public int getNumNodes() {
+        int ret = 0;
+        Queue<KdNode> queue = new LinkedList<>();
+        queue.add(root);
+
+        while (!queue.isEmpty()) {
+            KdNode node = queue.poll();
+            if (node == null) {
+                continue;
+            }
+            queue.add(node.getLesser());
+            queue.add(node.getGreater());
+            ret++;
+        }
+        
+        return ret;
+    }
+    
+    /**
+     * Return the length of the longest path.
+     * @return Return the length of the longest path.
+     */
+    public int getDepth() {
+        int depth = 0;
+        Queue<KdNode> queue = new LinkedList<>();
+        queue.add(root);
+
+        while (!queue.isEmpty()) {
+            KdNode node = queue.poll();
+            if (node == null) {
+                continue;
+            }
+            queue.add(node.getLesser());
+            queue.add(node.getGreater());
+            if (node.getDepth() > depth) {
+                depth = node.getDepth();
+            }
+        }
+        
+        return depth;
+    }
+    
+    /**
+     * Visits this tree.
      * 
      * @param visitor Visitor
      */
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTreeVisitor.java b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTreeVisitor.java
index ae02da318b51906609b9c054cfcaef8c5fcb7cd6..c478f67a44ff75c5f9c2a9730d50a3ec88347aa4 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTreeVisitor.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTreeVisitor.java
@@ -32,7 +32,7 @@ public abstract class KdTreeVisitor {
     }
     
     /**
-     * The main inspection methodto be implemented by specific visitors.
+     * The main inspection method to be implemented by specific visitors.
      * 
      * @param kdTree K-d tree to be visited
      */
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java
index b17354e39a52f5ed6d1aca263104c3178bc401db..d3271fe5ba6fdbb32a6b3142b99ad1d259fe9599 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java
@@ -1,158 +1,184 @@
-package cz.fidentis.analyst.mesh.core;
-
-import com.google.common.eventbus.EventBus;
-import java.util.ArrayList;
-import java.util.List;
-import cz.fidentis.analyst.mesh.MeshVisitor;
-import cz.fidentis.analyst.mesh.events.FacetAddedEvent;
-import java.util.Collections;
-import cz.fidentis.analyst.mesh.events.MeshListener;
-import java.io.Serializable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-/**
- * The main object for triangular meshes. Each mesh model consists  
- * of one or more mesh facets.
- * <p>
- * This class implements the publish-subscribe notifications to changes. 
- * However, the {@code HumanFace} class provides similar
- * functionality at the higher level of abstraction. Therefore, we recommend
- * to monitor this class when you want to be informed about changes in concrete human face.
- * <p>
- * Events fired by the class:
- * <ul>
- * <li>{@link cz.fidentis.analyst.mesh.events.FacetAddedEvent} when new facet is added.</li>
- * </ul>
- * </p>
- * 
- * @author Matej Lukes
- * @author Radek Oslejsek
- */
-public class MeshModel implements Serializable {
-    
-    private final List<MeshFacet> facets = new ArrayList<>();
-    
-    private final transient EventBus eventBus = new EventBus();
-    
-    /**
-     * Constructor of MeshModel
-     */
-    public MeshModel() {
-
-    }
-
-    /**
-     * Copy constructor of MeshModel
-     *
-     * @param meshModel copied MeshModel
-     */
-    public MeshModel(MeshModel meshModel) {
-        for (MeshFacet facet: meshModel.facets) {
-            facets.add(new MeshFacetImpl(facet));
-        }
-    }
-
-    /**
-     * returns list of MeshFacets
-     *
-     * @return list of MeshFacets
-     */
-    public List<MeshFacet> getFacets() {
-        return Collections.unmodifiableList(facets);
-    }
-
-    /**
-     * Adds a new mesh facet to the model. 
-     * Fires {@link cz.fidentis.analyst.mesh.events.FacetAddedEvent} to
-     * registered listeners.
-     *
-     * @param facet new MeshFacet
-     */
-    public void addFacet(MeshFacet facet) {
-        facets.add(facet);
-        eventBus.post(new FacetAddedEvent(facet));
-    }
-    
-    /**
-     * Applies the visitor to all mesh facets. If the visitor is thread-safe
-     * and the {@code concurrently} is {@code true}, then the visitor is
-     * applied to all mesh facet concurrently using all CPU cores.
-     * 
-     * @param visitor Visitor to be applied for the computation
-     * @param concurrently Parallel computation
-     * @throws NullPointerException if the visitor is {@code null}
-     */
-    public void compute(MeshVisitor visitor, boolean concurrently) {
-        if (concurrently && visitor.isThreadSafe()) {
-            ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
-            
-            for (MeshFacet f: this.facets) {
-                Runnable worker = new Runnable() {
-                    @Override
-                    public void run() {
-                        f.accept(visitor);
-                    }
-                };
-                executor.execute(worker);
-            }
-            
-            // Wait until all symmetry planes are computed:
-            executor.shutdown();
-            while (!executor.isTerminated()){}
-        } else {
-            for (MeshFacet f: this.facets) {
-                f.accept(visitor);
-            }
-        }
-    }
-    
-    /**
-     * Applies the visitor to all mesh facets sequentially.
-     * 
-     * @param visitor Visitor to be applied for the computation
-     * @throws NullPointerException if the visitor is {@code null}
-     */
-    public void compute(MeshVisitor visitor) {
-        compute(visitor, false);
-    }
-    
-    /**
-     * Registers listeners (objects concerned in the mesh model changes) to receive events.
-     * If listener is {@code null}, no exception is thrown and no action is taken.
-     * 
-     * @param listener Listener concerned in the mesh model changes.
-     */
-    public void registerListener(MeshListener listener) {
-        eventBus.register(listener);
-    }
-    
-    /**
-     * Unregisters listeners from receiving events.
-     * 
-     * @param listener Registered listener
-     */
-    public void unregisterListener(MeshListener listener) {
-        eventBus.unregister(listener);
-    }
-    
-    /**
-     * Removes duplicate vertices that differ only in normal vectors or texture coordinates.
-     * Multiple normals are replaced with the average normal. If the texture coordinate 
-     * differ then randomly selected one is used.
-     */
-    public void simplifyModel() {
-        for (MeshFacet f : this.facets) {
-            f.simplify();
-        }
-    }
-    
-    @Override
-    public String toString() {
-        int verts = 0;
-        for (MeshFacet f: facets) {
-            verts += f.getNumberOfVertices();
-        }
-        return facets.size() + " facets with " + verts + " vertices";
-    }
-}
+package cz.fidentis.analyst.mesh.core;
+
+import com.google.common.eventbus.EventBus;
+import java.util.ArrayList;
+import java.util.List;
+import cz.fidentis.analyst.mesh.MeshVisitor;
+import cz.fidentis.analyst.mesh.events.FacetAddedEvent;
+import java.util.Collections;
+import cz.fidentis.analyst.mesh.events.MeshListener;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * The main object for triangular meshes. Each mesh model consists  
+ * of one or more mesh facets.
+ * <p>
+ * This class implements the publish-subscribe notifications to changes. 
+ * However, the {@code HumanFace} class provides similar
+ * functionality at the higher level of abstraction. Therefore, we recommend
+ * to monitor this class when you want to be informed about changes in concrete human face.
+ * <p>
+ * Events fired by the class:
+ * <ul>
+ * <li>{@link cz.fidentis.analyst.mesh.events.FacetAddedEvent} when new facet is added.</li>
+ * </ul>
+ * </p>
+ * 
+ * @author Matej Lukes
+ * @author Radek Oslejsek
+ */
+public class MeshModel implements Serializable {
+    
+    private final List<MeshFacet> facets = new ArrayList<>();
+    
+    private final transient EventBus eventBus = new EventBus();
+    
+    /**
+     * Constructor of MeshModel
+     */
+    public MeshModel() {
+
+    }
+
+    /**
+     * Copy constructor of MeshModel
+     *
+     * @param meshModel copied MeshModel
+     */
+    public MeshModel(MeshModel meshModel) {
+        for (MeshFacet facet: meshModel.facets) {
+            facets.add(new MeshFacetImpl(facet));
+        }
+    }
+
+    /**
+     * returns list of MeshFacets
+     *
+     * @return list of MeshFacets
+     */
+    public List<MeshFacet> getFacets() {
+        return Collections.unmodifiableList(facets);
+    }
+
+    /**
+     * Adds a new mesh facet to the model. 
+     * Fires {@link cz.fidentis.analyst.mesh.events.FacetAddedEvent} to
+     * registered listeners.
+     *
+     * @param facet new MeshFacet
+     */
+    public void addFacet(MeshFacet facet) {
+        facets.add(facet);
+        eventBus.post(new FacetAddedEvent(facet));
+    }
+    
+    /**
+     * Adds a new mesh facets to the model. 
+     * Fires {@link cz.fidentis.analyst.mesh.events.FacetAddedEvent} to
+     * registered listeners.
+     *
+     * @param newFacets collection of new new facets
+     */
+    public void addFacets(Collection<MeshFacet> newFacets) {
+        facets.addAll(newFacets);
+        for (MeshFacet f: newFacets) {
+            eventBus.post(new FacetAddedEvent(f));
+        }
+    }
+    
+    /**
+     * Applies the visitor to all mesh facets. If the visitor is thread-safe
+     * and the {@code concurrently} is {@code true}, then the visitor is
+     * applied to all mesh facet concurrently using all CPU cores.
+     * 
+     * @param visitor Visitor to be applied for the computation
+     * @param concurrently Parallel computation
+     * @throws NullPointerException if the visitor is {@code null}
+     */
+    public void compute(MeshVisitor visitor, boolean concurrently) {
+        if (concurrently && visitor.isThreadSafe()) {
+            ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
+            
+            for (MeshFacet f: this.facets) {
+                Runnable worker = new Runnable() {
+                    @Override
+                    public void run() {
+                        f.accept(visitor);
+                    }
+                };
+                executor.execute(worker);
+            }
+            
+            // Wait until all symmetry planes are computed:
+            executor.shutdown();
+            while (!executor.isTerminated()){}
+        } else {
+            for (MeshFacet f: this.facets) {
+                f.accept(visitor);
+            }
+        }
+    }
+    
+    /**
+     * Applies the visitor to all mesh facets sequentially.
+     * 
+     * @param visitor Visitor to be applied for the computation
+     * @throws NullPointerException if the visitor is {@code null}
+     */
+    public void compute(MeshVisitor visitor) {
+        compute(visitor, false);
+    }
+    
+    /**
+     * Registers listeners (objects concerned in the mesh model changes) to receive events.
+     * If listener is {@code null}, no exception is thrown and no action is taken.
+     * 
+     * @param listener Listener concerned in the mesh model changes.
+     */
+    public void registerListener(MeshListener listener) {
+        eventBus.register(listener);
+    }
+    
+    /**
+     * Unregisters listeners from receiving events.
+     * 
+     * @param listener Registered listener
+     */
+    public void unregisterListener(MeshListener listener) {
+        eventBus.unregister(listener);
+    }
+    
+    /**
+     * Removes duplicate vertices that differ only in normal vectors or texture coordinates.
+     * Multiple normals are replaced with the average normal. If the texture coordinate 
+     * differ then randomly selected one is used.
+     */
+    public void simplifyModel() {
+        for (MeshFacet f : this.facets) {
+            f.simplify();
+        }
+    }
+    
+    @Override
+    public String toString() {
+        int verts = 0;
+        for (MeshFacet f: facets) {
+            verts += f.getNumberOfVertices();
+        }
+        return facets.size() + " facets with " + verts + " vertices";
+    }
+    
+    /**
+     * Returns number of vertices }sum of all facets).
+     * @return Number of vertices
+     */
+    public long getNumVertices() {
+        //int ret = 0;
+        //facets.stream().map(f -> f.getNumberOfVertices()).reduce(ret, Integer::sum);
+        //return ret;
+        return facets.stream().map(f -> f.getNumberOfVertices()).reduce(0, Integer::sum);
+    }
+}
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPoint.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPoint.java
index e216c5ef4bacbebc949924e83c6de6d64f44820f..dbcb4e27996521e8946c01b4a6ce49c89845dfd7 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPoint.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPoint.java
@@ -34,6 +34,12 @@ public interface MeshPoint extends Serializable {
      * @return position
      */
     Point3d getPosition();
+    
+    /**
+     * 
+     * @param newPos New position, must not be {@code null}
+     */
+    void setPosition(Point3d newPos);
 
     /**
      * @return texture coordinates
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPointImpl.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPointImpl.java
index 51c54481af080545691626ed5459a10f97d911ac..61dbabf958a9eec1ada278ca2d450182fd9d907e 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPointImpl.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPointImpl.java
@@ -56,6 +56,13 @@ public class MeshPointImpl implements MeshPoint {
     public Point3d getPosition() {
         return position;
     }
+    
+    @Override
+    public void setPosition(Point3d newPos) {
+        if (newPos != null) {
+            this.position = new Point3d(newPos);
+        }
+    }
 
     @Override
     public Vector3d getTexCoord() {
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshTriangle.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshTriangle.java
index 9176377791fcd07abdc079952050863843ef8d4a..3e0328d96ec801a9583918c2cfc9fdb79aa92671 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshTriangle.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshTriangle.java
@@ -31,9 +31,7 @@ public class MeshTriangle implements Iterable<MeshPoint> {
     /**
      * Creates new triangle
      * 
-     * @param v1 first vertex 
-     * @param v2 second vertex
-     * @param v3 third vertex
+     * @param facet Mesh facet
      * @param i1 which index is the first vertex stored in the mesh facet
      * @param i2 which index is the second vertex stored in the mesh facet
      * @param i3 which index is the third vertex stored in the mesh facet
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/ModelFileFilter.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/ModelFileFilter.java
deleted file mode 100644
index 17a5f729bcf869daaa0225876d6c3d57a31d9f44..0000000000000000000000000000000000000000
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/ModelFileFilter.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package cz.fidentis.analyst.mesh.io;
-
-import javax.swing.filechooser.FileFilter;
-import java.io.File;
-
-/**
- * @author Natália Bebjaková
- * 
- * Class that enables to choose just extensions we want in the filechooser 
- */
-public class ModelFileFilter extends FileFilter {
-
-    private final String[] extension;
-    private final String description;
-    
-    /**
-     * 
-     * @param extension Extentions of files
-     * @param description Description
-     */
-    public ModelFileFilter(String[] extension, String description) {
-        this.extension = extension;
-        this.description = description;
-    }
-
-    /**
-     * 
-     * @param f File 
-     * @return Whether file has chosen extension or not 
-     */
-    @Override
-    public boolean accept(File f) {
-        boolean accepted = false;
-        for (String extension1 : extension) {
-            if (f.isDirectory() || f.getName().endsWith(extension1)) {
-                accepted = true;
-            }
-        }
-        return accepted;
-    }
-    
-    /**
-     * 
-     * @return description
-     */
-    @Override
-    public String getDescription() {
-        return description;
-    }
-
-}
\ No newline at end of file
diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointExportServiceTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointExportServiceTest.java
index 1353c58c3ec18267223cc73ebe27f8ca133908f6..b3d80a890bec8977b189debe735047fc06ea4239 100644
--- a/MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointExportServiceTest.java
+++ b/MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointExportServiceTest.java
@@ -6,11 +6,11 @@
 package cz.fidentis.analyst.feature.services;
 
 import cz.fidentis.analyst.feature.FeaturePoint;
+import cz.fidentis.analyst.feature.services.FeaturePointCsvLoader;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.List;
-import java.util.Optional;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.DisplayName;
 
@@ -20,28 +20,28 @@ import org.junit.jupiter.api.DisplayName;
  */
 public class FeaturePointExportServiceTest {
 
-    private static final Path testFileDirectory = Paths.get("src", "test", "resources", "cz", "fidentis", "analyst", "feature", "services");
-    private static final String TEST_CSV_FILE = "00007_01_landmarks.csv";
+    private static final Path MODEL_TEST_FILE_DIRECTORY = Paths.get("src", "test", "resources", "cz", "fidentis", "analyst", "feature", "services");
+    private static final String MODEL_FILE = "00007_01_landmarks.csv";
 
     @DisplayName("Test writing a CSV file")
     @Test
     void exportFeaturePointsCSVTest() throws IOException {
         FeaturePointExportService service = new FeaturePointExportService();
-        Optional<List<FeaturePoint>> featurePoints = loadFeaturePoints();
-        service.exportFeaturePoints(featurePoints.get(), "test_file", "CSV");
+        List<FeaturePoint> featurePoints = loadFeaturePoints();
+        service.exportFeaturePoints(featurePoints, "test_file_csv", "CSV");
     }
 
     @DisplayName("Test writing a FP file")
     @Test
     void exportFeaturePointsFPTest() throws IOException {
         FeaturePointExportService service = new FeaturePointExportService();
-        Optional<List<FeaturePoint>> featurePoints = loadFeaturePoints();
-        service.exportFeaturePoints(featurePoints.get(), "test_file", "FP");
+        List<FeaturePoint> featurePoints = loadFeaturePoints();
+        service.exportFeaturePoints(featurePoints, "test_file_fp", "FP");
     }
 
-    private Optional<List<FeaturePoint>> loadFeaturePoints() {
-        FeaturePointsCsvLoader service = new FeaturePointsCsvLoader();
-        Optional<List<FeaturePoint>> featurePoints = service.importFeaturePointsCSV(testFileDirectory.toString(), TEST_CSV_FILE);
+    private List<FeaturePoint> loadFeaturePoints() throws IOException {
+        FeaturePointCsvLoader service = new FeaturePointCsvLoader();
+        List<FeaturePoint> featurePoints = service.loadFeaturePoints(MODEL_TEST_FILE_DIRECTORY.toString(), MODEL_FILE);
         return featurePoints;
 
     }
diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointImportServiceTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointImportServiceTest.java
index 803cd1ffb6ce6ee535fb24d1ac69da332d4d54a7..22915793e82762faaf10374badb0320716dd575c 100644
--- a/MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointImportServiceTest.java
+++ b/MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointImportServiceTest.java
@@ -1,20 +1,14 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
 package cz.fidentis.analyst.feature.services;
 
 import cz.fidentis.analyst.feature.FeaturePoint;
 import cz.fidentis.analyst.feature.provider.FeaturePointTypeProvider;
-import cz.fidentis.analyst.mesh.io.MeshObjLoader;
+import cz.fidentis.analyst.feature.services.FeaturePointCsvLoader;
+import cz.fidentis.analyst.feature.services.FeaturePointFpLoader;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.List;
-import java.util.Optional;
-import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.DisplayName;
@@ -24,49 +18,70 @@ import org.junit.jupiter.api.DisplayName;
  * @author Jakub Kolman
  */
 public class FeaturePointImportServiceTest {
-    
-    
+
     private static final Path testFileDirectory = Paths.get("src", "test", "resources", "cz", "fidentis", "analyst", "feature", "services");
     private static final String TEST_CSV_FILE = "00007_01_landmarks.csv";
     private static final String TEST_FP_FILE = "fp_head1_test.fp";
-     
+
+    @DisplayName("Test if CSV file can be read")
     @Test()
     void fileExistsTest() throws IOException {
         File testCsv = new File(testFileDirectory.toFile(), TEST_CSV_FILE);
         assertTrue(testCsv.canRead());
     }
-    
+
     @DisplayName("Test loading a CSV file")
     @Test
-    void importFeaturePointsCSVTest() {
-        Optional<List<FeaturePoint>> featurePoints = loadFeaturePoints();
-        assertTrue(featurePoints.isPresent());
-        assertTrue(featurePoints.get().size() > 0);
-        assertTrue(featurePoints.get().get(0).getX() == -45.3298
-                && featurePoints.get().get(0).getY() == 37.1466
-                && featurePoints.get().get(0).getZ() == -40.5415
-                && featurePoints.get().get(0).getFeaturePointType().equals(
+    void importFeaturePointsCSVTest() throws IOException {
+        List<FeaturePoint> featurePoints = FeaturePointCsvLoader.loadFeaturePoints(testFileDirectory.toString(), TEST_CSV_FILE);
+        assertTrue(featurePoints != null);
+        assertTrue(featurePoints.size() > 0);
+        assertTrue(featurePoints.get(0).getX() == -45.3298
+                && featurePoints.get(0).getY() == 37.1466
+                && featurePoints.get(0).getZ() == -40.5415
+                && featurePoints.get(0).getFeaturePointType().equals(
                         FeaturePointTypeProvider.getInstance().getFeaturePointTypeByCode("EX_R"))
         );
     }
 
-    private Optional<List<FeaturePoint>> loadFeaturePoints() {
-        FeaturePointsCsvLoader service = new FeaturePointsCsvLoader();
-        Optional<List<FeaturePoint>> featurePoints = service.importFeaturePointsCSV(testFileDirectory.toString(), TEST_CSV_FILE);
-        return featurePoints;
-    }
-    
     @DisplayName("Test loading a FP file")
     @Test
-    void importFeaturePointsFPTest() {
-        FeaturePointsFpLoader service = new FeaturePointsFpLoader();
-        Optional<List<FeaturePoint>> featurePoints = service.importFeaturePointsFP(testFileDirectory.toString(), TEST_FP_FILE);
-        assertTrue(featurePoints.isPresent());
-        assertTrue(featurePoints.get().size() > 0);
-        assertTrue(featurePoints.get().get(0).getX() == -40.429775
-                && featurePoints.get().get(0).getY() == 45.756405
-                && featurePoints.get().get(0).getZ() == 37.12462
-                && featurePoints.get().get(0).getFeaturePointType().equals(
+    void importFeaturePointsTest() throws IOException {
+        List<FeaturePoint> featurePoints = FeaturePointFpLoader.loadFeaturePoints(testFileDirectory.toString(), TEST_FP_FILE);
+        assertTrue(featurePoints != null);
+        assertTrue(featurePoints.size() > 0);
+        assertTrue(featurePoints.get(0).getX() == -40.429775
+                && featurePoints.get(0).getY() == 45.756405
+                && featurePoints.get(0).getZ() == 37.12462
+                && featurePoints.get(0).getFeaturePointType().equals(
+                        FeaturePointTypeProvider.getInstance().getFeaturePointTypeByCode("EX_R"))
+        );
+    }
+
+    @DisplayName("Test loading a FP file from generic service")
+    @Test
+    void importFeaturePointsFpFromGenericServiceTest() throws IOException {
+        List<FeaturePoint> featurePoints = FeaturePointImportService.importFeaturePoints(testFileDirectory.toString(), TEST_FP_FILE);
+        assertTrue(featurePoints != null);
+        assertTrue(featurePoints.size() > 0);
+        assertTrue(featurePoints.get(0).getX() == -40.429775
+                && featurePoints.get(0).getY() == 45.756405
+                && featurePoints.get(0).getZ() == 37.12462
+                && featurePoints.get(0).getFeaturePointType().equals(
+                        FeaturePointTypeProvider.getInstance().getFeaturePointTypeByCode("EX_R"))
+        );
+    }
+
+    @DisplayName("Test loading a CSV file from generic service")
+    @Test
+    void importFeaturePointsCsvFromGenericServiceTest() throws IOException {
+        List<FeaturePoint> featurePoints = FeaturePointImportService.importFeaturePoints(testFileDirectory.toString(), TEST_CSV_FILE);
+        assertTrue(featurePoints != null);
+        assertTrue(featurePoints.size() > 0);
+        assertTrue(featurePoints.get(0).getX() == -45.3298
+                && featurePoints.get(0).getY() == 37.1466
+                && featurePoints.get(0).getZ() == -40.5415
+                && featurePoints.get(0).getFeaturePointType().equals(
                         FeaturePointTypeProvider.getInstance().getFeaturePointTypeByCode("EX_R"))
         );
     }
diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/io/MeshObjLoaderTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/io/MeshObjLoaderTest.java
index d910e4ebe390fa059375ba020124e1f0bd96a1b1..cdec3b7c0c2df4153d41edd12989baac3066b6fe 100644
--- a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/io/MeshObjLoaderTest.java
+++ b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/io/MeshObjLoaderTest.java
@@ -175,7 +175,7 @@ public class MeshObjLoaderTest {
     }
     
     private Set<MeshPoint> getPointsInObject(OBJModel model, OBJObject object) {
-        Set<MeshPoint> points = new HashSet();
+        Set<MeshPoint> points = new HashSet<>();
         for (OBJMesh mesh : object.getMeshes()) {
             for (OBJFace face : mesh.getFaces()) {
                 for (OBJDataReference reference : face.getReferences()) {
diff --git a/MeshModel/test_file_csv_landmarks.csv b/MeshModel/test_file_csv_landmarks.csv
new file mode 100644
index 0000000000000000000000000000000000000000..c818665137ad06fcfb8038a8e7d02c70f3218b95
--- /dev/null
+++ b/MeshModel/test_file_csv_landmarks.csv
@@ -0,0 +1,2 @@
+Scan name,EX_R x,EX_R y,EX_R z,EX_L x,EX_L y,EX_L z,EN_R x,EN_R y,EN_R z,EN_L x,EN_L y,EN_L z,PAS_R x,PAS_R y,PAS_R z,PAS_L x,PAS_L y,PAS_L z,PAI_R x,PAI_R y,PAI_R z,PAI_L x,PAI_L y,PAI_L z,G x,G y,G z,SN x,SN y,SN z,AL_R x,AL_R y,AL_R z,AL_L x,AL_L y,AL_L z,N x,N y,N z,PRN x,PRN y,PRN z,LS x,LS y,LS z,STO x,STO y,STO z,LI x,LI y,LI z,CH_R x,CH_R y,CH_R z,CH_L x,CH_L y,CH_L z,CP_R x,CP_R y,CP_R z,CP_L x,CP_L y,CP_L z,SL x,SL y,SL z,GN x,GN y,GN z,GOL_R x,GOL_R y,GOL_R z,GOL_L x,GOL_L y,GOL_L z,ZY_R x,ZY_R y,ZY_R z,ZY_L x,ZY_L y,ZY_L z,PG x,PG y,PG z,T_R x,T_R y,T_R z,T_L x,T_L y,T_L z,SA_R x,SA_R y,SA_R z,SA_L x,SA_L y,SA_L z,SBA_R x,SBA_R y,SBA_R z,SBA_L x,SBA_L y,SBA_L z,PA_R x,PA_R y,PA_R z,PA_L x,PA_L y,PA_L z,OBS_R x,OBS_R y,OBS_R z,OBS_L x,OBS_L y,OBS_L z,OBI_R x,OBI_R y,OBI_R z,OBI_L x,OBI_L y,OBI_L z,PRA_R x,PRA_R y,PRA_R z,PRA_L x,PRA_L y,PRA_L z
+test_file_csv,-45.3298,37.1466,-40.5415,44.3033,36.255,-42.623,-18.5134,33.2336,-36.7921,16.188,32.6379,-37.2197,-34.3363,41.5306,-33.6564,33.8288,39.5634,-34.2531,-34.4132,31.9017,-35.2642,33.5827,30.789,-36.755,0.12959,51.8853,-14.4235,-0.0356107,-13.0827,-16.9983,-16.6623,-4.05884,-19.1798,15.5038,-4.97323,-21.1836,0.044336,39.4236,-19.1853,-0.0291473,0.258132,-0.140334,-0.0901103,-29.1039,-16.7076,0.055705,-35.7511,-21.7819,0.0285089,-44.8791,-21.1852,-28.1537,-35.8802,-32.2677,24.4702,-34.6564,-34.317,-5.68164,-26.7827,-16.8184,5.63171,-26.3173,-17.4413,0.0403775,-52.2879,-27.0041,0.0981629,-80.2827,-43.5233,-57.0806,-39.8906,-118.469,50.4482,-38.958,-118.26,-63.254,40.8951,-53.951,59.7107,38.7682,-58.1024,0.0468024,-61.4376,-25.9881,-78.3702,26.048,-120.74,70.6534,28.1125,-122.519,-91.2689,55.5377,-137.688,87.5631,56.4117,-137.202,-75.6368,-4.45582,-120.828,70.4776,-1.8171,-120.704,-93.2421,34.1812,-155.155,90.0449,35.8349,-155.402,-82.7099,46.6375,-123.483,76.087,46.7891,-123.211,-72.0651,-5.47207,-119.272,64.1992,-3.95897,-118.937,-83.3521,40.1314,-121.805,75.3747,40.0263,-121.781
\ No newline at end of file
diff --git a/MeshModel/test_file_fp_landmarks.fp b/MeshModel/test_file_fp_landmarks.fp
new file mode 100644
index 0000000000000000000000000000000000000000..13e775a3e5c1c38e6348d9fc5d10e575de13dfb7
--- /dev/null
+++ b/MeshModel/test_file_fp_landmarks.fp
@@ -0,0 +1,170 @@
+<!--Saved by software Fidentis Analyst--><facialPoints model="test_file_fp">
+<facialPoint type="1">
+<x>-45.329800</x>
+<y>37.146600</y>
+<z>-40.541500</z>
+<facialPoint type="2">
+<x>44.303300</x>
+<y>36.255000</y>
+<z>-42.623000</z>
+<facialPoint type="3">
+<x>-18.513400</x>
+<y>33.233600</y>
+<z>-36.792100</z>
+<facialPoint type="4">
+<x>16.188000</x>
+<y>32.637900</y>
+<z>-37.219700</z>
+<facialPoint type="5">
+<x>-34.336300</x>
+<y>41.530600</y>
+<z>-33.656400</z>
+<facialPoint type="6">
+<x>33.828800</x>
+<y>39.563400</y>
+<z>-34.253100</z>
+<facialPoint type="7">
+<x>-34.413200</x>
+<y>31.901700</y>
+<z>-35.264200</z>
+<facialPoint type="8">
+<x>33.582700</x>
+<y>30.789000</y>
+<z>-36.755000</z>
+<facialPoint type="9">
+<x>0.129590</x>
+<y>51.885300</y>
+<z>-14.423500</z>
+<facialPoint type="10">
+<x>-0.035611</x>
+<y>-13.082700</y>
+<z>-16.998300</z>
+<facialPoint type="11">
+<x>-16.662300</x>
+<y>-4.058840</y>
+<z>-19.179800</z>
+<facialPoint type="12">
+<x>15.503800</x>
+<y>-4.973230</y>
+<z>-21.183600</z>
+<facialPoint type="13">
+<x>0.044336</x>
+<y>39.423600</y>
+<z>-19.185300</z>
+<facialPoint type="14">
+<x>-0.029147</x>
+<y>0.258132</y>
+<z>-0.140334</z>
+<facialPoint type="15">
+<x>-0.090110</x>
+<y>-29.103900</y>
+<z>-16.707600</z>
+<facialPoint type="16">
+<x>0.055705</x>
+<y>-35.751100</y>
+<z>-21.781900</z>
+<facialPoint type="17">
+<x>0.028509</x>
+<y>-44.879100</y>
+<z>-21.185200</z>
+<facialPoint type="18">
+<x>-28.153700</x>
+<y>-35.880200</y>
+<z>-32.267700</z>
+<facialPoint type="19">
+<x>24.470200</x>
+<y>-34.656400</y>
+<z>-34.317000</z>
+<facialPoint type="20">
+<x>-5.681640</x>
+<y>-26.782700</y>
+<z>-16.818400</z>
+<facialPoint type="21">
+<x>5.631710</x>
+<y>-26.317300</y>
+<z>-17.441300</z>
+<facialPoint type="22">
+<x>0.040378</x>
+<y>-52.287900</y>
+<z>-27.004100</z>
+<facialPoint type="23">
+<x>0.098163</x>
+<y>-80.282700</y>
+<z>-43.523300</z>
+<facialPoint type="24">
+<x>-57.080600</x>
+<y>-39.890600</y>
+<z>-118.469000</z>
+<facialPoint type="25">
+<x>50.448200</x>
+<y>-38.958000</y>
+<z>-118.260000</z>
+<facialPoint type="26">
+<x>-63.254000</x>
+<y>40.895100</y>
+<z>-53.951000</z>
+<facialPoint type="27">
+<x>59.710700</x>
+<y>38.768200</y>
+<z>-58.102400</z>
+<facialPoint type="28">
+<x>0.046802</x>
+<y>-61.437600</y>
+<z>-25.988100</z>
+<facialPoint type="29">
+<x>-78.370200</x>
+<y>26.048000</y>
+<z>-120.740000</z>
+<facialPoint type="30">
+<x>70.653400</x>
+<y>28.112500</y>
+<z>-122.519000</z>
+<facialPoint type="31">
+<x>-91.268900</x>
+<y>55.537700</y>
+<z>-137.688000</z>
+<facialPoint type="32">
+<x>87.563100</x>
+<y>56.411700</y>
+<z>-137.202000</z>
+<facialPoint type="33">
+<x>-75.636800</x>
+<y>-4.455820</y>
+<z>-120.828000</z>
+<facialPoint type="34">
+<x>70.477600</x>
+<y>-1.817100</y>
+<z>-120.704000</z>
+<facialPoint type="35">
+<x>-93.242100</x>
+<y>34.181200</y>
+<z>-155.155000</z>
+<facialPoint type="36">
+<x>90.044900</x>
+<y>35.834900</y>
+<z>-155.402000</z>
+<facialPoint type="37">
+<x>-82.709900</x>
+<y>46.637500</y>
+<z>-123.483000</z>
+<facialPoint type="38">
+<x>76.087000</x>
+<y>46.789100</y>
+<z>-123.211000</z>
+<facialPoint type="39">
+<x>-72.065100</x>
+<y>-5.472070</y>
+<z>-119.272000</z>
+<facialPoint type="40">
+<x>64.199200</x>
+<y>-3.958970</y>
+<z>-118.937000</z>
+<facialPoint type="41">
+<x>-83.352100</x>
+<y>40.131400</y>
+<z>-121.805000</z>
+<facialPoint type="42">
+<x>75.374700</x>
+<y>40.026300</y>
+<z>-121.781000</z>
+</facialPoints>
\ No newline at end of file
diff --git a/README.md b/README.md
index debd2b7b8d9bc395b6fd6b3705d265ddd2cb8b49..f6a58a99c3d21792534410040edec253bf38d54f 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ This project is being developed at Masaryk University, Brno, as collaborative pr
 
 ## Requirements
 
-*  Oracle JDK 11 (JOGL 2.3 does not work with JDK >11 properly, at leat at Linux; should be working again in ongoing JOGL 2.4)
+*  [Oracle JDK 11](https://www.oracle.com/java/technologies/downloads/#java11) (JOGL 2.3 does not work with JDK >11 properly, at leat at Linux; should be working again in ongoing JOGL 2.4)
 *  [Maven](https://www.mkyong.com/maven/how-to-install-maven-in-windows/) for compilation
 *  IDE for development, e.g. NetBeans or IntelliJ IDEA
 
diff --git a/Renderer/pom.xml b/Renderer/pom.xml
index 6ee00742a4099056b72776a9a28a6a5406d40ef0..fbeaf205110c89ec644378e133cf850253c03f6f 100644
--- a/Renderer/pom.xml
+++ b/Renderer/pom.xml
@@ -4,7 +4,7 @@
     <parent>
         <groupId>cz.fidentis</groupId>
         <artifactId>FIDENTIS-Analyst-parent</artifactId>
-        <version>2.1.4</version>
+        <version>2021.10</version>
     </parent>
     <artifactId>Renderer</artifactId>
     <packaging>nbm</packaging>
diff --git a/VERSION.txt b/VERSION.txt
index e6629b4d11c6d890ea7c256ad38a0bc9dfcecbd2..18fef829e70598ff646b02ea090b52bd294b0d14 100644
--- a/VERSION.txt
+++ b/VERSION.txt
@@ -1 +1 @@
-2.1.4 Symmetry plane computation and visualization 
+2021.10 Weighted Hausdorff distance
diff --git a/application/pom.xml b/application/pom.xml
index 51b10c2a9e18f21929340da51dc6e5915fa7b468..4c825ad99f26461c7001a8c099262dbdab5efc44 100644
--- a/application/pom.xml
+++ b/application/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>cz.fidentis</groupId>
         <artifactId>FIDENTIS-Analyst-parent</artifactId>
-        <version>2.1.4</version>
+        <version>2021.10</version>
     </parent>
 
     <artifactId>FIDENTIS-Analyst-app</artifactId>
diff --git a/branding/pom.xml b/branding/pom.xml
index 91815f94b8ba1be51dcd584a1f7ce97e0c701bc5..312a83e96f79880a06a1e9f9fc47221bc5f176a3 100644
--- a/branding/pom.xml
+++ b/branding/pom.xml
@@ -5,7 +5,7 @@
   <parent>
       <groupId>cz.fidentis</groupId>
       <artifactId>FIDENTIS-Analyst-parent</artifactId>
-      <version>2.1.4</version>
+      <version>2021.10</version>
   </parent>
 
   <artifactId>FIDENTIS-Analyst-branding</artifactId>
diff --git a/pom.xml b/pom.xml
index b7b2917ce429ab7e73bc61647ebf844dfafc2a1e..2f074ff58002a311ce74a68fa301ef39a1009ab7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
 
     <groupId>cz.fidentis</groupId>
     <artifactId>FIDENTIS-Analyst-parent</artifactId>
-    <version>2.1.4</version>
+    <version>2021.10</version>
     <packaging>pom</packaging>
 
     <name>FIDENTIS-Analyst-2</name>
diff --git a/release.sh b/release.sh
index fcc0d7728241149325c910bc7fb8887fb5f03900..1abcb44fb4183a61687dae5ed601e28ed2624554 100755
--- a/release.sh
+++ b/release.sh
@@ -30,6 +30,6 @@ git log  --pretty=format:'%h -- %s' $LAST_TAG..HEAD --graph > CHANGELOG.md
 git add CHANGELOG.md
 git commit -m "CHANGELOG.md file updated with commits between the current and previous tag."
 
-git tag -a v$VERSION -m "$TAG_MESSAGE"
+git tag -a $VERSION -m "$TAG_MESSAGE"
 git config --global push.followTags true
 git push