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>l + * @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> + * @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, "{key}")"/> + <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.addButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> </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, "{key}")"/> + <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.removeButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> </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, "{key}")"/> + <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.selectAllButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> </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, "{key}")"/> + <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.deselectAllButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> </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, "{key}")"/> + <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.inflateButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> </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, "{key}")"/> + <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.oneOnOneButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> </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, "{key}")"/> + <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.analyseButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> </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);
jTable1.getTableHeader().setBackground(new java.awt.Color(204,204,204));
jTable1.getTableHeader().setFont(new java.awt.Font("Tahoma", 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();
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);
 }
 }
 }
});"> + <Connection code="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;
 }
}" 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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> - </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, "{key}")"/> - </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, "{key}")"/> - </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, "{key}")"/> - </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, "{key}")"/> - </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, "{key}")"/> - </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, "{key}")"/> - </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, "{key}")"/> - </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, "{key}")"/> - </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, "{key}")"/> - </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, "{key}")"/> - </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, "{key}")"/> - </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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="<String>"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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="<String>"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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, "{key}")"/> + </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