So occasionally program in VB6 but I never solved this problem.
I have a Private Sub to draw lots of stuff to a picturebox like lines, text, pictures. Lots and lots of lines of code. But then i want to use same lines to draw to a printer object. But I don't know how to do it.
For example:
private sub command1_click()
picture1.print "hello there"
etc etc etc
end sub
private sub command2_click()
printer.print "hello world"
etc etc etc
printer.print
end sub
to be
public sub pictureengine(action....)
if action = draw then picturebox is selected for output
if action = print then printer object is selected output
<object/control>.print "hello world"
etc etc etc
if action = print then printer.enddoc printer.print
end sub
There should be an alias to use controls/objects.
Thanks in advance
I was faced with this exact issue. I decided to abstract away the details of the PictureBox, Printer, or any other surface by implementing Interfaces. You will end up with 3 classes:
ISurface
CPrinterSurface
CPictureBoxSurface
The ISurface Class defines the interface and contains no code:
Option Explicit
Public Sub Create(ByRef SurfaceObject As Object)
End Sub
Public Sub AddLine(ByVal StartX As Double, _
ByVal StartY As Double, _
ByVal EndX As Double, _
ByVal EndY As Double, _
Optional ByVal PenColor As Long = vbWhite, _
Optional ByVal PenSize As Integer = 1, _
Optional ByVal PenStyle As DrawStyleConstants = vbSolid)
End Sub
Public Sub AddCircle(ByVal StartX As Double, _
ByVal StartY As Double, _
ByVal Radius As Double, _
Optional ByVal PenColor As Long = vbWhite, _
Optional ByVal PenSize As Integer = 1, _
Optional ByVal PenStyle As DrawStyleConstants = vbSolid)
End Sub
The CPrinterSurface Class implements the interface. This is where you add code.
Option Explicit
Implements ISurface
Private oPrinter As Printer
Private Sub ISurface_Create(SurfaceObject As Object)
Set oPrinter = SurfaceObject
End Sub
Private Sub ISurface_AddLine(ByVal StartX As Double, _
ByVal StartY As Double, _
ByVal EndX As Double, _
ByVal EndY As Double, _
Optional ByVal PenColor As Long = 16777215, _
Optional ByVal PenSize As Integer = 1, _
Optional ByVal PenStyle As DrawStyleConstants = 0&)
oPrinter.DrawWidth = PenSize
oPrinter.DrawStyle = PenStyle
oPrinter.ForeColor = PenColor
oPrinter.Line (StartX, StartY)-(EndX, EndY), PenColor
End Sub
Private Sub ISurface_AddCircle(ByVal StartX As Double, _
ByVal StartY As Double, _
ByVal Radius As Double, _
Optional ByVal PenColor As Long = 16777215, _
Optional ByVal PenSize As Integer = 1, _
Optional ByVal PenStyle As DrawStyleConstants = 0&)
oPrinter.DrawWidth = PenSize
oPrinter.DrawStyle = PenStyle
oPrinter.ForeColor = PenColor
oPrinter.Circle (StartX, StartY), Radius, PenColor
End Sub
The CPictureBoxSurface Class also implements the interface.
Option Explicit
Implements ISurface
Private oPictureBox As PictureBox
Private Sub ISurface_Create(SurfaceObject As Object)
Set oPictureBox = SurfaceObject
End Sub
Private Sub ISurface_AddLine(ByVal StartX As Double, _
ByVal StartY As Double, _
ByVal EndX As Double, _
ByVal EndY As Double, _
Optional ByVal PenColor As Long = 16777215, _
Optional ByVal PenSize As Integer = 1, _
Optional ByVal PenStyle As DrawStyleConstants = 0&)
oPictureBox.DrawWidth = PenSize
oPictureBox.DrawStyle = PenStyle
oPictureBox.ForeColor = PenColor
oPictureBox.Line (StartX, StartY)-(EndX, EndY), PenColor
End Sub
Private Sub ISurface_AddCircle(ByVal StartX As Double, _
ByVal StartY As Double, _
ByVal Radius As Double, _
Optional ByVal PenColor As Long = 16777215, _
Optional ByVal PenSize As Integer = 1, _
Optional ByVal PenStyle As DrawStyleConstants = 0&)
oPictureBox.DrawWidth = PenSize
oPictureBox.DrawStyle = PenStyle
oPictureBox.ForeColor = PenColor
oPictureBox.Circle (StartX, StartY), Radius, PenColor
End Sub
The Main App. Create an EXE project containing the logic to generically produce your drawing. Swap out the surface, and one codebase can draw to any implemented surface. Your project tree will consist of the main form with a PictureBox and a Button, and the 3 classes described above. Here is the code for the main form:
Option Explicit
Private MySurface As ISurface
Private Sub cmdCreate_Click()
Set MySurface = New CPictureBoxSurface
MySurface.Create Picture1
MySurface.AddCircle 1000, 1000, 500, vbRed
MySurface.AddCircle 1500, 1500, 500, vbBlue
End Sub
The code presented above eliminates duplication when you have multiple surfaces. It has been stripped down for clarity and to highlight the basic architecture. Hopefully you will be able to expound upon these concepts for your application.
Related
EDIT: Resolved, I answered the question below.
I am using the following to get metadata for PHAssets:
let data = NSData.init(contentsOf: url!)!
if let imageSource = CGImageSourceCreateWithData(data, nil) {
let metadata = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil)! as NSDictionary
}
The metadata dictionary has all the values I am looking for. However a few fields like ShutterSpeedValue, ExposureTime which have fractions get printed as decimals:
ExposureTime = "0.05"
ShutterSpeedValue = "4.321956769055745"
When I look at this data on my Mac's preview app and exiftool, it shows:
ExposureTime = 1/20
ShutterSpeedValue = 1/20
How can I get the correct fraction string instead of the decimal string?
EDIT: I tried simply converting the decimal to a fraction string using this from SO code but this isn't correct:
func rationalApproximation(of x0 : Double, withPrecision eps : Double = 1.0E-6) -> String {
var x = x0
var a = x.rounded(.down)
var (h1, k1, h, k) = (1, 0, Int(a), 1)
while x - a > eps * Double(k) * Double(k) {
x = 1.0/(x - a)
a = x.rounded(.down)
(h1, k1, h, k) = (h, k, h1 + Int(a) * h, k1 + Int(a) * k)
}
return "\(h)/\(k)"
}
As you notice, the decimal value of ShutterSpeedValue printed as 4.321956769055745 isn't even equal to 1/20.
Resolved.
As per
https://www.dpreview.com/forums/post/54376235
ShutterSpeedValue is defined as APEX value, where:
ShutterSpeed = -log2(ExposureTime)
So -log2(1/20) is 4.3219, just as what I observed.
So to get the ShutterSpeedValue, I use the following:
"1/\(ceil(pow(2, Double(4.321956769055745))))"
I tested 3 different photos and 1/20, 1/15 and 1/1919 were all correctly calculated using your formula.
How do I make a function scale(), that multiplies a float and a vector. It has to use this library shown here? I think it's called library, sorry if that is wrong.
/// Multiplication of a float and a vector
val scale : float -> float * float -> float * float
Spent 4 hours trying to figure it out.
My assignment (Data sciences 3rd week) is, I have a signature-file containing a 2D vector library and I need to make functions out of it using that library.
/// A 2D vector library
/// Vectors are represented as pairs of floats module vec2d
/// The length of a vector
val len : float * float -> float
/// The angle of a vector
val ang : float * float -> float
/// Multiplication of a float and a vector
val scale : float -> float * float -> float * float
/// Addition of two vectors
val add : float * float -> float * float -> float * float
/// Dot product of two vectors
val dot : float * float -> float * float -> float
Currently I have:
// LENGTH OF A VECTOR
// val len : float * float -> float
let len (x: float, y: float) =
sqrt(x**2.0 + y**2.0)
// ANGLE OF A VECTOR
// val ang : float * float -> float
let ang (x: float, y: float) =
Math.Atan2(y, x)
// MULTIPLICATION OF A FLOAT AND A VECTOR
// val scale : float -> float * float -> float * float
let scale () =
None
/// ADDITION OF TWO VECTORS
// add : float * float -> float * float -> float * float
let add (xy1: float, xy2: float) =
None
/// DOT PRODUCT OF TWO VECTORS
// dot : float * float -> float * float -> float
let dot (xy1: float, xy2: float) =
None
Any kind of help/hint would be really helpful! I'm stuck!
Is this what you're looking for?
let scale n (x: float, y: float) =
n*x, n*y
This multiplies each of the values in the vector tuple (x,y) with the float n.
If I have the next type:
type Color(r: float, g: float, b:float) =
member this.r = r
member this.g = g
member this.b = b
static member ( * ) (c1:Color, c2:Color) =
Color (c1.r*c2.r, c1.g*c2.g, c1.b*c2.b)
static member Zero = Color(0.0,0.0,0.0)
and I do:
let ca = Color(1.,1.,1.)
let cb = Color(1.,1.,1.)
ca = cb
I should obtain true, but the F# interactive via a script is giving me false
Instead, If I define as:
let ca = Color(1.,1.,1.)
let cb = ca
ca = cb
It returns true
Am I doing something wrong trying to compare two values of a defined type in this way?
How can I do it to obtain true as a result?
Thanks
The OP definition of Color is a class. Classes have referential equality by default, just like in C#. That means they're only equal if they literally are the same object (points to the same memory address).
Only the functional data types in F# have structural equality. These include records, discriminated unions, lists, and a few other types.
It'd be more idiomatic to define Color as a record:
type Color = { Red : float; Green : float; Blue : float }
This type has structural equality built in:
> let ca = { Red = 1.; Green = 1.; Blue = 1. };;
val ca : Color = {Red = 1.0;
Green = 1.0;
Blue = 1.0;}
> let cb = { Red = 1.; Green = 1.; Blue = 1. };;
val cb : Color = {Red = 1.0;
Green = 1.0;
Blue = 1.0;}
> ca = cb;;
val it : bool = true
If you want to define multiplication and zero for the type, you can do that as well:
let (*) x y = {
Red = x.Red * y.Red
Green = x.Green * y.Green
Blue = x.Blue * y.Blue }
let zero = { Red = 0.0; Green = 0.0; Blue = 0.0 }
This enables you to write, e.g.:
> let product = ca * cb;;
val product : Color = {Red = 1.0;
Green = 1.0;
Blue = 1.0;}
F# implements automatic memberwise comparison for records and unions, but not for classes. If you want to have it and construct values with the Color(r, g, b) syntax, you can use a single-case union. You will get pattern matching as a bonus (see my implementation of (*)).
type Color =
| Color of r: float * g: float * b: float
member this.r = let (Color(r, _, _)) = this in r
member this.g = let (Color(_, g, _)) = this in g
member this.b = let (Color(_, _, b)) = this in b
static member (*) (Color(r1, g1, b1), Color(r2, g2, b2)) =
Color(r1 * r2, g1 * g2, b1 * b2)
static member Zero = Color(0., 0., 0.)
To start you should read this page:
http://blogs.msdn.com/b/dsyme/archive/2009/11/08/equality-and-comparison-constraints-in-f-1-9-7.aspx
It does a great job of illustrating how equality works in F#.
As to your specific issue, you are looking at the difference between Reference Equality and Structural Equality. You can add the following annotation
[<CustomEquality; CustomComparison>]
And you can add overloads to the Equals method override x.Equals(other) to do your memberwise comparision
I've seen a lot of questions converting hex to int, but these are all of the unsigned-> unsigned variety. How could I convert signed hex to an Int?
eg.
somefunc('0xfffff830')
= -2000
Your question implies that you are dealing with 32-bit signed integers
(otherwise 0xfffff830 could not be considered as negative),
so this would work:
let num = "0xfffff830"
let x = Int32(truncatingBitPattern: strtoul(num, nil, 16))
println(x) // -2000
strtoul() converts the hex string to an unsigned integer UInt, and
Int32(truncatingBitPattern:) creates a (signed) 32-bit integer
from the lowest 32 bits of the given argument.
Updated for Swift 4:
let num = "0xfffff830"
let x = Int32(bitPattern: UInt32(num.dropFirst(2), radix: 16) ?? 0)
print(x) // -2000
You could use conversion to unsigned and then convert the unsigned to signed.
let num = "0xfffff830"
var result: UInt32 = 0
let converter = NSScanner(string: num)
converter.scanHexInt(&result)
print(unsafeBitCast(result, Int32.self)) // prints -2000
An approach
var hex = UInt32(0xfffff830)
let signedHex : Int
if hex > UInt32.max / 2 {
signedHex = -Int(~hex + 1) // ~ is the Bitwise NOT Operator
} else {
signedHex = Int(hex)
}
The following produces the below error:
int calc_ranks(ranks)
{
double multiplier = .5;
return multiplier * ranks;
}
The return type double is not a int, as defined by the method calc_ranks. How do I round/cast to an int?
Round it using the round() method:
int calc_ranks(ranks) {
double multiplier = .5;
return (multiplier * ranks).round();
}
You can use any of the following.
double d = 20.5;
int i = d.toInt(); // i = 20
int i = d.round(); // i = 21
int i = d.ceil(); // i = 21
int i = d.floor(); // i = 20
You can simply use toInt() to convert a num to an int.
int calc_ranks(ranks)
{
double multiplier = .5;
return (multiplier * ranks).toInt();
}
Note that to do exactly the same thing you can use the Truncating division operator :
int calc_ranks(ranks) => ranks ~/ 2;
I see a lot of answers, but with less description. Hope my answer will add some value.
Lets initalize the variable, and see how it will change with different methods.
double x = 8.5;
toInt()
It truncates the decimal value.
int a = x.toInt();
print(a); // 8
truncate()
It also truncates the decimal value.
int b = x.truncate();
print(b); // 8
round()
It returns the closest integer. It uses half up rounding mode.
int c = x.round();
print(c); // 9
ceil()
It returns the closest integer greater than the value.
int c = x.ceil();
print(c); // 9
floor()
It returns the closest integer smaller than the value.
int c = x.floor();
print(c); // 8
I looked at the answers above and added some more answers to make it a little easier to understand.
double value = 10.5;
Using toInt()
void main(){
double value = 10.5;
var y = value.toInt();
print(y);
print(y.runtimeType);
}
Using round()
The round() method returns the closest integer to the double.
void main(){
double value = 9.6;
var b = value.round();
print(b);
print(b.runtimeType);
}
Using ceil()
The ceil() method returns the smallest integer that is equal or greater than the given double.
void main(){
double value = 9.5;
var d = value.ceil();
print(d);
print(d.runtimeType);
}
Using floor()
The floor() method returns the greatest integer not greater than the given double.
void main(){
double value = 10.9;
var j = value.floor();
print(j);
print(j.runtimeType);
}
Conclusion
We’ve gone through 4 different techniques to convert a double to an integer in Dart and Flutter. You can choose from the method that fits your use case to solve your problem. Flutter is awesome and provides a lot of amazing features.
To convert double to int just this:
division
double01 ~/ double02
PS: The operator x ~/ y is more efficient than (x / y).toInt().
Multiplication, addition and subtraction
(double01 * double02).toInt
(double01 + double02).toInt
(double01 - double02).toInt
Its easy,
(20.8).round()
For String,
double.tryParse(20.8).round()
from string to int ->
if you string in int format like '10'
then use ---->
int.parse(value)
but if string in double format like '10.6'
then use like this ---->
double.parse(value).toInt()
convert double to int
doubleValue.toInt()
Try this!
int calc_ranks(ranks)
{
double multiplier = .5;
return (multiplier * ranks).truncate();
}
class CurrencyUtils{
static int doubletoint(double doublee) {
double multiplier = .5;
return (multiplier * doublee).round();
}
}
----------------------
CustomText( CurrencyUtils.doubletoint(
double.parse(projPageListss[0].budget.toString())
).toString(),
fontSize: 20,
color: Colors.white,
font: Font.QuicksandSemiBold,
),
There's another alternative, you can first cast the double to 'num' datatype and then convert to int using toInt().
double multiplier = .5;
return ((multiplier * ranks) as num).toInt();
The num type is an inherited data type of the int and double types.
You can cast both int and double to num, then cast it again to whatever you want
(double -> use toDouble(), int -> use toInt())