package org.jactr.modules.pm.visual.memory.impl.filter; /* * default logging */ import java.util.Comparator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jactr.core.chunk.IChunk; import org.jactr.core.production.request.ChunkTypeRequest; import org.jactr.core.slot.IConditionalSlot; import org.jactr.modules.pm.common.memory.filter.IIndexFilter; import org.jactr.modules.pm.visual.IVisualModule; /** * provides nearest filtering and also normalizes all references to current, * highest,lowest * * @author harrison */ public class NearestVisualLocationFilter extends AbstractVisualLocationIndexFilter<Double> { /** * Logger definition */ static private final transient Log LOGGER = LogFactory .getLog(NearestVisualLocationFilter.class); private final double[] _referenceLocation; public NearestVisualLocationFilter() { _referenceLocation = new double[0]; } public NearestVisualLocationFilter(double[] referenceLocation) { _referenceLocation = new double[referenceLocation.length]; System.arraycopy(referenceLocation, 0, _referenceLocation, 0, referenceLocation.length); } @Override protected Double compute(ChunkTypeRequest request) { IChunk visualLocation = getVisualLocation(request); if (visualLocation != null) { double[] coords = getCoordinates(visualLocation); double sqDistance = 0; // length may be 2 or 3 (if depth was provided) int len = Math.min(coords.length, _referenceLocation.length); for (int i = 0; i < len; i++) sqDistance += Math.pow(coords[i] - _referenceLocation[i], 2); return sqDistance; } return null; } /* * if we've gotten this far.. */ public boolean accept(ChunkTypeRequest template) { return get(template)!=null; } public Comparator<ChunkTypeRequest> getComparator() { return new Comparator<ChunkTypeRequest>() { public int compare(ChunkTypeRequest o1, ChunkTypeRequest o2) { if (o1 == o2) return 0; Double d1 = get(o1); Double d2 = get(o2); if (d1 < d2) return -1; if (d1 > d2) return 1; return 0; } }; } public IIndexFilter instantiate(ChunkTypeRequest request) { int index = 0; double[] location = null; for (IConditionalSlot cSlot : request.getConditionalSlots()) { /* * I should do the validity test here */ index++; if (IVisualModule.NEAREST_SLOT.equals(cSlot.getName()) && cSlot.getCondition() == IConditionalSlot.EQUALS) { IChunk visualLocation = (IChunk) cSlot.getValue(); if (visualLocation != null) { location = getCoordinates(visualLocation); break; } else if (LOGGER.isWarnEnabled()) LOGGER.warn("nearest was null, ignoring"); } } if (location == null) return null; NearestVisualLocationFilter filter = new NearestVisualLocationFilter( location); filter.setWeight(index); filter.setPerceptualMemory(getVisualMemory()); return filter; } public void normalizeRequest(ChunkTypeRequest searchRequest) { IChunk currentLocation = getVisualMemory().getVisualModule() .getVisualLocationBuffer().getCurrentVisualLocation(); if (currentLocation == null) currentLocation = getVisualMemory().getVisualLocationChunkAt(0, 0); for (IConditionalSlot cSlot : searchRequest.getConditionalSlots()) { if (!(cSlot.getValue() instanceof IChunk)) continue; String chunkName = ((IChunk) cSlot.getValue()).getSymbolicChunk() .getName(); if (IVisualModule.CURRENT_CHUNK.equals(chunkName)) { /* * resolve the current chunk - but how? for all cases but one, the * conditional slot named "x" will have its value assigned to * currentLocation's slot named "x". Unless the slots name is NEAREST, * in which case the value of the conditional slot will be the current * chunk itself */ if (IVisualModule.NEAREST_SLOT.equals(cSlot.getName())) cSlot.setValue(currentLocation); else cSlot.setValue(currentLocation.getSymbolicChunk().getSlot( cSlot.getName()).getValue()); } else if (IVisualModule.LESS_THAN_CURRENT_CHUNK.equals(chunkName)) { cSlot.setCondition(IConditionalSlot.LESS_THAN); cSlot.setValue(currentLocation.getSymbolicChunk().getSlot( cSlot.getName()).getValue()); } else if (IVisualModule.GREATER_THAN_CURRENT_CHUNK.equals(chunkName)) { cSlot.setCondition(IConditionalSlot.GREATER_THAN); cSlot.setValue(currentLocation.getSymbolicChunk().getSlot( cSlot.getName()).getValue()); } } } }