Hi I am using the function createPoint to animate a polygon using gsap. I am also using svg.js
If I use vanilla javascript to get the points of the svg with
var polygon = document.querySelector("polygon");
var points = polygon.points;
it returns 3 points which correspond to the number of times the createPoint function is run. This logs out as:
0: SVGPoint {x: 105.30396270751953, y: 143.0928955078125}
1: SVGPoint {x: 348.09027099609375, y: 97.7249984741211}
2: SVGPoint {x: 276.54010009765625, y: 327.56372070}
If I use the svg.js code
const draw = SVG().addTo('body')
var svg = draw.node;
const polygon = draw.polygon().node;
var points = polygon.points;
the same function logs a list of 4 SVGPoints with the first point being {x:0,y:0} even though I am only running the function 3 times. Where is the additional (index 0) svg point coming from? Thanks in advance
0: SVGPoint {x: 0, y: 0}
1: SVGPoint {x: 93.79865264892578, y: 124.19292449951172}
2: SVGPoint {x: 346.3572082519531, y: 97.5942153930664}
3: SVGPoint {x: 227.08517456054688, y: 269.97042846
given the following html
<svg>
<polygon points="">
</svg>
And the code below
TweenLite.defaultEase = Sine.easeInOut;
const draw = SVG().addTo('body')
var svg = draw.node;
const polygon = draw.polygon().node;
var points = polygon.points;
console.log('points',points)
var offset = 75;
createPoint(100, 100);
createPoint(300, 100);
createPoint(300, 300);
// createPoint(100, 300);
function createPoint(x, y) {
var minX = x - offset;
var maxX = x + offset;
var minY = y - offset;
var maxY = y + offset;
var point = points.appendItem(svg.createSVGPoint());
point.x = x;
point.y = y;
moveX();
moveY();
function moveX() {
TweenLite.to(point, random(2, 4), {
x: random(minX, maxX),
delay: random(0.5),
onComplete: moveX
});
}
function moveY() {
TweenLite.to(point, random(2, 4), {
y: random(minY, maxY),
delay: random(0.5),
onComplete: moveY
});
}
}
function random(min, max) {
if (max == null) { max = min; min = 0; }
if (min > max) { var tmp = min; min = max; max = tmp; }
return min + (max - min) * Math.random();
}
Just found out that by adding an empty array to the polygon i.e
const polygon = draw.polygon([]).node
it removes the default {x:0,y:0} object. Dont ask me why :)
Related
I'm trying to apply the solution presented in this Question's answer to crop a bitmap using RenderSript. My approach is a little bit different since I'm using bitmap directly as an input to crop.
Having very limited knowledge in RenderScript I developed the below code to crop my bitmap by modifying that answer.
crop.rs
#pragma version(1)
#pragma rs java_package_name(com.xxx.yyy)
#pragma rs_fp_relaxed
int32_t width;
int32_t height;
rs_allocation croppedImg;
uint xStart, yStart;
void __attribute__((kernel)) doCrop(uchar4 in,uint32_t x, uint32_t y) {
rsSetElementAt_uchar4(croppedImg,in, x-xStart, y-yStart);
}
ImageCropper
import android.content.Context
import android.graphics.Bitmap
import androidx.renderscript.*
import com.xxx.yyy.ScriptC_crop
import kotlin.math.abs
class ImageCropper(context: Context?) {
val rs = RenderScript.create(context)
var dx = 0 // (-width < dx < width);
var dy = 250 // (- height < dy < height);
var xStart = 50
var xEnd = 100
var yStart = 50
var yEnd = 100
fun crop(sourceBitmap: Bitmap): Bitmap{
val width = sourceBitmap.width
val height = sourceBitmap.height
if (dx<0) {
xStart = abs(dx)
xEnd= width
} else {
xStart = 0
xEnd = width - abs(dx)
}
if (dy<0) {
yStart= abs(dy)
yEnd=height
} else {
yStart = 0;
yEnd = height - abs(dy)
}
val cropperScript = ScriptC_crop(rs)
val inputType = Type.createXY(rs, Element.RGBA_8888(rs), width, height)
val inputAllocation = Allocation.createTyped(rs, inputType, Allocation.USAGE_SCRIPT)
inputAllocation.copyFrom(sourceBitmap)
val outputType = Type.createXY(rs, Element.RGBA_8888(rs), xEnd - xStart, yEnd - yStart)
val outputAllocation = Allocation.createTyped(rs, outputType, Allocation.USAGE_SCRIPT)
cropperScript._croppedImg = outputAllocation
cropperScript._width = width
cropperScript._height = height
cropperScript._xStart = xStart.toLong()
cropperScript._yStart = yStart.toLong()
val launchOptions: Script.LaunchOptions = Script.LaunchOptions()
launchOptions.setX(xStart, xEnd)
launchOptions.setY(yStart, yEnd)
cropperScript.forEach_doCrop(inputAllocation, launchOptions)
val resultBitmap = Bitmap.createBitmap(xEnd - xStart, yEnd - yStart, sourceBitmap.config)
outputAllocation.copyTo(resultBitmap)
rs.destroy()
return resultBitmap
}
}
When I try to execute the code I get a bellow error.
2021-04-11 20:55:41.639 18145-18202/com.chathuranga.shan.renderscriptexample E/RenderScript: Script::setVar unable to set allocation, invalid slot index
2021-04-11 20:55:41.645 18145-18202/com.chathuranga.shan.renderscriptexample A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x519 in tid 18202 (erscriptexample), pid 18145 (erscriptexample)
2021-04-11 20:55:41.639 18145-18202/com.chathuranga.shan.renderscriptexample E/RenderScript: Script::setVar unable to set allocation, invalid slot index
This error occurs in the line where I set _xStart and _yStart values. What am I doing wrong? is it some sort of data type issue?
I am working on image seam carving project, looking for some help. Can someone tell me what am I doing wrong here, Hyperskill is not accepting my solution. I am pretty sure I did not understand the project statement correctly. (I’ve been fighting it for a week)
Project: https://hyperskill.org/projects/100/stages/553/implement
First I am finding the minimum seam from all possible seams.
var minX = 0
// (minSeamX, 0) would be the coordinate of the minimum seam
var minSeamX = 0
var minSeam = Double.MAX_VALUE
//Starting from top left find the sum of pixel energies for all possible seams(#width number of possible seams)
for (column in 0 until width) {
var totalSeam = 0.0
var xHigh = column
var xLow = column
var min = Double.MAX_VALUE
for (y in 0 until height) {
for (x in xLow..xHigh) {
if (x < 0 || x > width - 1) continue
val energy = calculateEnergy(x, y, bufferedImage)
// println("Energy $x $y $energy")
if (energy < min) {
min = energy
minX = x
}
}
totalSeam += min
min = Double.MAX_VALUE
xLow = minX - 1
xHigh = minX + 1
}
if (totalSeam < minSeam) {
minSeamX = column
minSeam = totalSeam
}
println("total:$totalSeam")
}
after that I am applying the color to the minimum seam pixels
var xLow = minSeamX
var xHigh = minSeamX
var min = Double.MAX_VALUE
for (y in 0 until height) {
for (x in xLow..xHigh) {
val energy = calculateEnergy(x, y, bufferedImage)
if (energy < min) {
min = energy
minX = x
}
}
val createGraphics = applyColor(outImage, minX, y)
min = Double.MAX_VALUE
xLow = minX - 1
xHigh = minX + 1
}
Complete code
package seamcarving
import java.awt.Color
import java.awt.Graphics2D
import java.awt.image.BufferedImage
import java.io.File
import javax.imageio.ImageIO
import kotlin.math.pow
import kotlin.math.sqrt
fun main(args: Array<String>) {
val bufferedImage = ImageIO.read(File("/Users/name/Downloads/images/blue.png"))
val outImage = ImageIO.read(File("/Users/name/Downloads/images/blue.png"))
val height = bufferedImage.height
val width = bufferedImage.width
var minX = 0
// (minSeamX, 0) would be the coordinate of the minimum seam
var minSeamX = 0
var minSeam = Double.MAX_VALUE
//Starting from top left find the sum of pixel energies for all possible seams(#width number of possible seams)
for (column in 0 until width) {
var totalSeam = 0.0
var xHigh = column
var xLow = column
var min = Double.MAX_VALUE
for (y in 0 until height) {
for (x in xLow..xHigh) {
if (x < 0 || x > width - 1) continue
val energy = calculateEnergy(x, y, bufferedImage)
// println("Energy $x $y $energy")
if (energy < min) {
min = energy
minX = x
}
}
totalSeam += min
min = Double.MAX_VALUE
xLow = minX - 1
xHigh = minX + 1
}
if (totalSeam < minSeam) {
minSeamX = column
minSeam = totalSeam
}
println("total:$totalSeam")
}
var xLow = minSeamX
var xHigh = minSeamX
var min = Double.MAX_VALUE
for (y in 0 until height) {
for (x in xLow..xHigh) {
val energy = calculateEnergy(x, y, bufferedImage)
if (energy < min) {
min = energy
minX = x
}
}
val createGraphics = applyColor(outImage, minX, y)
min = Double.MAX_VALUE
xLow = minX - 1
xHigh = minX + 1
}
// for (x in 0 until width) {
// for (y in 0 until height) {
// val intensity = ((255.0 * array[x][y]) / max).toInt()
// val color = Color(intensity, intensity, intensity)
//// outputImage.setRGB(x, y, intensity)
// createGraphics.paint = color
// createGraphics.fillRect(x, y, 1, 1)
// }
// }
ImageIO.write(outImage, "png", File("out.png"))
// ImageIO.write(bufferedImage, "png", File("${args[3]}"))
}
private fun applyColor(outputImage: BufferedImage, maxX: Int, maxY: Int): Graphics2D? {
val createGraphics = outputImage.createGraphics()
val color = Color(255, 0, 0)
createGraphics.paint = color
createGraphics.fillRect(maxX, maxY, 1, 1)
return createGraphics
}
private fun calculateEnergy(x: Int, y: Int, bufferedImage: BufferedImage): Double {
return sqrt(getXGradient(x, y, bufferedImage) + getYGradient(x, y, bufferedImage))
}
fun getXGradient(x: Int, y: Int, inImage: BufferedImage): Double {
val width = inImage.width
var xx = x
var yy = y
if (x == 0) xx = 1
if (x == width - 1) xx = x - 1
val lc = Color(inImage.getRGB(xx - 1, yy))
val rc = Color(inImage.getRGB(xx + 1, yy))
return (lc.red - rc.red).toDouble().pow(2.0) + (lc.green - rc.green).toDouble().pow(2.0) + (lc.blue - rc.blue).toDouble().pow(2.0)
}
fun getYGradient(x: Int, y: Int, inImage: BufferedImage): Double {
val height = inImage.height
var xx = x
var yy = y
if (y == 0) yy = 1
if (y == height - 1) yy = y - 1
val lc = Color(inImage.getRGB(xx, yy - 1))
val rc = Color(inImage.getRGB(xx, yy + 1))
return (lc.red - rc.red).toDouble().pow(2.0) + (lc.green - rc.green).toDouble().pow(2.0) + (lc.blue - rc.blue).toDouble().pow(2.0)
}
Translating Obj-C to Swift. As you can see I declared let buf = UnsafeMutablePointer<UInt8>(CVPixelBufferGetBaseAddress(cvimgRef)) so I'm getting the error in the for loop below it.
Binary operator '+=' cannot be applied to operands of type 'Int' and 'UInt8'
Also as a little addendum I don't know how to translate the remaining Obj-C code below the for loop. What does that slash mean and how do I deal with the pointer? I have to say UnsafeMutableFloat somewhere?
// process the frame of video
func captureOutput(captureOutput:AVCaptureOutput, didOutputSampleBuffer sampleBuffer:CMSampleBuffer, fromConnection connection:AVCaptureConnection) {
// if we're paused don't do anything
if currentState == CurrentState.statePaused {
// reset our frame counter
self.validFrameCounter = 0
return
}
// this is the image buffer
var cvimgRef:CVImageBufferRef = CMSampleBufferGetImageBuffer(sampleBuffer)
// Lock the image buffer
CVPixelBufferLockBaseAddress(cvimgRef, 0)
// access the data
var width: size_t = CVPixelBufferGetWidth(cvimgRef)
var height:size_t = CVPixelBufferGetHeight(cvimgRef)
// get the raw image bytes
let buf = UnsafeMutablePointer<UInt8>(CVPixelBufferGetBaseAddress(cvimgRef))
var bprow: size_t = CVPixelBufferGetBytesPerRow(cvimgRef)
var r = 0
var g = 0
var b = 0
for var y = 0; y < height; y++ {
for var x = 0; x < width * 4; x += 4 {
b += buf[x]; g += buf[x + 1]; r += buf[x + 2] // error
}
buf += bprow() // error
}
Remaining Obj-C code.
r/=255*(float) (width*height);
g/=255*(float) (width*height);
b/=255*(float) (width*height);
You have a lot of type mismatch error.
The type of x should not be UInt8 because x to increase until the value of the width.
for var x:UInt8 = 0; x < width * 4; x += 4 { // error: '<' cannot be applied to operands of type 'UInt8' and 'Int'
So fix it like below:
for var x = 0; x < width * 4; x += 4 {
To increment the pointer address, you can use advancedBy() function.
buf += bprow(UnsafeMutablePointer(UInt8)) // error: '+=' cannot be applied to operands of type 'UnsafeMutablePointer<UInt8>' and 'size_t'
Like below:
var pixel = buf.advancedBy(y * bprow)
And this line,
RGBtoHSV(r, g, b) // error
There are no implicit casts in Swift between CGFloat and Float unfortunately. So you should cast explicitly to CGFloat.
RGBtoHSV(CGFloat(r), g: CGFloat(g), b: CGFloat(b))
The whole edited code is here:
func RGBtoHSV(r: CGFloat, g: CGFloat, b: CGFloat) -> (h: CGFloat, s: CGFloat, v: CGFloat) {
var h: CGFloat = 0.0
var s: CGFloat = 0.0
var v: CGFloat = 0.0
let col = UIColor(red: r, green: g, blue: b, alpha: 1.0)
col.getHue(&h, saturation: &s, brightness: &v, alpha: nil)
return (h, s, v)
}
// process the frame of video
func captureOutput(captureOutput:AVCaptureOutput, didOutputSampleBuffer sampleBuffer:CMSampleBuffer, fromConnection connection:AVCaptureConnection) {
// if we're paused don't do anything
if currentState == CurrentState.statePaused {
// reset our frame counter
self.validFrameCounter = 0
return
}
// this is the image buffer
var cvimgRef = CMSampleBufferGetImageBuffer(sampleBuffer)
// Lock the image buffer
CVPixelBufferLockBaseAddress(cvimgRef, 0)
// access the data
var width = CVPixelBufferGetWidth(cvimgRef)
var height = CVPixelBufferGetHeight(cvimgRef)
// get the raw image bytes
let buf = UnsafeMutablePointer<UInt8>(CVPixelBufferGetBaseAddress(cvimgRef))
var bprow = CVPixelBufferGetBytesPerRow(cvimgRef)
var r: Float = 0.0
var g: Float = 0.0
var b: Float = 0.0
for var y = 0; y < height; y++ {
var pixel = buf.advancedBy(y * bprow)
for var x = 0; x < width * 4; x += 4 { // error: '<' cannot be applied to operands of type 'UInt8' and 'Int'
b += Float(pixel[x])
g += Float(pixel[x + 1])
r += Float(pixel[x + 2])
}
}
r /= 255 * Float(width * height)
g /= 255 * Float(width * height)
b /= 255 * Float(width * height)
//}
// convert from rgb to hsv colourspace
var h: Float = 0.0
var s: Float = 0.0
var v: Float = 0.0
RGBtoHSV(CGFloat(r), g: CGFloat(g), b: CGFloat(b)) // error
}
How can I plot an array to an imageview as a graph?
I've been testing this in Playground and it works, but how can plot this as an imageview in an actual project?
let sineArraySize = 64
let frequency1 = 4.0
let phase1 = 0.0
let amplitude1 = 2.0
let sineWave = (0..<sineArraySize).map {
amplitude1 * sin(2.0 * M_PI / Double(sineArraySize) * Double($0) * frequency1 + phase1)
}
func plotArrayInPlayground<T>(arrayToPlot:Array<T>, title:String) {
for currentValue in arrayToPlot {
XCPCaptureValue(title, currentValue)
}
}
plotArrayInPlayground(sineWave, "Sine wave 1")
One way you could do this:
// this function creates a plot of an array of doubles where it scales to the provided width and the x-axis is on half height
func plotArray(arr: [Double], width: Double, height: Double) -> NSImage {
if arr.isEmpty { return NSImage() }
let xAxisHeight = height / 2
let increment = width / Double(arr.count)
let image = NSImage(size: NSSize(width: width, height: height))
image.lockFocus()
// set background color
NSColor.whiteColor().set()
NSRectFill(NSRect(x: 0, y: 0, width: width, height: height))
let path = NSBezierPath()
// line width of plot
path.lineWidth = 5
path.moveToPoint(NSPoint(x: 0, y: arr[0] * increment + xAxisHeight))
var i = increment
for value in dropFirst(sineWave) {
path.lineToPoint(NSPoint(x: i, y: value * increment + xAxisHeight))
i += increment
}
// set plot color
NSColor.blueColor().set()
path.stroke()
image.unlockFocus()
return image
}
var imageView = NSImageView()
imageView.image = plotArray(sineWave, 500, 200)
// have fun
I am trying to populate a circumference with points located at equal intervals. Here is the code (it uses some Processing, but it is not crucial for understanding):
class Circle (x: Float, y: Float, subdivisions: Int, radius: Float) extends WorldObject(x, y) {
def subs = subdivisions
def r = radius
val d = r + r
def makePoints() : List[Glyph] = {
val step = PConstants.TWO_PI / subdivisions
val points = List.make(subdivisions, new Glyph())
for(i <- 0 to subdivisions - 1) {
points(i) position (PApplet.cos(step * i) * r + xPos, PApplet.sin(step * i) * r + yPos)
}
points
}
val points: List[Glyph] = makePoints()
override def draw() {
applet fill 0
applet stroke 255
applet ellipse(x, y, d, d)
applet fill 255
points map(_.update())
}
}
class Glyph(x: Float, y: Float) extends WorldObject(x, y){
def this() = this(0, 0)
override def draw() {
applet ellipse(xPos, yPos, 10, 10)
}
}
object WorldObject {
}
abstract class WorldObject(var xPos: Float, var yPos: Float) {
def this() = this(0, 0)
def x = xPos
def y = yPos
def update() {
draw()
}
def draw()
def position(x: Float, y: Float) {
xPos = x
yPos = y
}
def move(dx: Float, dy: Float) {
xPos += dx
yPos += dy
}
}
The strange result that I get is that all the points are located at a single place. I have experimented with println checks... the checks in the makePoints() method shows everything ok, but checks in the Circle.draw() or even right after the makePoints() show the result as I see it on the screen - all points are located in a single place, right where the last of them is generated, namely x=430.9017 y=204.89435 for a circle positioned at x=400 y=300 and subdivided to 5 points. So somehow they all get collected into the place where the last of them sits.
Why is there such a behavior? What am I doing wrong?
UPD: We have been able to locate the reason, see below:
Answering the question, user unknown changed the code to use the fill method instead of make. The main relevant difference between them is that make pre-computes it's arguments and fill does not. Thus make fills the list with totally identical items. However, fill repeats the computation on each addition. Here are the source codes of these methods from Scala sources:
/** Create a list containing several copies of an element.
*
* #param n the length of the resulting list
* #param elem the element composing the resulting list
* #return a list composed of n elements all equal to elem
*/
#deprecated("use `fill' instead", "2.8.0")
def make[A](n: Int, elem: A): List[A] = {
val b = new ListBuffer[A]
var i = 0
while (i < n) {
b += elem
i += 1
}
b.toList
}
And the fill method:
/** Produces a $coll containing the results of some element computation a number of times.
* #param n the number of elements contained in the $coll.
* #param elem the element computation
* #return A $coll that contains the results of `n` evaluations of `elem`.
*/
def fill[A](n: Int)(elem: => A): CC[A] = {
val b = newBuilder[A]
b.sizeHint(n)
var i = 0
while (i < n) {
b += elem
i += 1
}
b.result
}
I changed a lot of variables forth and back (def x = ... => def x () = , x/ this.x and x/xPos and so on) added println statements and removed (P)applet-stuff, which made the compiler complain.
Providing a compilable, runnable, standalone demo would be beneficial. Here it is:
class Circle (x: Float, y: Float, subdivisions: Int, radius: Float)
extends WorldObject (x, y) {
def subs = subdivisions
def r = radius
val d = r + r
def makePoints() : List[Glyph] = {
// val step = PConstants.TWO_PI / subdivisions
val step = 6.283F / subdivisions
val points = List.fill (subdivisions) (new Glyph ())
for (i <- 0 to subdivisions - 1) {
// points (i) position (PApplet.cos (step * i) * r + xPos,
// PApplet.sin (step * i) * r + yPos)
val xx = (math.cos (step * i) * r).toFloat + xPos
val yy = (math.sin (step * i) * r).toFloat + yPos
println (xx + ": " + yy)
points (i) position (xx, yy)
}
points
}
val points: List [Glyph] = makePoints ()
override def draw () {
/*
applet fill 0
applet stroke 255
applet ellipse(x, y, d, d)
applet fill 255
*/
// println ("Circle:draw () upd-> " + super.x () + "\t" + y () + "\t" + d);
points map (_.update ())
println ("Circle:draw () <-upd " + x + "\t" + y + "\t" + d);
}
}
class Glyph (x: Float, y: Float) extends WorldObject (x, y) {
def this () = this (0, 0)
override def draw() {
// applet ellipse (xPos, yPos, 10, 10)
println ("Glyph:draw (): " + xPos + "\t" + yPos + "\t" + 10);
}
}
object Circle {
def main (as: Array [String]) : Unit = {
val c = new Circle (400, 300, 5, 100)
c.draw ()
}
}
object WorldObject {
}
abstract class WorldObject (var xPos: Float, var yPos: Float) {
def this () = this (0, 0)
def x = xPos
def y = yPos
def update () {
draw ()
}
def draw ()
def position (x: Float, y: Float) {
xPos = x
yPos = y
// println (x + " ?= " + xPos + " ?= " + (this.x ()))
}
def move (dx: Float, dy: Float) {
xPos += dx
yPos += dy
}
}
My result is:
500.0: 300.0
430.9052: 395.1045
319.10266: 358.78452
319.09177: 241.23045
430.8876: 204.88977
Glyph:draw (): 500.0 300.0 10
Glyph:draw (): 430.9052 395.1045 10
Glyph:draw (): 319.10266 358.78452 10
Glyph:draw (): 319.09177 241.23045 10
Glyph:draw (): 430.8876 204.88977 10
Circle:draw () <-upd 400.0 300.0 200.0
Can you spot the difference?
You should create a copy of your code, and stepwise remove code, which isn't necessary to reproduce the error, checking, whether the error is still present. Then you should reach a much smaller problem, or find the error yourself.