Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
M
Mappe - programmering 2
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Sverre Grønhaug Halvorsen
Mappe - programmering 2
Commits
ac37398a
Commit
ac37398a
authored
1 year ago
by
Nicklas Persia Tufteland
Browse files
Options
Downloads
Plain Diff
Merge branch '23-enable-zoom-on-transformation' into 'dev'
Resolve "Enable zoom on Transformation" Closes
#23
See merge request
!32
parents
b9c934d2
da4496f4
Branches
Branches containing commit
No related tags found
2 merge requests
!41
final delivery
,
!32
Resolve "Enable zoom on Transformation"
Pipeline
#287930
passed
1 year ago
Stage: build
Stage: test
Stage: package
Stage: deploy
Changes
2
Pipelines
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/main/java/edu/ntnu/idatt2003/view/ChaosImage.java
+165
-23
165 additions, 23 deletions
src/main/java/edu/ntnu/idatt2003/view/ChaosImage.java
src/main/java/edu/ntnu/idatt2003/view/MainPageView.java
+5
-5
5 additions, 5 deletions
src/main/java/edu/ntnu/idatt2003/view/MainPageView.java
with
170 additions
and
28 deletions
src/main/java/edu/ntnu/idatt2003/view/ChaosImage.java
+
165
−
23
View file @
ac37398a
package
edu.ntnu.idatt2003.view
;
package
edu.ntnu.idatt2003.view
;
import
edu.ntnu.idatt2003.model.ChaosCanvas
;
import
edu.ntnu.idatt2003.model.ChaosCanvas
;
import
javafx.beans.property.ObjectProperty
;
import
javafx.beans.property.SimpleObjectProperty
;
import
javafx.geometry.Point2D
;
import
javafx.scene.image.ImageView
;
import
javafx.scene.image.WritableImage
;
import
javafx.scene.image.WritableImage
;
import
javafx.scene.input.ScrollEvent
;
import
javafx.scene.layout.Pane
;
import
javafx.scene.layout.StackPane
;
import
javafx.scene.paint.Color
;
import
javafx.scene.paint.Color
;
import
javafx.scene.shape.Rectangle
;
import
javafx.scene.transform.Scale
;
/**
/**
* The ChaosImage class provides methods for creating and manipulating images based on a
* The ChaosImage class provides methods for creating and manipulating images based on a
...
@@ -10,18 +19,23 @@ import javafx.scene.paint.Color;
...
@@ -10,18 +19,23 @@ import javafx.scene.paint.Color;
* an image by a specified factor.
* an image by a specified factor.
*/
*/
public
class
ChaosImage
{
class
ChaosImage
{
private
static
final
int
MAX_SCALE
=
5
;
private
static
final
int
MIN_SCALE
=
1
;
private
static
final
double
ZOOM_FACTOR
=
1.05
;
private
ChaosImage
()
{
}
/**
/**
* Creates a WritableImage from a given ChaosCanvas object.
* Creates a WritableImage from a given ChaosCanvas object.
* Each element in the canvas array is mapped to a pixel in the image,
* Each element in the canvas array is mapped to a pixel in the image,
* where a value of 1 is black and 0 is white.
* where a value of 1 is black and 0 is white.
*
*
* @param chaosCanvas The ChaosCanvas object containing the data for the image.
* @param chaosCanvas The ChaosCanvas object containing the data for the image.
* @return A
WritableImage
representing the canvas data.
* @return A
Pane containing the image generated
representing the canvas data.
*/
*/
public
static
WritableImag
e
createImageFromCanvas
(
ChaosCanvas
chaosCanvas
)
{
public
static
Pan
e
createImageFromCanvas
(
ChaosCanvas
chaosCanvas
)
{
int
width
=
chaosCanvas
.
getWidth
();
int
width
=
chaosCanvas
.
getWidth
();
int
height
=
chaosCanvas
.
getHeight
();
int
height
=
chaosCanvas
.
getHeight
();
WritableImage
image
=
new
WritableImage
(
width
,
height
);
WritableImage
image
=
new
WritableImage
(
width
,
height
);
...
@@ -36,34 +50,162 @@ public class ChaosImage {
...
@@ -36,34 +50,162 @@ public class ChaosImage {
}
}
}
}
}
}
ImageView
imageView
=
new
ImageView
(
image
);
imageView
.
setFitWidth
(
600
);
imageView
.
setFitHeight
(
600
);
Pane
pane
=
new
Pane
(
imageView
);
pane
.
setMaxHeight
(
height
);
pane
.
setMaxWidth
(
width
);
StackPane
.
setAlignment
(
imageView
,
javafx
.
geometry
.
Pos
.
CENTER
);
pane
.
setClip
(
new
Rectangle
(
600
,
600
));
enableZoom
(
imageView
);
enablePan
(
imageView
);
return
pane
;
}
return
image
;
/**
* Enables zooming on an ImageView object, using a Scale transform.
*
* @param imageView The ImageView object to enable zooming on.
*/
private
static
void
enableZoom
(
ImageView
imageView
)
{
Scale
scaleTransform
=
new
Scale
();
imageView
.
getTransforms
().
add
(
scaleTransform
);
imageView
.
setOnScroll
(
e
->
zoom
(
imageView
,
e
));
}
}
/**
* Enables panning on an ImageView object, by translating the image based on mouse drag events
* and the last mouse coordinates. The panning is limited to the edges of the image.
*
* @param imageView The ImageView object to enable panning on.
*/
private
static
void
enablePan
(
ImageView
imageView
)
{
final
ObjectProperty
<
Point2D
>
lastMouseCoordinates
=
new
SimpleObjectProperty
<>();
imageView
.
setOnMousePressed
(
e
->
lastMouseCoordinates
.
set
(
new
Point2D
(
e
.
getX
(),
e
.
getY
())));
imageView
.
setOnMouseDragged
(
e
->
{
double
deltaX
=
e
.
getX
()
-
lastMouseCoordinates
.
get
().
getX
();
double
deltaY
=
e
.
getY
()
-
lastMouseCoordinates
.
get
().
getY
();
int
newX
=
(
int
)
(
imageView
.
getTranslateX
()
+
deltaX
);
int
newY
=
(
int
)
(
imageView
.
getTranslateY
()
+
deltaY
);
checkEdgesPan
(
imageView
,
newX
,
newY
);
});
}
/**
/**
* Scales a given WritableImage by a specified factor.
* Zooms in or out on an ImageView object based on the scroll event, by scaling the image.
* The method creates a new image with dimensions scaled by the scaleFactor and copies the color
* The zooming is centered around the mouse position.
* data from the original image.
*
*
* @param image The original WritableImage to be scaled.
* @param imageView The ImageView object to enable panning on.
* @param scaleFactor The factor by which to scale the image. A scaleFactor > 1 enlarges the
* image,while a scaleFactor < 1 reduces its size.
* @return A new WritableImage that is scaled by the specified factor.
*/
*/
private
static
void
zoom
(
ImageView
imageView
,
ScrollEvent
e
)
{
double
zoomFactor
=
calculateZoomFactor
(
e
.
getDeltaY
());
public
static
WritableImage
scaleImage
(
WritableImage
image
,
double
scaleFactor
)
{
final
double
scaleBefore
=
imageView
.
getScaleX
();
int
newWidth
=
(
int
)
(
image
.
getWidth
()
*
scaleFactor
);
double
scale
=
imageView
.
getScaleX
()
*
zoomFactor
;
int
newHeight
=
(
int
)
(
image
.
getHeight
()
*
scaleFactor
);
WritableImage
scaledImage
=
new
WritableImage
(
newWidth
,
newHeight
);
scale
=
clamp
(
scale
,
MIN_SCALE
,
MAX_SCALE
);
for
(
int
y
=
0
;
y
<
newHeight
;
y
++)
{
for
(
int
x
=
0
;
x
<
newWidth
;
x
++)
{
imageView
.
setScaleX
(
scale
);
Color
originalColor
=
image
.
getPixelReader
()
imageView
.
setScaleY
(
scale
);
.
getColor
((
int
)
(
x
/
scaleFactor
),
(
int
)
(
y
/
scaleFactor
));
scaledImage
.
getPixelWriter
().
setColor
(
x
,
y
,
originalColor
);
double
mouseX
=
e
.
getX
()
-
imageView
.
getFitWidth
()
/
2
;
double
mouseY
=
e
.
getY
()
-
imageView
.
getFitHeight
()
/
2
;
double
newTranslateX
=
calculateNewTranslate
(
mouseX
,
scale
,
scaleBefore
,
imageView
.
getTranslateX
());
double
newTranslateY
=
calculateNewTranslate
(
mouseY
,
scale
,
scaleBefore
,
imageView
.
getTranslateY
());
checkEdgesZoom
(
imageView
,
newTranslateX
,
newTranslateY
);
}
}
/**
* Checks if the image is within the bounds of the ImageView after zooming.
* If the image is outside the bounds, the image is translated back into the bounds.
*
* @param imageView The ImageView object to check the edges of.
* @param newX The new x-coordinate of the image.
* @param newY The new y-coordinate of the image.
*/
private
static
void
checkEdgesZoom
(
ImageView
imageView
,
double
newX
,
double
newY
)
{
double
imageWidthHalf
=
imageView
.
getFitWidth
()
/
2
;
double
imageHeightHalf
=
imageView
.
getFitHeight
()
/
2
;
if
((
newX
+
imageWidthHalf
)
/
imageView
.
getScaleX
()
<=
imageWidthHalf
&&
(
newX
-
imageWidthHalf
)
/
imageView
.
getScaleX
()
>=
-
imageWidthHalf
)
{
imageView
.
setTranslateX
(
newX
);
}
else
if
(
imageView
.
getScaleX
()
<=
1
)
{
imageView
.
setTranslateX
(
0
);
}
if
((
newY
+
imageHeightHalf
)
/
imageView
.
getScaleY
()
<=
imageHeightHalf
&&
(
newY
-
imageHeightHalf
)
/
imageView
.
getScaleY
()
>=
-
imageHeightHalf
)
{
imageView
.
setTranslateY
(
newY
);
}
else
if
(
imageView
.
getScaleY
()
<=
1
)
{
imageView
.
setTranslateY
(
0
);
}
}
return
scaledImage
;
}
}
/**
* Checks if the image is within the bounds of the ImageView after panning.
* If the image is outside the bounds, the image is not moved.
*
* @param imageView The ImageView object to check the edges of.
* @param newX The new x-coordinate of the image.
* @param newY The new y-coordinate of the image.
*/
private
static
void
checkEdgesPan
(
ImageView
imageView
,
double
newX
,
double
newY
)
{
double
imageWidthHalf
=
imageView
.
getFitWidth
()
/
2
;
double
imageHeightHalf
=
imageView
.
getFitHeight
()
/
2
;
if
((
newX
+
imageWidthHalf
)
/
imageView
.
getScaleX
()
<=
imageWidthHalf
&&
(
newX
-
imageWidthHalf
)
/
imageView
.
getScaleX
()
>=
-
imageWidthHalf
)
{
imageView
.
setTranslateX
(
newX
);
}
if
((
newY
+
imageHeightHalf
)
/
imageView
.
getScaleY
()
<=
imageHeightHalf
&&
(
newY
-
imageHeightHalf
)
/
imageView
.
getScaleY
()
>=
-
imageHeightHalf
)
{
imageView
.
setTranslateY
(
newY
);
}
}
/**
* Calculates the zoom factor based on the way the mouse wheel is scrolled.
* if deltaY is negative, the image is zoomed out, otherwise it is zoomed in.
* The zoom factor is calculated as 1.05, for zooming in, and 1/1.05 for zooming out.
*
* @param deltaY The amount the mouse wheel is scrolled.
* @return The calculated zoom factor.
*/
private
static
double
calculateZoomFactor
(
double
deltaY
)
{
return
deltaY
<
0
?
1
/
ZOOM_FACTOR
:
ZOOM_FACTOR
;
}
/**
* Calculates the new translation of the image after zooming, based on the mouse position,
* the scale factor after zooming, the scale factor before zooming, and the translation before
* zooming.
*
* @param mousePosition The position of the mouse.
* @param scale The scale factor after zooming.
* @param scaleBefore The scale factor before zooming.
* @param translateBefore The translation before zooming.
* @return The new translation of the image.
*/
private
static
double
calculateNewTranslate
(
double
mousePosition
,
double
scale
,
double
scaleBefore
,
double
translateBefore
)
{
return
-
mousePosition
*
scale
+
mousePosition
*
scaleBefore
+
translateBefore
;
}
/**
* Clamp a value between a minimum and maximum value. Makes sure the value is within the bounds.
*
* @param value The value to clamp.
* @param min The minimum value.
* @param max The maximum value.
* @return The clamped value.
*/
private
static
double
clamp
(
double
value
,
double
min
,
double
max
)
{
return
Math
.
max
(
min
,
Math
.
min
(
max
,
value
));
}
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
src/main/java/edu/ntnu/idatt2003/view/MainPageView.java
+
5
−
5
View file @
ac37398a
...
@@ -25,7 +25,6 @@ import javafx.scene.control.Button;
...
@@ -25,7 +25,6 @@ import javafx.scene.control.Button;
import
javafx.scene.control.ButtonType
;
import
javafx.scene.control.ButtonType
;
import
javafx.scene.control.ComboBox
;
import
javafx.scene.control.ComboBox
;
import
javafx.scene.control.TextField
;
import
javafx.scene.control.TextField
;
import
javafx.scene.image.ImageView
;
import
javafx.scene.layout.BorderPane
;
import
javafx.scene.layout.BorderPane
;
import
javafx.scene.layout.HBox
;
import
javafx.scene.layout.HBox
;
import
javafx.scene.layout.Pane
;
import
javafx.scene.layout.Pane
;
...
@@ -92,10 +91,11 @@ public class MainPageView extends Scene implements ChaosGameObserver {
...
@@ -92,10 +91,11 @@ public class MainPageView extends Scene implements ChaosGameObserver {
* The button container contains 7 buttons.
* The button container contains 7 buttons.
*/
*/
private
void
createPageContainer
()
{
private
void
createPageContainer
()
{
HBox
contentContainer
=
new
HBox
(
HBox
contentContainer
=
new
HBox
(
createAddTransformationPanel
(),
createAddTransformationPanel
(),
new
ImageView
(
ChaosImage
ChaosImage
.
createImageFromCanvas
(
controller
.
getGame
().
getCanvas
()),
.
createImageFromCanvas
(
controller
.
getGame
().
getCanvas
())),
mouseBox
());
mouseBox
()
);
pageContainer
.
getChildren
().
addAll
(
contentContainer
,
createButtonContainer
());
pageContainer
.
getChildren
().
addAll
(
contentContainer
,
createButtonContainer
());
pageContainer
.
getStyleClass
().
add
(
"page-container"
);
pageContainer
.
getStyleClass
().
add
(
"page-container"
);
pageContainer
.
setMaxHeight
(
Sizes
.
SCREEN_HEIGHT
-
PAGE_CONTAINER_MARGIN
);
pageContainer
.
setMaxHeight
(
Sizes
.
SCREEN_HEIGHT
-
PAGE_CONTAINER_MARGIN
);
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment