gpt4 book ai didi

java - 仅渲染与主圆相交的圆的段/区域

转载 作者:搜寻专家 更新时间:2023-10-31 20:15:46 27 4
gpt4 key购买 nike

我非常喜欢数学(或者你们大多数人会说的“数学”!),但我还没有达到知道这个问题答案的程度。我有一个主圆,它可以在显示器上的任何 x 和 y 处有一个中心点。其他圆圈将随意在显示器周围移动,但在任何给定的渲染方法调用中,我不仅要渲染那些与主圆相交的圆,而且还只渲染在主圆内可见的圆段。一个类比是转换在现实生活中的物体上的阴影,而我只想画出那个物体被“照亮”的部分。

我想最好在 Java 中执行此操作,但如果您有原始公式,我们将不胜感激。我想知道如何在 Java 中绘制形状并填充它,我确定在带有圆弧或其他东西的折线上一定有一些变化?

非常感谢

最佳答案

AB 为2 intersection points (没有或者只有1个拦截点可以忽略)

然后计算circular line segment的长度在 AB 之间。

根据这些信息,您应该能够使用 Graphics' drawArc(...) 绘制圆弧方法(如果我没记错的话……)。

编辑

好吧,您甚至不需要圆形线段的长度。我有线相交代码,所以我围绕它构建了一个小 GUI,你如何绘制/查看这种相交圆的 ARC(代码中有一些注释):

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Arc2D;

/**
* @author: Bart Kiers
*/
public class GUI extends JFrame {

private GUI() {
super("Circle Intersection Demo");
initGUI();
}

private void initGUI() {
super.setSize(600, 640);
super.setDefaultCloseOperation(EXIT_ON_CLOSE);
super.setLayout(new BorderLayout(5, 5));

final Grid grid = new Grid();

grid.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
Point p = new Point(e.getX(), e.getY()).toCartesianPoint(grid.getWidth(), grid.getHeight());
grid.showDraggedCircle(p);
}
});

grid.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
Point p = new Point(e.getX(), e.getY()).toCartesianPoint(grid.getWidth(), grid.getHeight());
grid.released(p);
}

@Override
public void mousePressed(MouseEvent e) {
Point p = new Point(e.getX(), e.getY()).toCartesianPoint(grid.getWidth(), grid.getHeight());
grid.pressed(p);
}
});

super.add(grid, BorderLayout.CENTER);
super.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new GUI();
}
});
}

private static class Grid extends JPanel {

private Circle c1 = null;
private Circle c2 = null;
private Point screenClick = null;
private Point currentPosition = null;

public void released(Point p) {
if (c1 == null || c2 != null) {
c1 = new Circle(screenClick, screenClick.distance(p));
c2 = null;
} else {
c2 = new Circle(screenClick, screenClick.distance(p));
}
screenClick = null;
repaint();
}

public void pressed(Point p) {
if(c1 != null && c2 != null) {
c1 = null;
c2 = null;
}
screenClick = p;
repaint();
}

@Override
public void paintComponent(Graphics g) {

Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, super.getWidth(), super.getHeight());

final int W = super.getWidth();
final int H = super.getHeight();
g2d.setColor(Color.LIGHT_GRAY);
g2d.drawLine(0, H / 2, W, H / 2); // x-axis
g2d.drawLine(W / 2, 0, W / 2, H); // y-axis

if (c1 != null) {
g2d.setColor(Color.RED);
c1.drawOn(g2d, W, H);
}

if (c2 != null) {
g2d.setColor(Color.ORANGE);
c2.drawOn(g2d, W, H);
}

if (screenClick != null && currentPosition != null) {
g2d.setColor(Color.DARK_GRAY);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
Circle temp = new Circle(screenClick, screenClick.distance(currentPosition));
temp.drawOn(g2d, W, H);
currentPosition = null;
}

if (c1 != null && c2 != null) {

g2d.setColor(Color.BLUE);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f));
Point[] ips = c1.intersections(c2);
for (Point ip : ips) {
ip.drawOn(g, W, H);
}
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f));
if (ips.length == 2) {
g2d.setStroke(new BasicStroke(10.0f));
c1.highlightArc(g2d, ips[0], ips[1], W, H);
}
}

g2d.dispose();
}

public void showDraggedCircle(Point p) {
currentPosition = p;
repaint();
}
}

private static class Circle {

public final Point center;
public final double radius;

public Circle(Point center, double radius) {
this.center = center;
this.radius = radius;
}

public void drawOn(Graphics g, int width, int height) {
// translate Cartesian(x,y) to Screen(x,y)
Point screenP = center.toScreenPoint(width, height);
int r = (int) Math.rint(radius);
g.drawOval((int) screenP.x - r, (int) screenP.y - r, r + r, r + r);

// draw the center
Point screenCenter = center.toScreenPoint(width, height);
r = 4;
g.drawOval((int) screenCenter.x - r, (int) screenCenter.y - r, r + r, r + r);
}

public void highlightArc(Graphics2D g2d, Point p1, Point p2, int width, int height) {

double a = center.degrees(p1);
double b = center.degrees(p2);

// translate Cartesian(x,y) to Screen(x,y)
Point screenP = center.toScreenPoint(width, height);
int r = (int) Math.rint(radius);

// find the point to start drawing our arc
double start = Math.abs(a - b) < 180 ? Math.min(a, b) : Math.max(a, b);

// find the minimum angle to go from `start`-angle to the other angle
double extent = Math.abs(a - b) < 180 ? Math.abs(a - b) : 360 - Math.abs(a - b);

// draw the arc
g2d.draw(new Arc2D.Double((int) screenP.x - r, (int) screenP.y - r, r + r, r + r, start, extent, Arc2D.OPEN));
}

public Point[] intersections(Circle that) {

// see: http://mathworld.wolfram.com/Circle-CircleIntersection.html
double d = this.center.distance(that.center);
double d1 = ((this.radius * this.radius) - (that.radius * that.radius) + (d * d)) / (2 * d);
double h = Math.sqrt((this.radius * this.radius) - (d1 * d1));
double x3 = this.center.x + (d1 * (that.center.x - this.center.x)) / d;
double y3 = this.center.y + (d1 * (that.center.y - this.center.y)) / d;
double x4_i = x3 + (h * (that.center.y - this.center.y)) / d;
double y4_i = y3 - (h * (that.center.x - this.center.x)) / d;
double x4_ii = x3 - (h * (that.center.y - this.center.y)) / d;
double y4_ii = y3 + (h * (that.center.x - this.center.x)) / d;

if (Double.isNaN(x4_i)) {
// no intersections
return new Point[0];
}

// create the intersection points
Point i1 = new Point(x4_i, y4_i);
Point i2 = new Point(x4_ii, y4_ii);

if (i1.distance(i2) < 0.0000000001) {
// i1 and i2 are (more or less) the same: a single intersection
return new Point[]{i1};
}

// two unique intersections
return new Point[]{i1, i2};
}

@Override
public String toString() {
return String.format("{center=%s, radius=%.2f}", center, radius);
}
}

private static class Point {

public final double x;
public final double y;

public Point(double x, double y) {
this.x = x;
this.y = y;
}

public double degrees(Point that) {
double deg = Math.toDegrees(Math.atan2(that.y - this.y, that.x - this.x));
return deg < 0.0 ? deg + 360 : deg;
}

public double distance(Point that) {
double dX = this.x - that.x;
double dY = this.y - that.y;
return Math.sqrt(dX * dX + dY * dY);
}

public void drawOn(Graphics g, int width, int height) {
// translate Cartesian(x,y) to Screen(x,y)
Point screenP = toScreenPoint(width, height);
int r = 7;
g.fillOval((int) screenP.x - r, (int) screenP.y - r, r + r, r + r);
}

public Point toCartesianPoint(int width, int height) {
double xCart = x - (width / 2);
double yCart = -(y - (height / 2));
return new Point(xCart, yCart);
}

public Point toScreenPoint(int width, int height) {
double screenX = x + (width / 2);
double screenY = -(y - (height / 2));
return new Point(screenX, screenY);
}

@Override
public String toString() {
return String.format("(%.2f,%.2f)", x, y);
}
}
}

如果您启动上面的 GUI,然后在文本框中键入 100 0 130 -80 55 180 并回车,您将看到以下内容:...

更改了代码,以便可以通过按住并拖动鼠标来绘制圆圈。截图:

enter image description here

关于java - 仅渲染与主圆相交的圆的段/区域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5014680/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com