mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-14 17:01:22 +00:00
68ca8c7016
According to enki (bivector community) when there are more than one null vector in a geometry, usually all vectors are null, and it was what to do with multiple null vectors that caused me to balk at using e0 for the null vector. However, using e0 for the null vector makes life much easier, especially as that's what most of the literature does. There are plenty of places, particularly in layout handling, that still need adjustment for the change, but things seem to work (minus duals, but they were broken in the first place, thus the discussion with enki).
106 lines
1.9 KiB
R
106 lines
1.9 KiB
R
#include <string.h>
|
|
#include "basisblade.h"
|
|
#include "metric.h"
|
|
#include "util.h"
|
|
|
|
@implementation BasisBlade : Object
|
|
-(BasisBlade *) initWithMask:(unsigned) mask scale:(double) scale
|
|
{
|
|
if (!(self = [super init])) {
|
|
return self;
|
|
}
|
|
self.mask = mask;
|
|
self.scale = scale;
|
|
return self;
|
|
}
|
|
|
|
+(BasisBlade *) scalar:(double) scale
|
|
{
|
|
return [[[BasisBlade alloc] initWithMask:0 scale:scale] autorelease];
|
|
}
|
|
|
|
+(BasisBlade *) zero
|
|
{
|
|
return [[[BasisBlade alloc] initWithMask:0 scale:0] autorelease];
|
|
}
|
|
|
|
+(BasisBlade *) basis:(unsigned) mask
|
|
{
|
|
return [[[BasisBlade alloc] initWithMask:mask scale:1] autorelease];
|
|
}
|
|
|
|
+(BasisBlade *) basis:(unsigned) mask scale:(double) scale
|
|
{
|
|
return [[[BasisBlade alloc] initWithMask:mask scale:scale] autorelease];
|
|
}
|
|
|
|
-(BasisBlade *) product:(BasisBlade *) b isOuter:(int)outer metric:(Metric *)m
|
|
{
|
|
if (outer && (mask & b.mask)) {
|
|
// the two blades share at least one basis vector
|
|
return [BasisBlade zero];
|
|
}
|
|
if (!scale || !b.scale) {
|
|
return [BasisBlade zero];
|
|
}
|
|
int sign = 1 - (-(count_flips (mask, b.mask) & 1) & 2);
|
|
double s = scale * b.scale * sign;
|
|
if (m) {
|
|
s *= [m apply: mask, b.mask];
|
|
if (!s) {
|
|
return [BasisBlade zero];
|
|
}
|
|
}
|
|
return [BasisBlade basis:(mask ^ b.mask) scale:s];
|
|
}
|
|
|
|
-(BasisBlade *) outerProduct:(BasisBlade *) b
|
|
{
|
|
return [self product:b isOuter:1 metric:nil];
|
|
}
|
|
|
|
-(BasisBlade *) geometricProduct:(BasisBlade *) b metric:(Metric *) m
|
|
{
|
|
return [self product:b isOuter:0 metric:m];
|
|
}
|
|
|
|
-(BasisBlade *) geometricProduct:(BasisBlade *) b
|
|
{
|
|
return [self product:b isOuter:0 metric:nil];
|
|
}
|
|
|
|
-(int) grade
|
|
{
|
|
return count_bits (mask);
|
|
}
|
|
|
|
-(unsigned) mask
|
|
{
|
|
return mask;
|
|
}
|
|
|
|
-(double) scale
|
|
{
|
|
return scale;
|
|
}
|
|
|
|
-(string) name
|
|
{
|
|
string basis = "";
|
|
|
|
for (int i = 0; i < 32; i++) {
|
|
if (mask & (1 << i)) {
|
|
basis += sprintf("%x", i);
|
|
}
|
|
}
|
|
if (basis) {
|
|
basis = "e" + basis;
|
|
}
|
|
return basis;
|
|
}
|
|
|
|
-(string) describe
|
|
{
|
|
return sprintf ("%g%s", scale, [self name]);
|
|
}
|
|
@end
|