Example #1
0
File: main.go Project: langxj/gxui
func drawMoon(canvas gxui.Canvas, center math.Point, radius float32) {
	c := 40
	p := make(gxui.Polygon, c*2)
	for i := 0; i < c; i++ {
		frac := float32(i) / float32(c)
		α := math.Lerpf(math.Pi*1.2, math.Pi*-0.2, frac)
		p[i] = gxui.PolygonVertex{
			Position: math.Point{
				X: center.X + int(radius*math.Sinf(α)),
				Y: center.Y + int(radius*math.Cosf(α)),
			},
			RoundedRadius: 0,
		}
	}
	for i := 0; i < c; i++ {
		frac := float32(i) / float32(c)
		α := math.Lerpf(math.Pi*-0.2, math.Pi*1.2, frac)
		r := math.Lerpf(radius, radius*0.5, math.Sinf(frac*math.Pi))
		p[i+c] = gxui.PolygonVertex{
			Position: math.Point{
				X: center.X + int(r*math.Sinf(α)),
				Y: center.Y + int(r*math.Cosf(α)),
			},
			RoundedRadius: 0,
		}
	}
	canvas.DrawPolygon(p, gxui.CreatePen(3, gxui.Gray80), gxui.CreateBrush(gxui.Gray40))
}
Example #2
0
func buildMoon(theme gxui.Theme, center math.Point, radius float32) gxui.Image {
	c := 40
	p := make(gxui.Polygon, c*2)
	for i := 0; i < c; i++ {
		frac := float32(i) / float32(c)
		α := math.Lerpf(math.Pi*1.2, math.Pi*-0.2, frac)
		p[i] = gxui.PolygonVertex{
			Position: math.Point{
				X: center.X + int(radius*math.Sinf(α)),
				Y: center.Y + int(radius*math.Cosf(α)),
			},
			RoundedRadius: 0,
		}
	}
	for i := 0; i < c; i++ {
		frac := float32(i) / float32(c)
		α := math.Lerpf(math.Pi*-0.2, math.Pi*1.2, frac)
		r := math.Lerpf(radius, radius*0.5, math.Sinf(frac*math.Pi))
		p[i+c] = gxui.PolygonVertex{
			Position: math.Point{
				X: center.X + int(r*math.Sinf(α)),
				Y: center.Y + int(r*math.Cosf(α)),
			},
			RoundedRadius: 0,
		}
	}
	image := theme.CreateImage()
	image.SetPolygon(p, gxui.CreatePen(3, gxui.Gray80), gxui.CreateBrush(gxui.Gray40))
	return image
}
Example #3
0
func segment(penWidth, r float32, a, b, c math.Vec2, aIsLast bool, vsEdgePos []float32, fillEdge []math.Vec2) ([]float32, []math.Vec2) {
	ba, ca := a.Sub(b), a.Sub(c)
	baLen, caLen := ba.Len(), ca.Len()
	baDir, caDir := ba.DivS(baLen), ca.DivS(caLen)
	dp := baDir.Dot(caDir)
	if dp < -0.99999 {
		// Straight lines cause DBZs, special case
		inner := a.Sub(caDir.Tangent().MulS(penWidth))
		vsEdgePos = appendVec2(vsEdgePos, a, inner)
		if fillEdge != nil /*&& i != 0*/ {
			fillEdge = append(fillEdge, inner)
		}
		return vsEdgePos, fillEdge
	}
	α := math.Acosf(dp) / 2
	// ╔═══════════════════════════╦════════════════╗
	// ║                           ║                ║
	// ║             A             ║                ║
	// ║            ╱:╲            ║                ║
	// ║           ╱α:α╲           ║   A            ║
	// ║          ╱  :  ╲          ║   |╲           ║
	// ║         ╱ . d . ╲         ║   |α╲          ║
	// ║        .    :    .        ║   |  ╲         ║
	// ║       .P    :    Q.       ║   |   ╲        ║
	// ║      ╱      X      ╲      ║   |    ╲       ║
	// ║     ╱ .     ┊     . ╲     ║   |     ╲      ║
	// ║    ╱   .    r    .   ╲    ║   |      ╲     ║
	// ║   ╱       . ┊ .       ╲   ║   |┐     β╲    ║
	// ║  B          ┊          C  ║   P————————X   ║
	// ║                           ║                ║
	// ║             ^             ║                ║
	// ║             ┊v            ║                ║
	// ║             ┊  u          ║                ║
	// ║             ┊—————>       ║                ║
	// ║                           ║                ║
	// ╚═══════════════════════════╩════════════════╝
	v := baDir.Add(caDir).Normalize()
	u := v.Tangent()
	//
	// cos(2 • α) = dp
	//
	//      cos⁻¹(dp)
	// α = ───────────
	//          2
	//
	//           r
	// sin(α) = ───
	//           d
	//
	//       r
	// d = ──────
	//     sin(α)
	//
	d := r / math.Sinf(α)

	// X cannot be futher than half way along ab or ac
	dMax := math.Minf(baLen, caLen) / (2 * math.Cosf(α))
	if d > dMax {
		// Adjust d and r to compensate
		d = dMax
		r = d * math.Sinf(α)
	}

	x := a.Sub(v.MulS(d))

	convex := baDir.Tangent().Dot(caDir) <= 0

	w := penWidth
	β := math.Pi/2 - α

	// Special case for convex vertices where the pen width is greater than
	// the rounding. Without dealing with this, we'd end up with the inner
	// vertices overlapping. Instead use a point calculated much the same as
	// x, but using the pen width.
	useFixedInnerPoint := convex && w > r
	fixedInnerPoint := a.Sub(v.MulS(math.Minf(w/math.Sinf(α), dMax)))

	// Concave vertices behave much the same as convex, but we have to flip
	// β as the sweep is reversed and w as we're extruding.
	if !convex {
		w, β = -w, -β
	}

	steps := 1 + int(d*α)

	if aIsLast {
		// No curvy edge required for the last vertex.
		// This is already done by the first vertex.
		steps = 1
	}

	for j := 0; j < steps; j++ {
		γ := float32(0)
		if steps > 1 {
			γ = math.Lerpf(-β, β, float32(j)/float32(steps-1))
		}

		dir := v.MulS(math.Cosf(γ)).Add(u.MulS(math.Sinf(γ)))
		va := x.Add(dir.MulS(r))
		vb := va.Sub(dir.MulS(w))
		if useFixedInnerPoint {
			vb = fixedInnerPoint
		}

		vsEdgePos = appendVec2(vsEdgePos, va, vb)
		if fillEdge != nil {
			fillEdge = append(fillEdge, vb)
		}
	}

	return vsEdgePos, fillEdge
}