1661876100
This module contains functions related to the representation of 3D rotations of reference frames. It is used on a daily basis on projects at the Brazilian National Institute for Space Research (INPE).
This package can be installed using:
julia> Pkg.update()
julia> Pkg.add("ReferenceFrameRotations")
See the package documentation.
Author: JuliaSpace
Source Code: https://github.com/JuliaSpace/ReferenceFrameRotations.jl
License: View license
1661876100
This module contains functions related to the representation of 3D rotations of reference frames. It is used on a daily basis on projects at the Brazilian National Institute for Space Research (INPE).
This package can be installed using:
julia> Pkg.update()
julia> Pkg.add("ReferenceFrameRotations")
See the package documentation.
Author: JuliaSpace
Source Code: https://github.com/JuliaSpace/ReferenceFrameRotations.jl
License: View license
1659074160
Kashmir is a Ruby DSL that makes serializing and caching objects a snap.
Kashmir allows you to describe representations of Ruby objects. It will generate hashes from these Ruby objects using the representation and dependency tree that you specify.
Kashmir::ActiveRecord
will also optimize and try to balance ActiveRecord
queries so your application hits the database as little as possible.
Kashmir::Caching
builds a dependency tree for complex object representations and caches each level of this tree separately. Kashmir will do so by creating cache views of each level as well as caching a complete tree. The caching engine is smart enough to fill holes in the cache tree with fresh data from your data store.
Combine Kashmir::Caching
+ Kashmir::ActiveRecord
for extra awesomeness.
For example, a Person
with name
and age
attributes:
class Person
include Kashmir
def initialize(name, age)
@name = name
@age = age
end
representations do
rep :name
rep :age
end
end
could be represented as:
{ name: 'Netto Farah', age: 26 }
Representing an object is as simple as:
include Kashmir
to the target class.# Add fields and methods you want to be visible to Kashmir
representations do
rep(:name)
rep(:age)
end
#represent
it.# Pass in an array with all the fields you want included
Person.new('Netto Farah', 26).represent([:name, :age])
=> {:name=>"Netto Farah", :age=>"26"}
Add this line to your application's Gemfile:
gem 'kashmir'
And then execute:
$ bundle
Kashmir is better described with examples.
Only whitelisted fields can be represented by Kashmir. This is done so sensitive fields (like passwords) cannot be accidentally exposed to clients.
class Recipe < OpenStruct
include Kashmir
representations do
rep(:title)
rep(:preparation_time)
end
end
Instantiate a Recipe
:
recipe = Recipe.new(title: 'Beef Stew', preparation_time: 60)
Kashmir automatically adds a #represent
method to every instance of Recipe
. #represent
takes an Array
with all the fields you want as part of your representation.
recipe.represent([:title, :preparation_time])
=> { title: 'Beef Stew', preparation_time: 60 }
You can represent any instance variable or method (basically anything that returns true
for respond_to?
).
class Recipe < OpenStruct
include Kashmir
representations do
rep(:title)
rep(:num_steps)
end
def num_steps
steps.size
end
end
Recipe.new(title: 'Beef Stew', steps: ['chop', 'cook']).represent([:title, :num_steps])
=> { title: 'Beef Stew', num_steps: 2 }
You can nest Kashmir objects to represent complex relationships between your objects.
class Recipe < OpenStruct
include Kashmir
representations do
rep(:title)
rep(:chef)
end
end
class Chef < OpenStruct
include Kashmir
representations do
base([:name])
end
end
When you create a representation, nest hashes to create nested representations.
netto = Chef.new(name: 'Netto Farah')
beef_stew = Recipe.new(title: 'Beef Stew', chef: netto)
beef_stew.represent([:title, { :chef => [ :name ] }])
=> {
:title => "Beef Stew",
:chef => {
:name => 'Netto Farah'
}
}
Not happy with this syntax? Check out Kashmir::DSL
or Kashmir::InlineDSL
for prettier code.
Are you tired of repeating the same fields over and over? You can create a base representation of your objects, so Kashmir returns basic fields automatically.
class Recipe
include Kashmir
representations do
base [:title, :preparation_time]
rep :num_steps
rep :chef
end
end
base(...)
takes an array with the fields you want to return on every representation of a given class.
brisket = Recipe.new(title: 'BBQ Brisket', preparation_time: 'a long time')
brisket.represent()
=> { :title => 'BBQ Brisket', :preparation_time => 'a long time' }
You can nest as many Kashmir objects as you want.
class Recipe < OpenStruct
include Kashmir
representations do
base [:title]
rep :chef
end
end
class Chef < OpenStruct
include Kashmir
representations do
base :name
rep :restaurant
end
end
class Restaurant < OpenStruct
include Kashmir
representations do
base [:name]
rep :rating
end
end
bbq_joint = Restaurant.new(name: "Netto's BBQ Joint", rating: '5 Stars')
netto = Chef.new(name: 'Netto', restaurant: bbq_joint)
brisket = Recipe.new(title: 'BBQ Brisket', chef: netto)
brisket.represent([
:chef => [
{ :restaurant => [ :rating ] }
]
])
=> {
title: 'BBQ Brisket',
chef: {
name: 'Netto',
restaurant: {
name: "Netto's BBQ Joint",
rating: '5 Stars'
}
}
}
Arrays of Kashmir objects work the same way as any other Kashmir representations. Kashmir will augment Array
with #represent
that will represent every item in the array.
class Ingredient < OpenStruct
include Kashmir
representations do
rep(:name)
rep(:quantity)
end
end
class ClassyRecipe < OpenStruct
include Kashmir
representations do
rep(:title)
rep(:ingredients)
end
end
omelette = ClassyRecipe.new(title: 'Omelette Du Fromage')
omelette.ingredients = [
Ingredient.new(name: 'Egg', quantity: 2),
Ingredient.new(name: 'Cheese', quantity: 'a lot!')
]
Just describe your Array
representations like any regular nested representation.
omelette.represent([:title, {
:ingredients => [ :name, :quantity ]
}
])
=> {
title: 'Omelette Du Fromage',
ingredients: [
{ name: 'Egg', quantity: 2 },
{ name: 'Cheese', quantity: 'a lot!' }
]
}
Kashmir::Dsl
Passing arrays and hashes around can be very tedious and lead to duplication. Kashmir::Dsl
allows you to create your own representers/decorators so you can keep your logic in one place and make way more expressive.
class Recipe < OpenStruct
include Kashmir
representations do
rep(:title)
rep(:num_steps)
end
end
class RecipeRepresenter
include Kashmir::Dsl
prop :title
prop :num_steps
end
All you need to do is include Kashmir::Dsl
in any ruby class. Every call to prop(field_name)
will translate directly into just adding an extra field in the representation array.
In this case, RecipeRepresenter
will translate directly to [:title, :num_steps]
.
brisket = Recipe.new(title: 'BBQ Brisket', num_steps: 2)
brisket.represent(RecipePresenter)
=> { title: 'BBQ Brisket', num_steps: 2 }
It is also possible to define nested representers with embed(:property_name, RepresenterClass)
.
class RecipeWithChefRepresenter
include Kashmir::Dsl
prop :title
embed :chef, ChefRepresenter
end
class ChefRepresenter
include Kashmir::Dsl
prop :full_name
end
Kashmir will inline these classes and return a raw Kashmir description.
RecipeWithChefRepresenter.definitions == [ :title, { :chef => [ :full_name ] }]
=> true
Representing the objects will work just as before.
chef = Chef.new(first_name: 'Netto', last_name: 'Farah')
brisket = Recipe.new(title: 'BBQ Brisket', chef: chef)
brisket.represent(RecipeWithChefRepresenter)
=> {
title: 'BBQ Brisket',
chef: {
full_name: 'Netto Farah'
}
}
You don't necessarily need to define a class for every nested representation.
class RecipeWithInlineChefRepresenter
include Kashmir::Dsl
prop :title
inline :chef do
prop :full_name
end
end
Using inline(:property_name, &block)
will work the same way as embed
. Except that you can now define short representations using ruby blocks. Leading us to our next topic.
Kashmir::InlineDsl
Kashmir::InlineDsl
sits right in between raw representations and Representers. It reads much better than arrays of hashes and provides the expressiveness of Kashmir::Dsl
without all the ceremony.
It works with every feature from Kashmir::Dsl
and allows you to define quick inline descriptions for your Kashmir
objects.
class Recipe < OpenStruct
include Kashmir
representations do
rep(:title)
rep(:num_steps)
end
end
Just call #represent_with(&block)
on any Kashmir
object and use the Kashmir::Dsl
syntax.
brisket = Recipe.new(title: 'BBQ Brisket', num_steps: 2)
brisket.represent_with do
prop :title
prop :num_steps
end
=> { title: 'BBQ Brisket', num_steps: 2 }
You can nest inline representations using inline(:field, &block)
the same way we did with Kashmir::Dsl
.
class Ingredient < OpenStruct
include Kashmir
representations do
rep(:name)
rep(:quantity)
end
end
class ClassyRecipe < OpenStruct
include Kashmir
representations do
rep(:title)
rep(:ingredients)
end
end
omelette = ClassyRecipe.new(title: 'Omelette Du Fromage')
omelette.ingredients = [
Ingredient.new(name: 'Egg', quantity: 2),
Ingredient.new(name: 'Cheese', quantity: 'a lot!')
]
Just call #represent_with(&block)
and start nesting other inline representations.
omelette.represent_with do
prop :title
inline :ingredients do
prop :name
prop :quantity
end
end
=> {
title: 'Omelette Du Fromage',
ingredients: [
{ name: 'Egg', quantity: 2 },
{ name: 'Cheese', quantity: 'a lot!' }
]
}
Inline representations can become lengthy and confusing over time. If you find yourself nesting more than two levels or including more than 3 or 4 fields per level consider creating Representers with Kashmir::Dsl
.
Kashmir::ActiveRecord
Kashmir works just as well with ActiveRecord. ActiveRecord::Relation
s can be used as Kashmir representations just as any other classes.
Kashmir will attempt to preload every ActiveRecord::Relation
defined as representations automatically by using ActiveRecord::Associations::Preloader
. This will guarantee that you don't run into N+1 queries while representing collections and dependent objects.
Here's an example of how Kashmir will attempt to optimize database queries:
ActiveRecord::Schema.define do
create_table :recipes, force: true do |t|
t.column :title, :string
t.column :num_steps, :integer
t.column :chef_id, :integer
end
create_table :chefs, force: true do |t|
t.column :name, :string
end
end
module AR
class Recipe < ActiveRecord::Base
include Kashmir
belongs_to :chef
representations do
rep :title
rep :chef
end
end
class Chef < ActiveRecord::Base
include Kashmir
has_many :recipes
representations do
rep :name
rep :recipes
end
end
end
AR::Chef.all.each do |chef|
chef.recipes.to_a
end
will generate
SELECT * FROM chefs
SELECT "recipes".* FROM "recipes" WHERE "recipes"."chef_id" = ?
SELECT "recipes".* FROM "recipes" WHERE "recipes"."chef_id" = ?
With Kashmir:
AR::Chef.all.represent([:recipes])
SELECT "chefs".* FROM "chefs"
SELECT "recipes".* FROM "recipes" WHERE "recipes"."chef_id" IN (1, 2)
For more examples, check out: https://github.com/IFTTT/kashmir/blob/master/test/activerecord_tricks_test.rb
Kashmir::Caching
(Experimental)Caching is the best feature in Kashmir. The Kashmir::Caching
module will cache every level of the dependency tree Kashmir generates when representing an object.
As you can see in the image above, Kashmir will build a dependency tree of the representation. If you have Caching on, Kashmir will:
Each layer gets its own cache keys which can be expired at different times. Kashmir will also be able to fill in blanks in the dependency tree and fetch missing objects individually.
Caching is turned off by default, but you can use one of the two available implementations.
You can also build your own custom caching engine by following the NullCaching
protocol available at: https://github.com/IFTTT/kashmir/blob/master/lib/kashmir/plugins/null_caching.rb
Kashmir::Caching
In Memory
Kashmir.init(
cache_client: Kashmir::Caching::Memory.new
)
With Memcached
require 'kashmir/plugins/memcached_caching'
client = Dalli::Client.new(url, namespace: 'kashmir', compress: true)
default_ttl = 5.minutes
Kashmir.init(
cache_client: Kashmir::Caching::Memcached.new(client, default_ttl)
)
For more advanced examples, check out: https://github.com/IFTTT/kashmir/blob/master/test/caching_test.rb
git checkout -b my-new-feature
)git commit -am 'Add some feature'
)git push origin my-new-feature
)Author: IFTTT
Source code: https://github.com/IFTTT/kashmir
License: MIT license
1666024390
3D rotations made easy in Julia
This package implements various 3D rotation parameterizations and defines conversions between them. At their heart, each rotation parameterization is a 3×3 unitary (orthogonal) matrix (based on the StaticArrays.jl package), and acts to rotate a 3-vector about the origin through matrix-vector multiplication.
While the RotMatrix
type is a dense representation of a 3×3
matrix, we also have sparse (or computed, rather) representations such as quaternions, angle-axis parameterizations, and Euler angles.
For composing rotations about the origin with other transformations, see the CoordinateTransformations.jl package.
The following operations are supported by all of the implemented rotation parameterizations.
Any two rotations of the same type can be composed with simple multiplication:
q3 = q2*q1
Rotations can be composed with the opposite (or inverse) rotation with the appropriate division operation
q1 = q2\q3
q2 = q3/q1
Any rotation can operate on a 3D vector (represented as a SVector{3}
), again through simple multiplication:
r2 = q*r
which also supports multiplication by the opposite rotation
r = q\r2
The rotation angle and axis can be obtained for any rotation parameterization using
rotation_axis(r::Rotation)
rotation_angle(r::Rotation)
All rotation types support one(R)
to construct the identity rotation for the desired parameterization. A random rotation, uniformly sampled over the space of rotations, can be sampled using rand(R)
. For example:
r = one(QuatRotation) # equivalent to QuatRotation(1.0, 0.0, 0.0, 0.0)
q = rand(QuatRotation)
p = rand(MRP{Float32})
All rotatations can be converted to another parameterization by simply calling the constructor for the desired parameterization. For example:
q = rand(QuatRotation)
aa = AngleAxis(q)
r = RotMatrix(aa)
using Rotations, StaticArrays
# create the identity rotation (identity matrix)
id = one(RotMatrix{3, Float64})
# create a random rotation matrix (uniformly distributed over all 3D rotations)
r = rand(RotMatrix{3}) # uses Float64 by default
# create a point
p = SVector(1.0, 2.0, 3.0) # from StaticArrays.jl, but could use any AbstractVector...
# convert to a quaternion (QuatRotation) and rotate the point
q = QuatRotation(r)
p_rotated = q * p
# Compose rotations
q2 = rand(QuatRotation)
q3 = q * q2
# Take the inverse (equivalent to transpose)
q_inv = transpose(q)
q_inv == inv(q)
p ≈ q_inv * (q * p)
q4 = q3 / q2 # q4 = q3 * inv(q2)
q5 = q3 \ q2 # q5 = inv(q3) * q2
# convert to a Modified Rodrigues Parameter (aka Stereographic quaternion projection, recommended for applications with differentiation)
spq = MRP(r)
# convert to the Angle-axis parameterization, or related Rotation vector
aa = AngleAxis(r)
rv = RotationVec(r)
ϕ = rotation_angle(r)
v = rotation_axis(r)
# convert to Euler angles, composed of X/Y/Z axis rotations (Z applied first)
# (all combinations of "RotABC" are defined)
r_xyz = RotXYZ(r)
# Rotation about the X axis by 0.1 radians
r_x = RotX(0.1)
# Composing axis rotations together automatically results in Euler parameterization
RotX(0.1) * RotY(0.2) * RotZ(0.3) === RotXYZ(0.1, 0.2, 0.3)
# Can calculate Jacobian - derivatives of rotations with respect to parameters
j1 = Rotations.jacobian(RotMatrix, q) # How does the matrix change w.r.t the 4 Quat parameters?
j2 = Rotations.jacobian(q, p) # How does the rotated point q*p change w.r.t. the 4 Quat parameters?
# ... all Jacobian's involving RotMatrix, MRP and Quat are implemented
# (MRP is ideal for optimization purposes - no constaints/singularities)
Rotation Matrix RotMatrix{N, T}
An N×N rotation matrix storing the rotation. This is a simple wrapper for a StaticArrays SMatrix{N,N,T}
. A rotation matrix R
should have the property I = R * R'
, but this isn't enforced by the constructor. On the other hand, all the types below are guaranteed to be "proper" rotations for all input parameters (equivalently: parity conserving, in SO(3), det(r) = 1
, or a rotation without reflection).
Arbitrary Axis Rotation AngleAxis{T}
A 3D rotation with fields theta
, axis_x
, axis_y
, and axis_z
to store the rotation angle and axis of the rotation. Like all other types in this package, once it is constructed it acts and behaves as a 3×3 AbstractMatrix
. The axis will be automatically renormalized by the constructor to be a unit vector, so that theta
always represents the rotation angle in radians.
Quaternions QuatRotation{T}
A 3D rotation parameterized by a unit quaternion. Note that the constructor will renormalize the quaternion to be a unit quaternion, and that although they follow the same multiplicative algebra as quaternions, it is better to think of QuatRotation
as a 3×3 matrix rather than as a quaternion number.
Previously Quat
, UnitQuaternion
.
Rotation Vector RotationVec{T}
A 3D rotation encoded by an angle-axis representation as angle * axis
. This type is used in packages such as OpenCV.
Note: If you're differentiating a Rodrigues Vector check the result is what you expect at theta = 0. The first derivative of the rotation should behave, but higher-order derivatives of it (as well as parameterization conversions) should be tested. The Stereographic Quaternion Projection (MRP
) is the recommended three parameter format for differentiation.
Previously RodriguesVec
.
Rodrigues Parameters RodriguesParam{T}
A 3-parameter representation of 3D rotations that has a singularity at 180 degrees. They can be interpreted as a projection of the unit quaternion onto the plane tangent to the quaternion identity. They are computationally efficient and do not have a sign ambiguity.
Modified Rodrigues Parameter MRP{T}
A 3D rotation encoded by the stereographic projection of a unit quaternion. This projection can be visualized as a pin hole camera, with the pin hole matching the quaternion [-1,0,0,0]
and the image plane containing the origin and having normal direction [1,0,0,0]
. The "identity rotation" Quaternion(1.0,0,0,0)
then maps to the MRP(0,0,0)
These are similar to the Rodrigues vector in that the axis direction is stored in an unnormalized form, and the rotation angle is encoded in the length of the axis. This type has the nice property that the derivatives of the rotation matrix w.r.t. the MRP
parameters are rational functions, making the MRP
type a good choice for differentiation / optimization.
They are frequently used in aerospace applications since they are a 3-parameter representation whose singularity happens at 360 degrees. In practice, the singularity can be avoided with some switching logic between one of two equivalent MRPs (obtained by projecting the negated quaternion).
Previously SPQuat
.
Cardinal axis rotations RotX{T}
, RotY{T}
, RotZ{T}
Sparse representations of 3D rotations about the X, Y, or Z axis, respectively.
Two-axis rotations RotXY{T}
, etc
Conceptually, these are compositions of two of the cardinal axis rotations above, so that RotXY(x, y) == RotX(x) * RotY(y)
(note that the order of application to a vector is right-to-left, as-in matrix-matrix-vector multiplication: RotXY(x, y) * v == RotX(x) * (RotY(y) * v)
).
Euler Angles - Three-axis rotations RotXYZ{T}
, RotXYX{T}
, etc
A composition of 3 cardinal axis rotations is typically known as a Euler angle parameterization of a 3D rotation. The rotations with 3 unique axes, such as RotXYZ
, are said to follow the Tait Bryan angle ordering, while those which repeat (e.g. EulerXYX
) are said to use Proper Euler angle ordering.
Like the two-angle versions, the order of application to a vector is right-to-left, so that RotXYZ(x, y, z) * v == RotX(x) * (RotY(y) * (RotZ(z) * v))
. This may be interpreted as an "extrinsic" rotation about the Z, Y, and X axes or as an "intrinsic" rotation about the X, Y, and Z axes. Similarly, RotZYX(z, y, x)
may be interpreted as an "extrinsic" rotation about the X, Y, and Z axes or an "intrinsic" rotation about the Z, Y, and X axes.
It is often convenient to consider perturbations or errors about a particular 3D rotation, such as applications in state estimation or optimization-based control. Intuitively, we expect these errors to live in three-dimensional space. For globally non-singular parameterizations such as unit quaternions, we need a way to map between the four parameters of the quaternion to this three-dimensional plane tangent to the four-dimensional hypersphere on which quaternions live.
There are several of these maps provided by Rotations.jl:
ExponentialMap
: A very common mapping that uses the quaternion exponential and the quaternion logarithm. The quaternion logarithm converts a 3D rotation vector (i.e. axis-angle vector) to a unit quaternion. It tends to be the most computationally expensive mapping.
CayleyMap
: Represents the differential quaternion using Rodrigues parameters. This parameterization goes singular at 180° but does not inherit the sign ambiguities of the unit quaternion. It offers an excellent combination of cheap computation and good behavior.
MRPMap
: Uses Modified Rodrigues Parameters (MRPs) to represent the differential unit quaternion. This mapping goes singular at 360°.
QuatVecMap
: Uses the vector part of the unit quaternion as the differential unit quaternion. This mapping also goes singular at 180° but is the computationally cheapest map and often performs well.
Rotations.jl provides the RotationError
type for representing rotation errors, that act just like a SVector{3}
but carry the nonlinear map used to compute the error, which can also be used to convert the error back to a QuatRotation
(and, by extention, any other 3D rotation parameterization). The following methods are useful for computing RotationError
s and adding them back to the nominal rotation:
rotation_error(R1::Rotation, R2::Rotation, error_map::ErrorMap) # compute the error between `R1` and `R2` using `error_map`
add_error(R::Rotation, err::RotationError) # "adds" the error to `R` by converting back a `UnitQuaterion` and composing with `R`
or their aliases
R1 ⊖ R2 # caclulate the error using the default error map
R1 ⊕ err # alias for `add_error(R1, err)`
For a practical application of these ideas, see the quatenrion-multiplicative Extended Kalman Filter (MEKF). This article provides a good description.
When taking derivatives with respect to quaternions we need to account both for these mappings and the fact that local perturbations to a rotation act through composition instead of addition, as they do in vector space (e.g. q * dq
vs x + dx
). The following methods are useful for computing these Jacobians for QuatRotation
, RodriguesParam
or MRP
∇rotate(q,r)
: Jacobian of the q*r
with respect to the rotation∇composition1(q2,q1)
: Jacobian of q2*q1
with respect to q1∇composition2(q2,q1,b)
: Jacobian of q2*q1
with respect to q2∇²composition1(q2,q1)
: Jacobian of ∇composition1(q2,q2)'b
where b is an arbitrary vector∇differential(q)
: Jacobian of composing the rotation with an infinitesimal rotation, with respect to the infinitesimal rotation. For unit quaternions, this is a 4x3 matrix.∇²differential(q,b)
: Jacobian of ∇differential(q)'b
for some vector b.All parameterizations can be converted to and from (mutable or immutable) 3×3 matrices, e.g.
using StaticArrays, Rotations
# export
q = QuatRotation(1.0,0,0,0)
matrix_mutable = Array(q)
matrix_immutable = SMatrix{3,3}(q)
# import
q2 = Quaternion(matrix_mutable)
q3 = Quaternion(matrix_immutable)
This package assumes active (right handed) rotations where applicable.
They're faster (Julia's Array
and BLAS aren't great for 3×3 matrices) and don't need preallocating or garbage collection. For example, see this benchmark case where we get a 20× speedup:
julia> cd(Pkg.dir("Rotations") * "/test")
julia> include("benchmark.jl")
julia > BenchMarkRotations.benchmark_mutable()
Rotating using mutables (Base.Matrix and Base.Vector):
0.124035 seconds (2 allocations: 224 bytes)
Rotating using immutables (Rotations.RotMatrix and StaticArrays.SVector):
0.006006 seconds
Author: JuliaGeometry
Source Code: https://github.com/JuliaGeometry/Rotations.jl
License: View license
1623408615
With the advancement in technology, many products have found a dire need to showcase their product virtually and to make the virtual experience as clear as actual a technology called 3D is used. The 3D technology allows a business to showcase their products in 3 dimensions virtually.
Want to develop an app that showcases anything in 3D?
WebClues Infotech with its expertise in mobile app development can seamlessly connect a technology that has the capability to change an industry with its integration in the mobile app. After successfully serving more than 950 projects WebClues Infotech is prepared with its highly skilled development team to serve you.
Want to know more about our 3D design app development?
Visit us at
https://www.webcluesinfotech.com/3d-design-services/
Visit: https://www.webcluesinfotech.com/3d-design-services/
Share your requirements https://www.webcluesinfotech.com/contact-us/
View Portfolio https://www.webcluesinfotech.com/portfolio/
#3d design service provide #3d design services #3d modeling design services #professional 3d design services #industrial & 3d product design services #3d web design & development company
1666830000
Provides 2D and 3D vector types for vector operations in Julia.
Installation
Run one of those commands in the Julia REPL:
Through the SISL registry:
] registry add https://github.com/sisl/Registry
add Vec
Through Pkg
import Pkg
Pkg.add(PackageSpec(url="https://github.com/sisl/Vec.jl.git"))
Usage
Vec.jl
provides several vector types, named after their groups. All types are immutable and are subtypes of 'StaticArrays'' FieldVector
, so they can be indexed and used as vectors in many contexts.
VecE2
provides an (x,y) type of the Euclidean-2 group.VecE3
provides an (x,y,z) type of the Euclidean-3 group.VecSE2
provides an (x,y,theta) type of the special-Euclidean 2 group.v = VecE2(0, 1)
v = VecSE2(0,1,0.5)
v = VecE3(0, 1, 2)
Additional geometry types include Quat
for quaternions, Line
, LineSegment
, and Projectile
.
The switch to StaticArrays brings several breaking changes. If you need a backwards-compatible version, please checkout the v0.1.0
tag with cd(Pkg.dir("Vec")); run(`git checkout v0.1.0`)
.
Author: sisl
Source Code: https://github.com/sisl/Vec.jl
License: View license