Получение отдельных пикселей из точки касания

Можно ли обнаружить каждый затронутый пиксель? Более конкретно, когда пользователь касается экрана, возможно ли отследить все координаты x-y кластера точек, которых коснулся пользователь? Как определить разницу между тем, когда пользователи рисуют большим пальцем, и когда они рисуют кончиком пальца? Я хотел бы отразить разницу в кистях в зависимости от того, как пользователи касаются экрана, а также хотел бы отслеживать все затрагиваемые пиксели.

В настоящее время я использую следующие коды из образца GLPaint с сайта разработчиков Apple:

http://developer.apple.com/library/ios/#samplecode/GLPaint/Introduction/Intro.html

Примеры кодов позволяют рисовать с помощью заранее заданного размера кисти и отслеживать координаты x-y на этом пути. Как я могу изменить кисть в зависимости от того, как пользователи касаются экрана, и отслеживать все пиксели, к которым прикасаются, с течением времени?

// Drawings a line onscreen based on where the user touches

- (void) renderLineFromPoint:(CGPoint)start toPoint:(CGPoint)end

{
     NSLog(@"x:%f   y:%f",start.x, start.y);

     static GLfloat*          vertexBuffer = NULL;

     static NSUInteger     vertexMax = 64;

     NSUInteger               vertexCount = 0,

                    count,

                    i;



     [EAGLContext setCurrentContext:context];

     glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);



     // Convert locations from Points to Pixels

     CGFloat scale = self.contentScaleFactor;

     start.x *= scale;

     start.y *= scale;

     end.x *= scale;

     end.y *= scale;



     // Allocate vertex array buffer

     if(vertexBuffer == NULL)

          vertexBuffer = malloc(vertexMax * 2 * sizeof(GLfloat));



     // Add points to the buffer so there are drawing points every X pixels

     count = MAX(ceilf(sqrtf((end.x - start.x) * (end.x - start.x) + (end.y - start.y) * (end.y - start.y)) / kBrushPixelStep), 1);

     for(i = 0; i < count; ++i) {

          if(vertexCount == vertexMax) {

               vertexMax = 2 * vertexMax;

               vertexBuffer = realloc(vertexBuffer, vertexMax * 2 * sizeof(GLfloat));

          }



          vertexBuffer[2 * vertexCount + 0] = start.x + (end.x - start.x) * ((GLfloat)i / (GLfloat)count);

          vertexBuffer[2 * vertexCount + 1] = start.y + (end.y - start.y) * ((GLfloat)i / (GLfloat)count);

          vertexCount += 1;

     }



     // Render the vertex array

     glVertexPointer(2, GL_FLOAT, 0, vertexBuffer);

     glDrawArrays(GL_POINTS, 0, vertexCount);



     // Display the buffer

     glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);

     [context presentRenderbuffer:GL_RENDERBUFFER_OES];

}


// Handles the start of a touch

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

{

     CGRect                    bounds = [self bounds];

     UITouch*     touch = [[event touchesForView:self] anyObject];

     firstTouch = YES;

     // Convert touch point from UIView referential to OpenGL one (upside-down flip)

     location = [touch locationInView:self];

     location.y = bounds.size.height - location.y;

}

// Handles the continuation of a touch.

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

{  

     CGRect                    bounds = [self bounds];

     UITouch*               touch = [[event touchesForView:self] anyObject];



     // Convert touch point from UIView referential to OpenGL one (upside-down flip)

     if (firstTouch) {

          firstTouch = NO;

          previousLocation = [touch previousLocationInView:self];

          previousLocation.y = bounds.size.height - previousLocation.y;

     } else {

          location = [touch locationInView:self];

         location.y = bounds.size.height - location.y;

          previousLocation = [touch previousLocationInView:self];

          previousLocation.y = bounds.size.height - previousLocation.y;

     }



     // Render the stroke

     [self renderLineFromPoint:previousLocation toPoint:location];

}



// Handles the end of a touch event when the touch is a tap.

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

{

     CGRect                    bounds = [self bounds];

    UITouch*     touch = [[event touchesForView:self] anyObject];

     if (firstTouch) {

          firstTouch = NO;

          previousLocation = [touch previousLocationInView:self];

          previousLocation.y = bounds.size.height - previousLocation.y;

          [self renderLineFromPoint:previousLocation toPoint:location];

     }

}


// Handles the end of a touch event.

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event

{

     // If appropriate, add code necessary to save the state of the application.

     // This application is not saving state.

}

person HappyAppDeveloper    schedule 04.04.2012    source источник


Ответы (2)


AFAIK нет API для доступа к сенсорной зоне для прикосновения. Я даже не уверен, учитывая ограничения емкостного сенсорного экрана, возможно ли то, что вы хотите, физически. Я вспоминаю презентацию на недавней конференции Cocoa Heads, где было продемонстрировано, что некоторая информация доступна в OS X (через частный API) для трекпадов, но не для iOS.

Я считаю, что это одна из причин, по которой графические планшеты используют специальные стилусы, в которые встроена собственная сенсорная технология.

Частичным обходным решением для приложения для рисования может быть имитация «рисования», как это делают некоторые настольные приложения: если пользовательское прикосновение задерживается в заданном месте, рисуйте так, как если бы чернила выходили из «пера» и постепенно распространялись через «перо». бумага."

person Conrad Shultz    schedule 04.04.2012
comment
Спасибо большое за Ваш ответ. Вы знаете, возможно ли это на Android? - person HappyAppDeveloper; 04.04.2012
comment
Понятия не имею, извините, я не разрабатываю для Android. Я уверен, что у других будет ответ. Если вы ничего не можете найти в поиске, я предлагаю опубликовать новый вопрос с пометкой Android. - person Conrad Shultz; 04.04.2012

Оборудование Broadcomm в iPad сканирует экран с частотой 64 Гц. Он делает это, подавая сигнал последовательно в течение 400 мкс каждый на 39 прозрачных проводящих слоев, которые составляют электроды сенсорного экрана. Если ваш палец перемещается более чем на один пиксель в течение 0,015625 секунды, что вполне вероятно, аппаратное обеспечение не может обнаружить это, потому что оно занято измерением других частей экрана для большего количества событий касания.

Это то же самое независимо от iOS или Android. Дешевые планшеты Android и большие экраны имеют пониженную скорость сканирования, поэтому их события касания еще более разнесены.

На планшете Wacom дигитайзер работает на частоте 100 Гц, поэтому последовательность точек будет более точной, но все равно будут отсутствовать те пиксели, которых касается стилус между двумя измерениями.

person Peter Kämpf    schedule 29.07.2014