You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

334 lines
7.0 KiB

/**
Copyright (c) 2014-present, Facebook, Inc.
All rights reserved.
This source code is licensed under the BSD-style license found in the
LICENSE file in the root directory of this source tree. An additional grant
of patent rights can be found in the PATENTS file in the same directory.
*/
#import "POPVector.h"
#import "POPDefines.h"
#import "POPCGUtils.h"
namespace POP
{
Vector::Vector(const size_t count)
{
_count = count;
_values = 0 != count ? (CGFloat *)calloc(count, sizeof(CGFloat)) : NULL;
}
Vector::Vector(const Vector& other)
{
_count = other.size();
_values = 0 != _count ? (CGFloat *)calloc(_count, sizeof(CGFloat)) : NULL;
if (0 != _count) {
memcpy(_values, other.data(), _count * sizeof(CGFloat));
}
}
Vector::~Vector()
{
if (NULL != _values) {
free(_values);
_values = NULL;
}
_count = 0;
}
void Vector::swap(Vector &first, Vector &second)
{
using std::swap;
swap(first._count, second._count);
swap(first._values, second._values);
}
Vector& Vector::operator=(const Vector& other)
{
Vector temp(other);
swap(*this, temp);
return *this;
}
bool Vector::operator==(const Vector &other) const {
if (_count != other.size()) {
return false;
}
const CGFloat * const values = other.data();
for (NSUInteger idx = 0; idx < _count; idx++) {
if (_values[idx] != values[idx]) {
return false;
}
}
return true;
}
bool Vector::operator!=(const Vector &other) const {
if (_count == other.size()) {
return false;
}
const CGFloat * const values = other.data();
for (NSUInteger idx = 0; idx < _count; idx++) {
if (_values[idx] != values[idx]) {
return false;
}
}
return true;
}
Vector *Vector::new_vector(NSUInteger count, const CGFloat *values)
{
if (0 == count) {
return NULL;
}
Vector *v = new Vector(count);
if (NULL != values) {
memcpy(v->_values, values, count * sizeof(CGFloat));
}
return v;
}
Vector *Vector::new_vector(const Vector * const other)
{
if (NULL == other) {
return NULL;
}
return Vector::new_vector(other->size(), other->data());
}
Vector *Vector::new_vector(NSUInteger count, Vector4r vec)
{
if (0 == count) {
return NULL;
}
Vector *v = new Vector(count);
NSCAssert(count <= 4, @"unexpected count %lu", (unsigned long)count);
for (NSUInteger i = 0; i < MIN(count, (NSUInteger)4); i++) {
v->_values[i] = vec[i];
}
return v;
}
Vector4r Vector::vector4r() const
{
Vector4r v = Vector4r::Zero();
for (size_t i = 0; i < _count; i++) {
v(i) = _values[i];
}
return v;
}
Vector2r Vector::vector2r() const
{
Vector2r v = Vector2r::Zero();
if (_count > 0) v(0) = _values[0];
if (_count > 1) v(1) = _values[1];
return v;
}
Vector *Vector::new_cg_float(CGFloat f)
{
Vector *v = new Vector(1);
v->_values[0] = f;
return v;
}
CGPoint Vector::cg_point () const
{
Vector2r v = vector2r();
return CGPointMake(v(0), v(1));
}
Vector *Vector::new_cg_point(const CGPoint &p)
{
Vector *v = new Vector(2);
v->_values[0] = p.x;
v->_values[1] = p.y;
return v;
}
CGSize Vector::cg_size () const
{
Vector2r v = vector2r();
return CGSizeMake(v(0), v(1));
}
Vector *Vector::new_cg_size(const CGSize &s)
{
Vector *v = new Vector(2);
v->_values[0] = s.width;
v->_values[1] = s.height;
return v;
}
CGRect Vector::cg_rect() const
{
return _count < 4 ? CGRectZero : CGRectMake(_values[0], _values[1], _values[2], _values[3]);
}
Vector *Vector::new_cg_rect(const CGRect &r)
{
Vector *v = new Vector(4);
v->_values[0] = r.origin.x;
v->_values[1] = r.origin.y;
v->_values[2] = r.size.width;
v->_values[3] = r.size.height;
return v;
}
#if TARGET_OS_IPHONE
UIEdgeInsets Vector::ui_edge_insets() const
{
return _count < 4 ? UIEdgeInsetsZero : UIEdgeInsetsMake(_values[0], _values[1], _values[2], _values[3]);
}
Vector *Vector::new_ui_edge_insets(const UIEdgeInsets &i)
{
Vector *v = new Vector(4);
v->_values[0] = i.top;
v->_values[1] = i.left;
v->_values[2] = i.bottom;
v->_values[3] = i.right;
return v;
}
#endif
CGAffineTransform Vector::cg_affine_transform() const
{
if (_count < 6) {
return CGAffineTransformIdentity;
}
NSCAssert(size() >= 6, @"unexpected vector size:%lu", (unsigned long)size());
CGAffineTransform t;
t.a = _values[0];
t.b = _values[1];
t.c = _values[2];
t.d = _values[3];
t.tx = _values[4];
t.ty = _values[5];
return t;
}
Vector *Vector::new_cg_affine_transform(const CGAffineTransform &t)
{
Vector *v = new Vector(6);
v->_values[0] = t.a;
v->_values[1] = t.b;
v->_values[2] = t.c;
v->_values[3] = t.d;
v->_values[4] = t.tx;
v->_values[5] = t.ty;
return v;
}
CGColorRef Vector::cg_color() const
{
if (_count < 4) {
return NULL;
}
return POPCGColorRGBACreate(_values);
}
Vector *Vector::new_cg_color(CGColorRef color)
{
CGFloat rgba[4];
POPCGColorGetRGBAComponents(color, rgba);
return new_vector(4, rgba);
}
#if SCENEKIT_SDK_AVAILABLE
SCNVector3 Vector::scn_vector3() const
{
return _count < 3 ? SCNVector3Make(0.0, 0.0, 0.0) : SCNVector3Make(_values[0], _values[1], _values[2]);
}
Vector *Vector::new_scn_vector3(const SCNVector3 &vec3)
{
Vector *v = new Vector(3);
v->_values[0] = vec3.x;
v->_values[1] = vec3.y;
v->_values[2] = vec3.z;
return v;
}
SCNVector4 Vector::scn_vector4() const
{
return _count < 4 ? SCNVector4Make(0.0, 0.0, 0.0, 0.0) : SCNVector4Make(_values[0], _values[1], _values[2], _values[3]);
}
Vector *Vector::new_scn_vector4(const SCNVector4 &vec4)
{
Vector *v = new Vector(4);
v->_values[0] = vec4.x;
v->_values[1] = vec4.y;
v->_values[2] = vec4.z;
v->_values[3] = vec4.w;
return v;
}
#endif
void Vector::subRound(CGFloat sub)
{
for (NSUInteger idx = 0; idx < _count; idx++) {
_values[idx] = POPSubRound(_values[idx], sub);
}
}
CGFloat Vector::norm() const
{
return sqrtr(squaredNorm());
}
CGFloat Vector::squaredNorm() const
{
CGFloat d = 0;
for (NSUInteger idx = 0; idx < _count; idx++) {
d += (_values[idx] * _values[idx]);
}
return d;
}
NSString * Vector::toString() const
{
if (0 == _count)
return @"()";
if (1 == _count)
return [NSString stringWithFormat:@"%f", _values[0]];
if (2 == _count)
return [NSString stringWithFormat:@"(%.3f, %.3f)", _values[0], _values[1]];
NSMutableString *s = [NSMutableString stringWithCapacity:10];
for (NSUInteger idx = 0; idx < _count; idx++) {
if (0 == idx) {
[s appendFormat:@"[%.3f", _values[idx]];
} else if (idx == _count - 1) {
[s appendFormat:@", %.3f]", _values[idx]];
} else {
[s appendFormat:@", %.3f", _values[idx]];
}
}
return s;
}
}