Commit 76bbe956 authored by Dipl.-Ing. Jonas Stienen's avatar Dipl.-Ing. Jonas Stienen
Browse files

Fixing problems with ita_diffraction_shadow_zone

parent 2a7f3f2d
function in_shadow = ita_diffraction_shadow_zone( wedge, sourcePos, receiverPos )
function in_shadow = ita_diffraction_shadow_zone( wedge, source_pos, receiver_pos )
%ITA_DIFFRACTION_SHADOW_ZONE Returns true if receiver is, from the source's
%point of view, covered by the wedge and therefor inside the shadow region
%% assertions
if ~numel( sourcePos ) == 3
if ~numel( source_pos ) == 3
error( 'Source point must be of dimension 3')
end
if ~numel( receiverPos )
if ~numel( receiver_pos )
error( 'Receiver point must be of dimension 3')
end
if ~wedge.point_outside_wedge( sourcePos )
if ~wedge.point_outside_wedge( source_pos )
error( 'Source point must be outside of wedge' )
end
if ~wedge.point_outside_wedge( receiverPos )
if ~wedge.point_outside_wedge( receiver_pos )
error( 'Receiver point must be outside of wedge' )
end
%% Set variables
apexPoint = wedge.get_aperture_point( sourcePos, receiverPos ); % point on aperture which is on shortest connection of source and receiver across the aperture
referenceFaceIsMainFace = ~wedge.point_facing_main_side( sourcePos ); % true if main wedge face is starting point for every angle measure from face into the room
% choose coordinate system of face normals and aperture direction according
% to source facing wedge face resulting in a clockwise rotation system
if referenceFaceIsMainFace
mainWedgeFaceNormal = wedge.main_face_normal;
oppositeWedgeFaceNormal = wedge.opposite_face_normal;
apexDir = wedge.aperture_direction;
else
mainWedgeFaceNormal = wedge.opposite_face_normal;
oppositeWedgeFaceNormal = wedge.main_face_normal;
apexDir = -wedge.aperture_direction;
end
% Use auxiliary shadow plane defined by aperture and source position -> border of the shadow zone
sourceApexDirection = ( apexPoint - sourcePos ) ./ norm( apexPoint - sourcePos ) ;
%% Validations
% Define shadow plane normal always pointing away from the wedge
shadowPlaneNormal = -cross( sourceApexDirection, apexDir ) ./ norm( cross( sourceApexDirection, apexDir ) );
% Inner edges can't create shadow zones
if isa( wedge, 'itaInfiniteWedge' )
if strcmpi( wedge.edge_type, 'inner_edge' )
in_shadow = false;
return
end
end
% Distances from source position to each wedge face
distFromSrc2MainFace = dot( sourcePos - apexPoint, mainWedgeFaceNormal );
distFromSrc2OppositeFace = dot( sourcePos - apexPoint, oppositeWedgeFaceNormal );
source_pos_above_main_plane = dot( wedge.main_face_normal, source_pos - wedge.location ) >= 0;
source_pos_above_opposite_plane = dot( wedge.opposite_face_normal, source_pos - wedge.location ) >= 0;
% Check if source position is above wedge facing both wedge faces
sourceFacingBothWedgeFaces = distFromSrc2MainFace >= -wedge.set_get_geo_eps && distFromSrc2OppositeFace >= -wedge.set_get_geo_eps;
receiver_pos_above_main_face = dot( wedge.main_face_normal, receiver_pos - wedge.location ) >= 0;
receiver_pos_above_opposite_face = dot( wedge.opposite_face_normal, receiver_pos - wedge.location ) >= 0;
if source_pos_above_main_plane && receiver_pos_above_main_face
in_shadow = false;
return
end
%% Consider different cases
if sourceFacingBothWedgeFaces
% no shadow region possible
if source_pos_above_opposite_plane && receiver_pos_above_opposite_face
in_shadow = false;
else
% shadow region exists
distFromRcv2ShadowPlane = dot( receiverPos - apexPoint, shadowPlaneNormal );
distFromRcv2MainFace = dot( receiverPos -apexPoint, mainWedgeFaceNormal );
return
end
rcvInFrontOfMainFace = distFromRcv2MainFace >= -wedge.set_get_geo_eps;
rcvAboveShadowPlane = distFromRcv2ShadowPlane >= -wedge.set_get_geo_eps;
% Only cases left: one of source / receiver is above main and other below
% opposite face plane
if rcvAboveShadowPlane || rcvInFrontOfMainFace
if source_pos_above_main_plane
source_shadow_boundary_plane_dir = cross( wedge.aperture_direction, source_pos - wedge.location );
source_shadow_boundary_plane_normal = source_shadow_boundary_plane_dir / norm( source_shadow_boundary_plane_dir );
if dot( source_shadow_boundary_plane_normal, receiver_pos - source_pos ) >= 0
in_shadow = false;
else
in_shadow = true;
end
return
end
if source_pos_above_opposite_plane
source_shadow_boundary_plane_dir = cross( wedge.aperture_direction, source_pos - wedge.location );
source_shadow_boundary_plane_normal = source_shadow_boundary_plane_dir / norm( source_shadow_boundary_plane_dir );
if dot( source_shadow_boundary_plane_normal, receiver_pos - source_pos ) >= 0
in_shadow = true;
else
in_shadow = false;
end
return
end
assert( false ) % We should have a decision and used a return directive until this line
end
%% Init scene
% infite wedge
wdgNormal_1 = [1, 1, 0];
wdgNormal_2 = [-1, 1, 0];
wdgLoc = [0 0 2];
infWdg = itaInfiniteWedge(wdgNormal_1 / norm( wdgNormal_1 ), wdgNormal_2 / norm( wdgNormal_2 ), wdgLoc);
%% Shadow zone test
% screen
screenNormal_1 = [ 1, 0, 0];
screenNormal_2 = [-1, 0, 0];
screenLoc = wdgLoc;
screenApexDir = [0, 0, 1];
infScreen = itaSemiInfinitePlane(screenNormal_1, screenNormal_2, screenLoc);
n1 = [ 1, 1, 0 ] / sqrt( 2 );
n2 = [ -1, 1, 0 ] / sqrt( 2 );
loc = [ 0 0 0 ];
wedge = itaInfiniteWedge( n1, n2, loc, 'outer_edge' );
screen = itaSemiInfinitePlane( [ 1 0 0 ], loc, [ 0 0 1 ] );
% source
srcPosFacingMainSide = 3/sqrt(1) * [ 1, 0, 0];
srcPosFacingOppositeSide = 3/sqrt(1) * [-1, 0, 0];
srcPosFacingBothSides = 3/sqrt(1) * [ 0, 1, 0];
source = [ 1 -0.001 0 ];
receiver = [ -1 -0.001 0 ];
% receiver
rcvStartPos = 3/sqrt(2) * [ 1, -1, 0];
rcvEndPos = 3/sqrt(2) * [-1, -1, 0];
numOfRcvPositions = 100; % set number of receiver to be aligned around the aperture
assert( ita_diffraction_shadow_zone( wedge, source, receiver ) )
assert( ita_diffraction_shadow_zone( wedge, receiver, source ) )
assert( ita_diffraction_shadow_zone( screen, source, receiver ) )
assert( ita_diffraction_shadow_zone( screen, receiver, source ) )
% Discard boundary positions to avoid numerical inaccuracies (reasonable if these positions are on the wedge face)
discardRcvStartPos = true;
discardRcvEndPos = true;
assert( ~ita_diffraction_shadow_zone( wedge, source, source ) )
assert( ~ita_diffraction_shadow_zone( wedge, receiver, receiver ) )
assert( ~ita_diffraction_shadow_zone( screen, source, source ) )
assert( ~ita_diffraction_shadow_zone( screen, receiver, receiver ) )
%% Align receivers around aperture
apexPoint = infWdg.get_aperture_point(srcPosFacingMainSide, rcvStartPos);
referencFaceIsMainSide = infWdg.point_facing_main_side( srcPosFacingOppositeSide );
source = [ 1 +0.001 0 ];
receiver = [ -1 +0.001 0 ];
rcvPosAngleStart = infWdg.get_angle_from_point_to_wedge_face(rcvStartPos, referencFaceIsMainSide);
rcvPosAngleEnd = infWdg.get_angle_from_point_to_wedge_face(rcvEndPos, referencFaceIsMainSide);
rcvAnglesFromRefFace = linspace( rcvPosAngleStart, rcvPosAngleEnd, numOfRcvPositions );
assert( ~ita_diffraction_shadow_zone( wedge, source, receiver ) )
assert( ~ita_diffraction_shadow_zone( wedge, receiver, source ) )
assert( ~ita_diffraction_shadow_zone( screen, receiver, source ) )
assert( ~ita_diffraction_shadow_zone( screen, source, receiver ) )
% Set different receiver positions rotated around the aperture
rcvPositions = ita_align_points_around_aperture( infWdg, rcvStartPos, rcvAnglesFromRefFace, apexPoint, referencFaceIsMainSide );
% Avoid first and last receiver position if wanted
if discardRcvStartPos
rcvPositions = rcvPositions(2:end, :);
end
if discardRcvEndPos
rcvPositions = rcvPositions(1:end-1, :);
end
numOfRcvPositions = size(rcvPositions, 1); % update number of receiver positions
%% Calculations
inShadowZone_SrcFacingMainSide = false(numOfRcvPositions, 1);
inShadowZone_SrcFacingOppSide = false(numOfRcvPositions, 1);
inShadowZone_SrcFacingBothSides = false(numOfRcvPositions, 1);
% Case1: source is facing wedge main face
for i = 1 : numOfRcvPositions
inShadowZone_SrcFacingMainSide(i) = ita_diffraction_shadow_zone( infWdg, srcPosFacingMainSide, rcvPositions(i, :) );
end
% Case2: source is face wegde opposite face
for i = 1 : numOfRcvPositions
inShadowZone_SrcFacingOppSide(i) = ita_diffraction_shadow_zone( infWdg, srcPosFacingOppositeSide, rcvPositions(i, :) );
end
% Case3: sourc is faceing both wedge sides -> loacted above wedge
for i = 1 : numOfRcvPositions
inShadowZone_SrcFacingBothSides(i) = ita_diffraction_shadow_zone( infWdg, srcPosFacingBothSides, rcvPositions(i, :) );
end
assert( ~ita_diffraction_shadow_zone( wedge, source, source ) )
assert( ~ita_diffraction_shadow_zone( wedge, receiver, receiver ) )
assert( ~ita_diffraction_shadow_zone( screen, source, source ) )
assert( ~ita_diffraction_shadow_zone( screen, receiver, receiver ) )
disp 'Shadow zone test successfull'
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment