可以鼠标拖动查看
滚轮可以放大某一块
右下角显示当前鼠标的位置
左下角显示当前屏幕显示的位置,由于是复平面,所以横轴是石洲,纵轴是虚轴
左上角菜单可以改变清晰度,1会很卡,可能每一帧要运行半分钟,看电脑配置
具体实现代码或软件加QQ群 : 302493982 获取
本demo是用scala写的 因为可以重载操作运算符,Qt/c++有点麻烦就没用
package rsslosc.x_4__1.scala
class Complex(val a: Double, val b: Double) {
def getA: Double = a
def getB: Double = b
def +(complex: Complex): Complex = {
val c = complex.getA
val d = complex.getB
new Complex(a + c, b + d)
}
def -(complex: Complex): Complex = {
val c = complex.getA
val d = complex.getB
new Complex(a - c, b - d)
}
def *(complex: Complex): Complex = {
val c = complex.getA
val d = complex.getB
new Complex(a * c - b * d, b * c + a * d)
}
def /(complex: Complex): Complex = {
val c = complex.getA
val d = complex.getB
new Complex((a * c + b * d) / (c * c + d * d), (b * c - a * d) / (c * c + d * d))
}
def ^(n: Long): Complex = {
if (n < 1) {
return new Complex(0, 0)
}
var n_ = n
var that = this
var ans = new Complex(1, 0)
while (n_ > 0) {
if ((n_ & 1) == 1) {
ans = ans * that
}
n_ >>= 1
that = that * that
}
ans
}
def distance(complex: Complex): Double = {
val c = complex.getA
val d = complex.getB
Math.sqrt(Math.pow(a - c, 2) + Math.pow(b - d, 2))
}
override def toString: String = {
if (b > 0) return a + " + " + b + " i"
else if (b < 0) return a + " - " + -b + " i"
a + ""
}
}
object Complex {
def apply(a: Double, b: Double): Complex = new Complex(a, b)
}
package rsslosc.x_4__1.scala
class ChooseColor {
def color(p: Complex): String = {
var point: Complex = p
var min: Double = 0x3f3f3f3f
var d_1: Double = 0
var d__1: Double = 0
var d_i: Double = 0
var d__i: Double = 0
var mark = 0
while (min > 1e-2 && mark < 30) {
val fenzi = (point ^ 4) - Complex(1, 0)
val fenmu = (point ^ 3) * Complex(4, 0)
point = point - (fenzi / fenmu)
d_1 = point distance Complex(1, 0)
d__1 = point distance Complex(-1, 0)
d_i = point distance Complex(0, 1)
d__i = point distance Complex(0, -1)
min = Math.min(d_1, Math.min(d__1, Math.min(d_i, d__i)))
mark += 1
}
if (d_1 - min < 1e-2) return "1"
if (d__1 - min < 1e-2) return "-1"
if (d_i - min < 1e-2) return "i"
"-i"
}
}
package rsslosc.x_4__1.scala
import javafx.application.Application
import javafx.scene.Scene
import javafx.scene.control.{
Label, Menu, MenuBar, MenuItem}
import javafx.scene.input.MouseEvent
import javafx.scene.layout._
import javafx.scene.paint.Color
import javafx.scene.shape.Rectangle
import javafx.stage.Stage
object Draw {
def main(args: Array[String]): Unit = {
Application.launch(classOf[Draw], args: _*)
}
}
class Draw extends Application {
val X: Int = 1000 //画布长度
val Y: Int = 700 //画布宽度
var grainSize: Int = 5 //精度 数值越大,精度越小
var init_x: Double = -150 //初始x坐标
var init_y: Double = -100 //初始y坐标
var rangeAccuracy_a: Int = 3 //缩放比例分子
var rangeAccuracy_b: Int = 10 //缩放比例分母
override def start(primaryStage: Stage): Unit = {
val vBox: VBox = new VBox
val hBox: HBox = new HBox
val labelLeft: Label = new Label
val pane: Pane = new Pane
HBox.setHgrow(pane, Priority.ALWAYS)
val labelRight: Label = new Label
hBox.getChildren.addAll(labelLeft, pane, labelRight)
val anchorPane: AnchorPane = new AnchorPane
val menuBar: MenuBar = new MenuBar
val menuChange: Menu = new Menu("_Change")
val menuChangeGrainSize: Menu = new Menu("change grain size")
val menuItemChangeGrainSize_1: MenuItem = new MenuItem("1")
val menuItemChangeGrainSize_2: MenuItem = new MenuItem("2")
val menuItemChangeGrainSize_3: MenuItem = new MenuItem("3")
val menuItemChangeGrainSize_4: MenuItem = new MenuItem("4")
menuChangeGrainSize.getItems.addAll(menuItemChangeGrainSize_1, menuItemChangeGrainSize_2,
menuItemChangeGrainSize_3, menuItemChangeGrainSize_4)
menuItemChangeGrainSize_1.setOnAction(_ => {
grainSize = 1
anchorPane.getChildren.remove(0 , anchorPane.getChildren.size())
anchorPane.getChildren.addAll(drawImg(): _*)
})
menuItemChangeGrainSize_2.setOnAction(_ => {
grainSize = 2
anchorPane.getChildren.remove(0 , anchorPane.getChildren.size())
anchorPane.getChildren.addAll(drawImg(): _*)
})
menuItemChangeGrainSize_3.setOnAction(_ => {
grainSize = 3
anchorPane.getChildren.remove(0 , anchorPane.getChildren.size())
anchorPane.getChildren.addAll(drawImg(): _*)
})
menuItemChangeGrainSize_4.setOnAction(_ => {
grainSize = 4
anchorPane.getChildren.remove(0 , anchorPane.getChildren.size())
anchorPane.getChildren.addAll(drawImg(): _*)
})
menuChange.getItems.add(menuChangeGrainSize)
menuBar.getMenus.add(menuChange)
var moveBeginX: Double = 0
var moveBeginY: Double = 0
anchorPane.setOnScroll(e => {
val oldRangeAccuracy = rangeAccuracy_a.doubleValue() / rangeAccuracy_b.doubleValue()
if (e.getTextDeltaY > 0) rangeAccuracy_a -= 1 else rangeAccuracy_a += 1
if (rangeAccuracy_a == 0) {
rangeAccuracy_a = 9
rangeAccuracy_b *= 10
}
if (rangeAccuracy_a == 10) {
rangeAccuracy_a = 1
rangeAccuracy_b /= 10
}
val newRangeAccuracy = rangeAccuracy_a.doubleValue() / rangeAccuracy_b.doubleValue()
val changeAccuracy = oldRangeAccuracy - newRangeAccuracy
init_x += changeAccuracy * e.getX
init_y += changeAccuracy * e.getY
anchorPane.getChildren.clear()
anchorPane.getChildren.addAll(drawImg(): _*)
writeLabel(labelLeft)
})
anchorPane.setOnMouseMoved(e => {
writeNowLocation(labelRight,e)
})
anchorPane.setOnMouseExited(_ => {
labelRight.setText("")
})
anchorPane.setOnMousePressed(e => {
moveBeginX = e.getX
moveBeginY = e.getY
})
anchorPane.setOnMouseReleased(e => {
init_x -= (e.getX - moveBeginX) * (rangeAccuracy_a.doubleValue() / rangeAccuracy_b.doubleValue())
init_y -= (e.getY - moveBeginY) * (rangeAccuracy_a.doubleValue() / rangeAccuracy_b.doubleValue())
anchorPane.getChildren.clear()
anchorPane.getChildren.addAll(drawImg(): _*)
writeLabel(labelLeft)
})
writeLabel(labelLeft)
anchorPane.getChildren.addAll(drawImg(): _*)
vBox.getChildren.addAll(menuBar, anchorPane, hBox)
primaryStage.setScene(new Scene(vBox, X, Y + 50))
primaryStage.show()
}
def writeNowLocation(label: Label, e: MouseEvent): Unit = {
val nowAccuracy = rangeAccuracy_a.doubleValue() / rangeAccuracy_b.doubleValue()
label.setText("当前位置: " + (init_x + e.getX * nowAccuracy).formatted("%.4f") +
" + " + (-init_y - e.getY * nowAccuracy).formatted("%.4f") + " i ")
}
def writeLabel(label: Label): Unit = {
val nowAccuracy = rangeAccuracy_a.doubleValue() / rangeAccuracy_b.doubleValue()
label.setText("实轴 : " + init_x.formatted("%.4f") + " ~ " + (init_x + nowAccuracy * X).formatted("%.4f") +
" 虚轴 : " + (-init_y - nowAccuracy * Y).formatted("%.4f") + " i ~ " + (-init_y).formatted("%.4f") + " i")
}
def drawImg(): Array[Rectangle] = {
val chooseColor: ChooseColor = new ChooseColor
val rectangle: Array[Rectangle] = new Array[Rectangle]((X / grainSize) * (Y / grainSize))
var index: Int = 0
val rangeAccuracy: Double = rangeAccuracy_a.doubleValue() / rangeAccuracy_b.doubleValue()
for (i <- 0 until X / grainSize) {
for (j <- 0 until Y / grainSize) {
rectangle(index) = new Rectangle(i * grainSize, j * grainSize, grainSize, grainSize)
chooseColor.color(
new Complex(init_x + rangeAccuracy * i * grainSize, init_y + rangeAccuracy * j * grainSize)
) match {
case "1" => rectangle(index).setFill(Color.RED)
case "-1" => rectangle(index).setFill(Color.BLUE)
case "i" => rectangle(index).setFill(Color.GREEN)
case "-i" => rectangle(index).setFill(Color.ORANGE)
}
index += 1
}
}
rectangle
}
}
有个问题 : 改变清晰度内存不减,有大佬来帮忙看看
System.gc() 没用
anchorPane.getChildren.clear() 没用